From c27c2320574902117b1c2e66f210640eb606a736 Mon Sep 17 00:00:00 2001 From: George Joseph Date: Fri, 27 May 2016 13:49:42 -0600 Subject: ari/resource_channels: Add 'formats' to channel create/originate If you create a local channel and don't specify an originator channel to take capabilities from, we automatically add all audio formats to the new channel's capabilities. When we try to make the channel compatible with another, the "best format" functions pick the best format available, which in this case will be slin192. While this is great for preserving quality, it's the worst for performance and overkill for the vast majority of applications. In the absense of any other information, adding all formats is the correct thing to do and it's not always possible to supply an originator so a new parameter 'formats' has been added to the channel create/originate functions. It's just a comma separated list of formats to make availalble for the channel. Example: "ulaw,slin,slin16". 'formats' and 'originator' are mutually exclusive. To facilitate determination of format names, the format name has been added to "core show codecs". ASTERISK-26070 #close Change-Id: I091b23ecd41c1b4128d85028209772ee139f604b --- res/ari/resource_channels.c | 47 ++++++++++++++++++++++++++++++++++++++++++++- res/ari/resource_channels.h | 4 ++++ res/res_ari_channels.c | 14 ++++++++++++++ 3 files changed, 64 insertions(+), 1 deletion(-) (limited to 'res') diff --git a/res/ari/resource_channels.c b/res/ari/resource_channels.c index 9e2db9de6..6baac7a4e 100644 --- a/res/ari/resource_channels.c +++ b/res/ari/resource_channels.c @@ -912,6 +912,7 @@ static void ari_channels_handle_originate_with_id(const char *args_endpoint, const char *args_channel_id, const char *args_other_channel_id, const char *args_originator, + const char *args_formats, struct ast_ari_response *response) { char *dialtech; @@ -930,6 +931,7 @@ static void ari_channels_handle_originate_with_id(const char *args_endpoint, }; struct ari_origination *origination; pthread_t thread; + struct ast_format_cap *format_cap = NULL; if ((assignedids.uniqueid && AST_MAX_PUBLIC_UNIQUEID < strlen(assignedids.uniqueid)) || (assignedids.uniqueid2 && AST_MAX_PUBLIC_UNIQUEID < strlen(assignedids.uniqueid2))) { @@ -944,6 +946,12 @@ static void ari_channels_handle_originate_with_id(const char *args_endpoint, return; } + if (!ast_strlen_zero(args_originator) && !ast_strlen_zero(args_formats)) { + ast_ari_response_error(response, 400, "Bad Request", + "Originator and formats can't both be specified"); + return; + } + dialtech = ast_strdupa(args_endpoint); if ((stuff = strchr(dialtech, '/'))) { *stuff++ = '\0'; @@ -1066,7 +1074,41 @@ static void ari_channels_handle_originate_with_id(const char *args_endpoint, } } - if (ast_dial_prerun(dial, other, NULL)) { + if (!ast_strlen_zero(args_formats)) { + char *format_name; + char *formats_copy = ast_strdupa(args_formats); + + if (!(format_cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT))) { + ast_ari_response_alloc_failed(response); + ast_dial_destroy(dial); + ast_free(origination); + ast_channel_cleanup(other); + return; + } + + while ((format_name = ast_strip(strsep(&formats_copy, ",")))) { + struct ast_format *fmt = ast_format_cache_get(format_name); + + if (!fmt || ast_format_cap_append(format_cap, fmt, 0)) { + if (!fmt) { + ast_ari_response_error( + response, 400, "Bad Request", + "Provided format (%s) was not found", format_name); + } else { + ast_ari_response_alloc_failed(response); + } + ast_dial_destroy(dial); + ast_free(origination); + ast_channel_cleanup(other); + ao2_ref(format_cap, -1); + ao2_cleanup(fmt); + return; + } + ao2_ref(fmt, -1); + } + } + + if (ast_dial_prerun(dial, other, format_cap)) { ast_ari_response_alloc_failed(response); ast_dial_destroy(dial); ast_free(origination); @@ -1075,6 +1117,7 @@ static void ari_channels_handle_originate_with_id(const char *args_endpoint, } ast_channel_cleanup(other); + ao2_cleanup(format_cap); chan = ast_dial_get_channel(dial, 0); if (!chan) { @@ -1215,6 +1258,7 @@ void ast_ari_channels_originate_with_id(struct ast_variable *headers, args->channel_id, args->other_channel_id, args->originator, + args->formats, response); ast_variables_destroy(variables); } @@ -1251,6 +1295,7 @@ void ast_ari_channels_originate(struct ast_variable *headers, args->channel_id, args->other_channel_id, args->originator, + args->formats, response); ast_variables_destroy(variables); } diff --git a/res/ari/resource_channels.h b/res/ari/resource_channels.h index 4d3ad5f8b..5bb6f7f1e 100644 --- a/res/ari/resource_channels.h +++ b/res/ari/resource_channels.h @@ -78,6 +78,8 @@ struct ast_ari_channels_originate_args { const char *other_channel_id; /*! The unique id of the channel which is originating this one. */ const char *originator; + /*! The format name capability list to use if originator is not specified. Ex. "ulaw,slin16". Format names an be found with "core show codecs". */ + const char *formats; }; /*! * \brief Body parsing function for /channels. @@ -141,6 +143,8 @@ struct ast_ari_channels_originate_with_id_args { const char *other_channel_id; /*! The unique id of the channel which is originating this one. */ const char *originator; + /*! The format name capability list to use if originator is not specified. Ex. "ulaw,slin16". Format names an be found with "core show codecs". */ + const char *formats; }; /*! * \brief Body parsing function for /channels/{channelId}. diff --git a/res/res_ari_channels.c b/res/res_ari_channels.c index d1ae80196..a14a9c8cb 100644 --- a/res/res_ari_channels.c +++ b/res/res_ari_channels.c @@ -157,6 +157,10 @@ int ast_ari_channels_originate_parse_body( if (field) { args->originator = ast_json_string_get(field); } + field = ast_json_object_get(body, "formats"); + if (field) { + args->formats = ast_json_string_get(field); + } return 0; } @@ -217,6 +221,9 @@ static void ast_ari_channels_originate_cb( if (strcmp(i->name, "originator") == 0) { args.originator = (i->value); } else + if (strcmp(i->name, "formats") == 0) { + args.formats = (i->value); + } else {} } /* Look for a JSON request entity */ @@ -377,6 +384,10 @@ int ast_ari_channels_originate_with_id_parse_body( if (field) { args->originator = ast_json_string_get(field); } + field = ast_json_object_get(body, "formats"); + if (field) { + args->formats = ast_json_string_get(field); + } return 0; } @@ -434,6 +445,9 @@ static void ast_ari_channels_originate_with_id_cb( if (strcmp(i->name, "originator") == 0) { args.originator = (i->value); } else + if (strcmp(i->name, "formats") == 0) { + args.formats = (i->value); + } else {} } for (i = path_vars; i; i = i->next) { -- cgit v1.2.3