]> git.ipfire.org Git - thirdparty/asterisk.git/commitdiff
codecs: Fix ABI incompatibility created by adding format_name to ast_codec 00/3100/5
authorGeorge Joseph <gjoseph@digium.com>
Tue, 28 Jun 2016 14:00:32 +0000 (08:00 -0600)
committerGeorge Joseph <gjoseph@digium.com>
Tue, 28 Jun 2016 19:38:28 +0000 (13:38 -0600)
Adding format_name even to the end of ast_codec caused issued with
binary codec modules because the pointer would be garbage in asterisk
when they registered.  So, the ast_codec structure was reverted and an
internal_ast_codec structure was created just for use in codec.c.  A new
internal-only API was also added (__ast_codec_register_with_format) so
that codec_builtin could register codecs with the format_name in a
separate parameter rather than in the ast_codec structure.

ASTERISK-26144 #close
Reported-by: Alexei Gradinari
Change-Id: I6df1b08f6a6ae089db23adfe1ebc8636330265ba

include/asterisk/codec.h
main/codec.c
main/codec_builtin.c

index fb2b7da38baeee3e7939a551b458ea9a625949d0..28befec50cbe10dfdbe7c392fd68685100d54995 100644 (file)
@@ -77,8 +77,6 @@ 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 c8644fd34a6a336b9f47b7f07b5b67ded8f28478..c253233bb634d256b8945fb039fbe699a92d546d 100644 (file)
@@ -49,6 +49,32 @@ static int codec_id = 1;
 /*! \brief Registered codecs */
 static struct ao2_container *codecs;
 
+/*!
+ * \internal
+ * \brief Internal codec structure
+ *
+ * External codecs won't know about the format_name field so the public
+ * ast_codec structure has to leave it out.  This structure will be used
+ * for the internal codecs.
+ *
+ */
+struct internal_ast_codec {
+       /*! \brief Public codec structure.  Must remain first. */
+       struct ast_codec external;
+       /*! \brief A format name for a default sane format using this codec */
+       const char *format_name;
+};
+
+/*!
+ * \internal
+ * \brief Internal function for registration with format name
+ *
+ * This function is only used by codec.c and codec_builtin.c and
+ * will be removed in Asterisk 14
+ */
+int __ast_codec_register_with_format(struct ast_codec *codec, const char *format_name,
+       struct ast_module *mod);
+
 static int codec_hash(const void *obj, int flags)
 {
        const struct ast_codec *codec;
@@ -113,7 +139,7 @@ static int codec_cmp(void *obj, void *arg, int flags)
 static char *show_codecs(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 {
        struct ao2_iterator i;
-       struct ast_codec *codec;
+       struct internal_ast_codec *codec;
 
        switch (cmd) {
        case CLI_INIT:
@@ -144,19 +170,19 @@ static char *show_codecs(struct ast_cli_entry *e, int cmd, struct ast_cli_args *
        for (; (codec = ao2_iterator_next(&i)); ao2_ref(codec, -1)) {
                if (a->argc == 4) {
                        if (!strcasecmp(a->argv[3], "audio")) {
-                               if (codec->type != AST_MEDIA_TYPE_AUDIO) {
+                               if (codec->external.type != AST_MEDIA_TYPE_AUDIO) {
                                        continue;
                                }
                        } else if (!strcasecmp(a->argv[3], "video")) {
-                               if (codec->type != AST_MEDIA_TYPE_VIDEO) {
+                               if (codec->external.type != AST_MEDIA_TYPE_VIDEO) {
                                        continue;
                                }
                        } else if (!strcasecmp(a->argv[3], "image")) {
-                               if (codec->type != AST_MEDIA_TYPE_IMAGE) {
+                               if (codec->external.type != AST_MEDIA_TYPE_IMAGE) {
                                        continue;
                                }
                        } else if (!strcasecmp(a->argv[3], "text")) {
-                               if (codec->type != AST_MEDIA_TYPE_TEXT) {
+                               if (codec->external.type != AST_MEDIA_TYPE_TEXT) {
                                        continue;
                                }
                        } else {
@@ -165,11 +191,11 @@ static char *show_codecs(struct ast_cli_entry *e, int cmd, struct ast_cli_args *
                }
 
                ast_cli(a->fd, "%8u %-5s %-12s %-16s (%s)\n",
-                       codec->id,
-                       ast_codec_media_type2str(codec->type),
-                       codec->name,
+                       codec->external.id,
+                       ast_codec_media_type2str(codec->external.type),
+                       codec->external.name,
                        S_OR(codec->format_name, "no cached format"),
-                       codec->description);
+                       codec->external.description);
        }
 
        ao2_iterator_destroy(&i);
@@ -190,7 +216,7 @@ static int codec_id_cmp(void *obj, void *arg, int flags)
 static char *show_codec(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 {
        int type_punned_codec;
-       struct ast_codec *codec;
+       struct internal_ast_codec *codec;
 
        switch (cmd) {
        case CLI_INIT:
@@ -217,7 +243,7 @@ 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 (%s)\n", (unsigned int) codec->id, codec->description,
+       ast_cli(a->fd, "%11u %s (%s)\n", (unsigned int) codec->external.id, codec->external.description,
                S_OR(codec->format_name, "no format"));
 
        ao2_ref(codec, -1);
@@ -262,9 +288,14 @@ static void codec_dtor(void *obj)
 }
 
 int __ast_codec_register(struct ast_codec *codec, struct ast_module *mod)
+{
+       return __ast_codec_register_with_format(codec, NULL, mod);
+}
+
+int __ast_codec_register_with_format(struct ast_codec *codec, const char *format_name, struct ast_module *mod)
 {
        SCOPED_AO2WRLOCK(lock, codecs);
-       struct ast_codec *codec_new;
+       struct internal_ast_codec *codec_new;
 
        /* Some types have specific requirements */
        if (codec->type == AST_MEDIA_TYPE_UNKNOWN) {
@@ -293,8 +324,9 @@ int __ast_codec_register(struct ast_codec *codec, struct ast_module *mod)
                        codec->name, ast_codec_media_type2str(codec->type), codec->sample_rate);
                return -1;
        }
-       *codec_new = *codec;
-       codec_new->id = codec_id++;
+       codec_new->external = *codec;
+       codec_new->format_name = format_name;
+       codec_new->external.id = codec_id++;
 
        ao2_link_flags(codecs, codec_new, OBJ_NOLOCK);
 
@@ -302,7 +334,7 @@ int __ast_codec_register(struct ast_codec *codec, struct ast_module *mod)
        ast_module_shutdown_ref(mod);
 
        ast_verb(2, "Registered '%s' codec '%s' at sample rate '%u' with id '%u'\n",
-               ast_codec_media_type2str(codec->type), codec->name, codec->sample_rate, codec_new->id);
+               ast_codec_media_type2str(codec->type), codec->name, codec->sample_rate, codec_new->external.id);
 
        ao2_ref(codec_new, -1);
 
index d7d253ab8d05de662df3db005e67a026f2b2f16f..d3f65174c8cfb6529e67d8c5f0c036b1f6187d1a 100644 (file)
@@ -38,6 +38,9 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 #include "asterisk/format_cache.h"
 #include "asterisk/frame.h"
 
+int __ast_codec_register_with_format(struct ast_codec *codec, const char *format_name,
+       struct ast_module *mod);
+
 enum frame_type {
        TYPE_HIGH,     /* 0x0 */
        TYPE_LOW,      /* 0x1 */
@@ -774,8 +777,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); \
+               res |= __ast_codec_register_with_format(&(codec), (codec).name, NULL); \
                __codec_ ## __LINE__ = ast_codec_get((codec).name, (codec).type, (codec).sample_rate); \
                __fmt_ ## __LINE__ = __codec_ ## __LINE__ ? ast_format_create(__codec_ ## __LINE__) : NULL; \
                res |= ast_format_cache_set(__fmt_ ## __LINE__); \
@@ -789,8 +791,7 @@ static struct ast_codec t140 = {
                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); \
+               res |= __ast_codec_register_with_format(&(codec), fmt_name, NULL); \
                __codec_ ## __LINE__ = ast_codec_get((codec).name, (codec).type, (codec).sample_rate); \
                __fmt_ ## __LINE__ = ast_format_create_named((fmt_name), __codec_ ## __LINE__); \
                res |= ast_format_cache_set(__fmt_ ## __LINE__); \