]> git.ipfire.org Git - thirdparty/asterisk.git/commitdiff
ari/resource_channels: Add 'formats' to channel create/originate 17/2917/3
authorGeorge Joseph <gjoseph@digium.com>
Fri, 27 May 2016 19:49:42 +0000 (13:49 -0600)
committerGeorge Joseph <gjoseph@digium.com>
Fri, 3 Jun 2016 22:31:39 +0000 (17:31 -0500)
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

CHANGES
include/asterisk/codec.h
main/codec.c
main/codec_builtin.c
res/ari/resource_channels.c
res/ari/resource_channels.h
res/res_ari_channels.c
rest-api/api-docs/channels.json

diff --git a/CHANGES b/CHANGES
index 890b3afb355062e9ed73db6ba8c5e56df1cc0abf..912dc7f739d7bcd2fb635819f21a9641ec131a2d 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -71,6 +71,18 @@ app_confbridge
    server installations via alternate means (DUNDI for example). By default
    this feature is not used.
 
+Codecs
+------------------
+ * Added the associated format name to 'core show codecs'.
+
+res_ari_channels
+------------------
+ * Added 'formats' to channel create/originate to allow setting the allowed
+   formats for a channel when no originator channel is available.  Especially
+   useful for Local channel creation where no other format information is
+   available.  'core show codecs' can now be used to look up suitable format
+   names.
+
 ------------------------------------------------------------------------------
 --- Functionality changes from Asterisk 13.8.0 to Asterisk 13.9.0 ------------
 ------------------------------------------------------------------------------
index 28befec50cbe10dfdbe7c392fd68685100d54995..fb2b7da38baeee3e7939a551b458ea9a625949d0 100644 (file)
@@ -77,6 +77,8 @@ struct ast_codec {
        unsigned int smooth;
        /*! \brief The module that registered this codec */
        struct ast_module *mod;
+       /*! \brief A format name for a default sane format using this codec */
+       const char *format_name;
 };
 
 /*!
index 543d4d0bde6dc9e8df51cace5d546dbe06c59926..c8644fd34a6a336b9f47b7f07b5b67ded8f28478 100644 (file)
@@ -135,8 +135,8 @@ static char *show_codecs(struct ast_cli_entry *e, int cmd, struct ast_cli_args *
                                "\tIt does not indicate anything about your configuration.\n");
        }
 
-       ast_cli(a->fd, "%8s %5s %8s %s\n","ID","TYPE","NAME","DESCRIPTION");
-       ast_cli(a->fd, "-----------------------------------------------------------------------------------\n");
+       ast_cli(a->fd, "%8s %-5s %-12s %-16s %s\n","ID","TYPE","NAME","FORMAT","DESCRIPTION");
+       ast_cli(a->fd, "------------------------------------------------------------------------------------------------\n");
 
        ao2_rdlock(codecs);
        i = ao2_iterator_init(codecs, AO2_ITERATOR_DONTLOCK);
@@ -164,10 +164,11 @@ static char *show_codecs(struct ast_cli_entry *e, int cmd, struct ast_cli_args *
                        }
                }
 
-               ast_cli(a->fd, "%8u %5s %8s (%s)\n",
+               ast_cli(a->fd, "%8u %-5s %-12s %-16s (%s)\n",
                        codec->id,
                        ast_codec_media_type2str(codec->type),
                        codec->name,
+                       S_OR(codec->format_name, "no cached format"),
                        codec->description);
        }
 
@@ -216,7 +217,8 @@ static char *show_codec(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a
                return CLI_SUCCESS;
        }
 
-       ast_cli(a->fd, "%11u %s\n", (unsigned int) codec->id, codec->description);
+       ast_cli(a->fd, "%11u %s (%s)\n", (unsigned int) codec->id, codec->description,
+               S_OR(codec->format_name, "no format"));
 
        ao2_ref(codec, -1);
 
index 346b47b8798b8b7703515b3daabdea89f6dbec26..d7d253ab8d05de662df3db005e67a026f2b2f16f 100644 (file)
@@ -774,6 +774,7 @@ static struct ast_codec t140 = {
                int __res_ ## __LINE__ = 0; \
                struct ast_format *__fmt_ ## __LINE__; \
                struct ast_codec *__codec_ ## __LINE__; \
+               codec.format_name = (codec).name; \
                res |= __ast_codec_register(&(codec), NULL); \
                __codec_ ## __LINE__ = ast_codec_get((codec).name, (codec).type, (codec).sample_rate); \
                __fmt_ ## __LINE__ = __codec_ ## __LINE__ ? ast_format_create(__codec_ ## __LINE__) : NULL; \
@@ -783,14 +784,15 @@ static struct ast_codec t140 = {
                __res_ ## __LINE__; \
        })
 
-#define CODEC_REGISTER_AND_CACHE_NAMED(format_name, codec) \
+#define CODEC_REGISTER_AND_CACHE_NAMED(fmt_name, codec) \
        ({ \
                int __res_ ## __LINE__ = 0; \
                struct ast_format *__fmt_ ## __LINE__; \
                struct ast_codec *__codec_ ## __LINE__; \
+               codec.format_name = fmt_name; \
                res |= __ast_codec_register(&(codec), NULL); \
                __codec_ ## __LINE__ = ast_codec_get((codec).name, (codec).type, (codec).sample_rate); \
-               __fmt_ ## __LINE__ = ast_format_create_named((format_name), __codec_ ## __LINE__); \
+               __fmt_ ## __LINE__ = ast_format_create_named((fmt_name), __codec_ ## __LINE__); \
                res |= ast_format_cache_set(__fmt_ ## __LINE__); \
                ao2_ref(__fmt_ ## __LINE__, -1); \
                ao2_ref(__codec_ ## __LINE__, -1); \
index 9e2db9de67feec9c75ccfe6098cf33fe3ae4264f..6baac7a4e7cfacc7f71fa37ccd9004735b46c915 100644 (file)
@@ -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);
 }
index 4d3ad5f8bc0aee2916e3fe5058b80bf6b7092f40..5bb6f7f1ed7054a4a51725b8760c9ce744899abc 100644 (file)
@@ -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}.
index d1ae80196bbcbe60756949e6ce5a0075f6241d51..a14a9c8cb4dc9ac4782bbd38314bf45e3adfc54f 100644 (file)
@@ -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) {
index cb41fb681658732822436081383517144f683729..8eaa5eb9b5b81d9118172e0e229291e252c31f95 100644 (file)
                                                        "required": false,
                                                        "allowMultiple": false,
                                                        "dataType": "string"
+                                               },
+                                               {
+                                                       "name": "formats",
+                                                       "description": "The format name capability list to use if originator is not specified. Ex. \"ulaw,slin16\".  Format names can be found with \"core show codecs\".",
+                                                       "paramType": "query",
+                                                       "required": false,
+                                                       "allowMultiple": false,
+                                                       "dataType": "string"
                                                }
                                        ],
                                        "errorResponses": [
                                                        "required": false,
                                                        "allowMultiple": false,
                                                        "dataType": "string"
+                                               },
+                                               {
+                                                       "name": "formats",
+                                                       "description": "The format name capability list to use if originator is not specified. Ex. \"ulaw,slin16\".  Format names can be found with \"core show codecs\".",
+                                                       "paramType": "query",
+                                                       "required": false,
+                                                       "allowMultiple": false,
+                                                       "dataType": "string"
                                                }
                                        ],
                                        "errorResponses": [
                                                        "reason": "Invalid parameters for originating a channel."
                                                }
                                        ]
-
                                },
                                {
                                        "httpMethod": "DELETE",