<p>Sean Bright has uploaded this change for <strong>review</strong>.</p><p><a href="https://gerrit.asterisk.org/10781">View Change</a></p><pre style="font-family: monospace,monospace; white-space: pre-wrap;">res_format_attr_ilbc.c: Add format attribute handler for iLBC<br><br>ASTERISK-28199 #close<br><br>Change-Id: I5c5d37984826c6738706eae6b9edb284d564ce2b<br>---<br>A res/res_format_attr_ilbc.c<br>1 file changed, 241 insertions(+), 0 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;">git pull ssh://gerrit.asterisk.org:29418/asterisk refs/changes/81/10781/1</pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/res/res_format_attr_ilbc.c b/res/res_format_attr_ilbc.c</span><br><span>new file mode 100644</span><br><span>index 0000000..542b7e3</span><br><span>--- /dev/null</span><br><span>+++ b/res/res_format_attr_ilbc.c</span><br><span>@@ -0,0 +1,241 @@</span><br><span style="color: hsl(120, 100%, 40%);">+/*</span><br><span style="color: hsl(120, 100%, 40%);">+ * Asterisk -- An open source telephony toolkit.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * Copyright (C) 2018, Digium, Inc.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * Sean Bright <sean.bright@gmail.com></span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * See http://www.asterisk.org for more information about</span><br><span style="color: hsl(120, 100%, 40%);">+ * the Asterisk project. Please do not directly contact</span><br><span style="color: hsl(120, 100%, 40%);">+ * any of the maintainers of this project for assistance;</span><br><span style="color: hsl(120, 100%, 40%);">+ * the project provides a web site, mailing lists and IRC</span><br><span style="color: hsl(120, 100%, 40%);">+ * channels for your use.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * This program is free software, distributed under the terms of</span><br><span style="color: hsl(120, 100%, 40%);">+ * the GNU General Public License Version 2. See the LICENSE file</span><br><span style="color: hsl(120, 100%, 40%);">+ * at the top of the source tree.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*! \file</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \brief iLBC Format Attribute Module</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \author\verbatim Sean Bright <sean.bright@gmail.com> \endverbatim</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * This is a format attribute module for the iLBC codec.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \ingroup codecs</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*** MODULEINFO</span><br><span style="color: hsl(120, 100%, 40%);">+       <support_level>core</support_level></span><br><span style="color: hsl(120, 100%, 40%);">+***/</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#include "asterisk.h"</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ASTERISK_FILE_VERSION(__FILE__, "$Revision$")</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#include "asterisk/module.h"</span><br><span style="color: hsl(120, 100%, 40%);">+#include "asterisk/format.h"</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+struct ilbc_attr {</span><br><span style="color: hsl(120, 100%, 40%);">+  unsigned char mode;</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static void ilbc_destroy(struct ast_format *format)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+     struct ilbc_attr *attr = ast_format_get_attribute_data(format);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     ast_free(attr);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static int ilbc_clone(const struct ast_format *src, struct ast_format *dst)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+  struct ilbc_attr *original = ast_format_get_attribute_data(src);</span><br><span style="color: hsl(120, 100%, 40%);">+      struct ilbc_attr *attr = ast_calloc(1, sizeof(*attr));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      if (!attr) {</span><br><span style="color: hsl(120, 100%, 40%);">+          return -1;</span><br><span style="color: hsl(120, 100%, 40%);">+    }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   if (original) {</span><br><span style="color: hsl(120, 100%, 40%);">+               *attr = *original;</span><br><span style="color: hsl(120, 100%, 40%);">+    }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   ast_format_set_attribute_data(dst, attr);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static enum ast_format_cmp_res ilbc_cmp(const struct ast_format *format1, const struct ast_format *format2)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+        struct ilbc_attr *attr1 = ast_format_get_attribute_data(format1);</span><br><span style="color: hsl(120, 100%, 40%);">+     struct ilbc_attr *attr2 = ast_format_get_attribute_data(format2);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   if (!attr1 || !attr2 || attr1->mode == attr2->mode) {</span><br><span style="color: hsl(120, 100%, 40%);">+           return AST_FORMAT_CMP_EQUAL;</span><br><span style="color: hsl(120, 100%, 40%);">+  }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   return AST_FORMAT_CMP_NOT_EQUAL;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static struct ast_format *ilbc_get_joint(const struct ast_format *format1, const struct ast_format *format2)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+        struct ast_format *cloned;</span><br><span style="color: hsl(120, 100%, 40%);">+    struct ilbc_attr *attr, *attr1, *attr2;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     cloned = ast_format_clone(format1);</span><br><span style="color: hsl(120, 100%, 40%);">+   if (!cloned) {</span><br><span style="color: hsl(120, 100%, 40%);">+                return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+  }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   attr = ast_format_get_attribute_data(cloned);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       attr1 = ast_format_get_attribute_data(format1);</span><br><span style="color: hsl(120, 100%, 40%);">+       attr2 = ast_format_get_attribute_data(format2);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     /*</span><br><span style="color: hsl(120, 100%, 40%);">+     * From RFC 3952:</span><br><span style="color: hsl(120, 100%, 40%);">+      *</span><br><span style="color: hsl(120, 100%, 40%);">+     * The offer contains the preferred mode of the offerer.  The answerer</span><br><span style="color: hsl(120, 100%, 40%);">+         * may agree to that mode by including the same mode in the answer, or</span><br><span style="color: hsl(120, 100%, 40%);">+         * may include a different mode.  The resulting mode used by both</span><br><span style="color: hsl(120, 100%, 40%);">+      * parties SHALL be the lower of the bandwidth modes in the offer and</span><br><span style="color: hsl(120, 100%, 40%);">+  * answer.</span><br><span style="color: hsl(120, 100%, 40%);">+     *</span><br><span style="color: hsl(120, 100%, 40%);">+     * That is, an offer of "mode=20" receiving an answer of "mode=30" will</span><br><span style="color: hsl(120, 100%, 40%);">+    * result in "mode=30" being used by both participants.  Similarly, an</span><br><span style="color: hsl(120, 100%, 40%);">+       * offer of "mode=30" and an answer of "mode=20" will result in</span><br><span style="color: hsl(120, 100%, 40%);">+    * "mode=30" being used by both participants.</span><br><span style="color: hsl(120, 100%, 40%);">+        */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ attr->mode = attr1->mode > attr2->mode ? attr1->mode : attr2->mode;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       return cloned;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static struct ast_format *ilbc_parse_sdp_fmtp(const struct ast_format *format, const char *attributes)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+        char *attribs = ast_strdupa(attributes), *attrib;</span><br><span style="color: hsl(120, 100%, 40%);">+     struct ast_format *cloned;</span><br><span style="color: hsl(120, 100%, 40%);">+    struct ilbc_attr *attr;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     cloned = ast_format_clone(format);</span><br><span style="color: hsl(120, 100%, 40%);">+    if (!cloned) {</span><br><span style="color: hsl(120, 100%, 40%);">+                return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+  }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   attr = ast_format_get_attribute_data(cloned);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       while ((attrib = strsep(&attribs, ";"))) {</span><br><span style="color: hsl(120, 100%, 40%);">+              unsigned char val;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+          attrib = ast_strip(attrib);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+         if (sscanf(attrib, "mode=%hhu", &val) == 1) {</span><br><span style="color: hsl(120, 100%, 40%);">+                   if (val == 20 || val == 30) {</span><br><span style="color: hsl(120, 100%, 40%);">+                         attr->mode = val;</span><br><span style="color: hsl(120, 100%, 40%);">+                  }</span><br><span style="color: hsl(120, 100%, 40%);">+             }</span><br><span style="color: hsl(120, 100%, 40%);">+     }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   return cloned;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static void ilbc_generate_sdp_fmtp(const struct ast_format *format, unsigned int payload, struct ast_str **str)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+       struct ilbc_attr *attr = ast_format_get_attribute_data(format);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     if (!attr) {</span><br><span style="color: hsl(120, 100%, 40%);">+          return;</span><br><span style="color: hsl(120, 100%, 40%);">+       }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   if (attr->mode) {</span><br><span style="color: hsl(120, 100%, 40%);">+          ast_str_append(str, 0, "a=fmtp:%u mode=%hhu\r\n", payload, attr->mode);</span><br><span style="color: hsl(120, 100%, 40%);">+  }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   return;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static const void *ilbc_attribute_get(const struct ast_format *format, const char *name)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+     struct ilbc_attr *attr = ast_format_get_attribute_data(format);</span><br><span style="color: hsl(120, 100%, 40%);">+       unsigned char *val = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  if (!attr) {</span><br><span style="color: hsl(120, 100%, 40%);">+          return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+  }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   if (!strcasecmp(name, "mode")) {</span><br><span style="color: hsl(120, 100%, 40%);">+            val = &attr->mode;</span><br><span style="color: hsl(120, 100%, 40%);">+     } else {</span><br><span style="color: hsl(120, 100%, 40%);">+              ast_log(LOG_WARNING, "Unknown attribute type: %s\n", name);</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   return val;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static struct ast_format *ilbc_attribute_set(const struct ast_format *format,</span><br><span style="color: hsl(120, 100%, 40%);">+       const char *name, const char *value)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+       struct ast_format *cloned;</span><br><span style="color: hsl(120, 100%, 40%);">+    struct ilbc_attr *attr;</span><br><span style="color: hsl(120, 100%, 40%);">+       unsigned char val;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  cloned = ast_format_clone(format);</span><br><span style="color: hsl(120, 100%, 40%);">+    if (!cloned) {</span><br><span style="color: hsl(120, 100%, 40%);">+                return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+  }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   attr = ast_format_get_attribute_data(cloned);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       if (sscanf(value, "%hhu", &val) != 1) {</span><br><span style="color: hsl(120, 100%, 40%);">+         ast_log(LOG_WARNING, "Unknown value '%s' for attribute type '%s'\n",</span><br><span style="color: hsl(120, 100%, 40%);">+                        value, name);</span><br><span style="color: hsl(120, 100%, 40%);">+         return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+  }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   if (!strcasecmp(name, "mode")) {</span><br><span style="color: hsl(120, 100%, 40%);">+            if (val == 20 || val == 30) {</span><br><span style="color: hsl(120, 100%, 40%);">+                 attr->mode = val;</span><br><span style="color: hsl(120, 100%, 40%);">+          } else {</span><br><span style="color: hsl(120, 100%, 40%);">+                      ast_log(LOG_NOTICE, "Invalid '%s' specified: %hhu (expected 20 or 30)\n",</span><br><span style="color: hsl(120, 100%, 40%);">+                           name, val);</span><br><span style="color: hsl(120, 100%, 40%);">+           }</span><br><span style="color: hsl(120, 100%, 40%);">+     } else {</span><br><span style="color: hsl(120, 100%, 40%);">+              ast_log(LOG_WARNING, "Unknown attribute type: %s\n", name);</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   return cloned;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static struct ast_format_interface ilbc_interface = {</span><br><span style="color: hsl(120, 100%, 40%);">+    .format_destroy = ilbc_destroy,</span><br><span style="color: hsl(120, 100%, 40%);">+       .format_clone = ilbc_clone,</span><br><span style="color: hsl(120, 100%, 40%);">+   .format_cmp = ilbc_cmp,</span><br><span style="color: hsl(120, 100%, 40%);">+       .format_get_joint = ilbc_get_joint,</span><br><span style="color: hsl(120, 100%, 40%);">+   .format_parse_sdp_fmtp = ilbc_parse_sdp_fmtp,</span><br><span style="color: hsl(120, 100%, 40%);">+ .format_generate_sdp_fmtp = ilbc_generate_sdp_fmtp,</span><br><span style="color: hsl(120, 100%, 40%);">+   .format_attribute_get = ilbc_attribute_get,</span><br><span style="color: hsl(120, 100%, 40%);">+   .format_attribute_set = ilbc_attribute_set,</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static int unload_module(void)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+  return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static int load_module(void)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+       if (ast_format_interface_register("iLBC", &ilbc_interface)) {</span><br><span style="color: hsl(120, 100%, 40%);">+           return AST_MODULE_LOAD_DECLINE;</span><br><span style="color: hsl(120, 100%, 40%);">+       }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   return AST_MODULE_LOAD_SUCCESS;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "iLBC Format Attribute Module",</span><br><span style="color: hsl(120, 100%, 40%);">+        .support_level = AST_MODULE_SUPPORT_CORE,</span><br><span style="color: hsl(120, 100%, 40%);">+     .load = load_module,</span><br><span style="color: hsl(120, 100%, 40%);">+  .unload = unload_module,</span><br><span style="color: hsl(120, 100%, 40%);">+);</span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.asterisk.org/10781">change 10781</a>. To unsubscribe, or for help writing mail filters, visit <a href="https://gerrit.asterisk.org/settings">settings</a>.</p><div itemscope itemtype="http://schema.org/EmailMessage"><div itemscope itemprop="action" itemtype="http://schema.org/ViewAction"><link itemprop="url" href="https://gerrit.asterisk.org/10781"/><meta itemprop="name" content="View Change"/></div></div>

<div style="display:none"> Gerrit-Project: asterisk </div>
<div style="display:none"> Gerrit-Branch: 13 </div>
<div style="display:none"> Gerrit-MessageType: newchange </div>
<div style="display:none"> Gerrit-Change-Id: I5c5d37984826c6738706eae6b9edb284d564ce2b </div>
<div style="display:none"> Gerrit-Change-Number: 10781 </div>
<div style="display:none"> Gerrit-PatchSet: 1 </div>
<div style="display:none"> Gerrit-Owner: Sean Bright <sean.bright@gmail.com> </div>