]> git.ipfire.org Git - thirdparty/freeswitch.git/commitdiff
add bitrate patch from moc with some extra stuff for late neg mode
authorAnthony Minessale <anthm@freeswitch.org>
Wed, 29 Sep 2010 21:52:34 +0000 (16:52 -0500)
committerAnthony Minessale <anthm@freeswitch.org>
Wed, 29 Sep 2010 21:52:43 +0000 (16:52 -0500)
14 files changed:
src/include/switch_core.h
src/include/switch_module_interfaces.h
src/include/switch_types.h
src/mod/codecs/mod_amr/mod_amr.c
src/mod/codecs/mod_ilbc/mod_ilbc.c
src/mod/codecs/mod_silk/mod_silk.c
src/mod/codecs/mod_siren/mod_siren.c
src/mod/codecs/mod_speex/mod_speex.c
src/mod/endpoints/mod_sofia/mod_sofia.h
src/mod/endpoints/mod_sofia/sofia_glue.c
src/switch_channel.c
src/switch_core_codec.c
src/switch_core_sqldb.c
src/switch_loadable_module.c

index 7275f263196cf9b335e8bd6c25c7beb99746d4da..8b08db7d9dc5dec806971752c592bd7e76e56cea 100644 (file)
@@ -1339,12 +1339,15 @@ SWITCH_DECLARE(switch_status_t) switch_core_timer_destroy(switch_timer_t *timer)
   \param pool the memory pool to use
   \return SWITCH_STATUS_SUCCESS if the handle is allocated
 */
-SWITCH_DECLARE(switch_status_t) switch_core_codec_init(switch_codec_t *codec,
+#define switch_core_codec_init(_codec, _codec_name, _fmtp, _rate, _ms, _channels, _flags, _codec_settings, _pool) \
+       switch_core_codec_init_with_bitrate(_codec, _codec_name, _fmtp, _rate, _ms, _channels, 0, _flags, _codec_settings, _pool)
+SWITCH_DECLARE(switch_status_t) switch_core_codec_init_with_bitrate(switch_codec_t *codec,
                                                                                                           const char *codec_name,
                                                                                                           const char *fmtp,
                                                                                                           uint32_t rate,
                                                                                                           int ms,
                                                                                                           int channels,
+                                                                                                          uint32_t bitrate,
                                                                                                           uint32_t flags, const switch_codec_settings_t *codec_settings, switch_memory_pool_t *pool);
 
 SWITCH_DECLARE(switch_status_t) switch_core_codec_copy(switch_codec_t *codec, switch_codec_t *new_codec, switch_memory_pool_t *pool);
index 078b83d2fd052adcdbe9760efcb1616849bda900..a6013a9386068e9139d3954fca9def63f63ad94a 100644 (file)
@@ -570,42 +570,23 @@ struct switch_directory_handle {
        void *private_info;
 };
 
-
 /* nobody has more setting than speex so we will let them set the standard */
 /*! \brief Various codec settings (currently only relevant to speex) */
 struct switch_codec_settings {
-       /*! desired quality */
-       int quality;
-       /*! desired complexity */
-       int complexity;
-       /*! desired enhancement */
-       int enhancement;
-       /*! desired vad level */
-       int vad;
-       /*! desired vbr level */
-       int vbr;
-       /*! desired vbr quality */
-       float vbr_quality;
-       /*! desired abr level */
-       int abr;
-       /*! desired dtx setting */
-       int dtx;
-       /*! desired preprocessor settings */
-       int preproc;
-       /*! preprocessor vad settings */
-       int pp_vad;
-       /*! preprocessor gain control settings */
-       int pp_agc;
-       /*! preprocessor gain level */
-       float pp_agc_level;
-       /*! preprocessor denoise level */
-       int pp_denoise;
-       /*! preprocessor dereverb settings */
-       int pp_dereverb;
-       /*! preprocessor dereverb decay level */
-       float pp_dereverb_decay;
-       /*! preprocessor dereverb level */
-       float pp_dereverb_level;
+       int unused;
+};
+
+/*! an abstract handle of a fmtp parsed by codec */
+struct switch_codec_fmtp {
+       /*! actual samples transferred per second for those who are not moron g722 RFC writers */
+       uint32_t actual_samples_per_second;
+       /*! bits transferred per second */
+       int bits_per_second;
+       /*! number of microseconds of media in one packet (ptime * 1000) */
+       int microseconds_per_packet;
+       /*! private data for the codec module to store handle specific info */
+       void *private_info;
+
 };
 
 /*! an abstract handle to a codec module */
@@ -618,8 +599,6 @@ struct switch_codec {
        char *fmtp_in;
        /*! fmtp line for local sdp */
        char *fmtp_out;
-       /*! codec settings for this handle */
-       switch_codec_settings_t codec_settings;
        /*! flags to modify behaviour */
        uint32_t flags;
        /*! the handle's memory pool */
@@ -678,6 +657,8 @@ struct switch_codec_interface {
        const char *interface_name;
        /*! a list of codec implementations related to the codec */
        switch_codec_implementation_t *implementations;
+       /*! function to decode a codec fmtp parameters */
+       switch_core_codec_fmtp_parse_func_t parse_fmtp;
        uint32_t codec_id;
        switch_thread_rwlock_t *rwlock;
        int refs;
index 70eaa4f80e451f6d984f281dac5329dc2d2473f4..57c5661c7cda27211df0ace3a15f67ef3f059f59 100644 (file)
@@ -1588,6 +1588,7 @@ typedef struct switch_core_thread_session switch_core_thread_session_t;
 typedef struct switch_codec_implementation switch_codec_implementation_t;
 typedef struct switch_buffer switch_buffer_t;
 typedef struct switch_codec_settings switch_codec_settings_t;
+typedef struct switch_codec_fmtp switch_codec_fmtp_t;
 typedef struct switch_odbc_handle switch_odbc_handle_t;
 
 typedef struct switch_io_routines switch_io_routines_t;
@@ -1646,6 +1647,7 @@ typedef switch_status_t (*switch_core_codec_decode_func_t) (switch_codec_t *code
                                                                                                                        void *decoded_data, uint32_t *decoded_data_len, uint32_t *decoded_rate, unsigned int *flag);
 
 typedef switch_status_t (*switch_core_codec_init_func_t) (switch_codec_t *, switch_codec_flag_t, const switch_codec_settings_t *codec_settings);
+typedef switch_status_t (*switch_core_codec_fmtp_parse_func_t) (const char *fmtp, switch_codec_fmtp_t *codec_fmtp);
 typedef switch_status_t (*switch_core_codec_destroy_func_t) (switch_codec_t *);
 
 
index a864254e28f54f115147df44143f934966538268..e8925c4581a47e60a88d7f454998bfe563ad76cb 100644 (file)
@@ -98,11 +98,8 @@ typedef enum {
        AMR_DTX_ENABLED
 } amr_dtx_t;
 
-struct amr_context {
-       void *encoder_state;
-       void *decoder_state;
-       switch_byte_t enc_modes;
-       switch_byte_t enc_mode;
+/*! \brief Various codec settings */
+struct amr_codec_settings {
        int dtx_mode;
        uint32_t change_period;
        switch_byte_t max_ptime;
@@ -110,6 +107,24 @@ struct amr_context {
        switch_byte_t channels;
        switch_byte_t flags;
 };
+typedef struct amr_codec_settings amr_codec_settings_t;
+
+static amr_codec_settings_t default_codec_settings = {
+       /*.dtx_mode */ AMR_DTX_ENABLED,
+       /*.change_period */ 0,
+       /*.max_ptime */ 0,
+       /*.ptime */ 0,
+       /*.channels */ 0,
+       /*.flags */ 0,
+};
+
+
+struct amr_context {
+       void *encoder_state;
+       void *decoder_state;
+       switch_byte_t enc_modes;
+       switch_byte_t enc_mode;
+};
 
 #define AMR_DEFAULT_BITRATE AMR_BITRATE_1220
 
@@ -117,6 +132,88 @@ static struct {
        switch_byte_t default_bitrate;
 } globals;
 
+static switch_status_t switch_amr_fmtp_parse(const char *fmtp, switch_codec_fmtp_t *codec_fmtp)
+{
+       if (codec_fmtp) {
+               amr_codec_settings_t *codec_settings = NULL;
+               if (codec_fmtp->private_info) {
+                       codec_settings = codec_fmtp->private_info;
+                       memcpy(codec_settings, &default_codec_settings, sizeof(*codec_settings));
+               }
+
+               if (fmtp) {
+                       int x, argc;
+                       char *argv[10];
+                       char *fmtp_dup = strdup(fmtp);
+
+                       switch_assert(fmtp_dup);
+
+                       argc = switch_separate_string((char *) fmtp_dup, ';', argv, (sizeof(argv) / sizeof(argv[0])));
+                       for (x = 0; x < argc; x++) {
+                               char *data = argv[x];
+                               char *arg;
+                               switch_assert(data);
+                               while (*data == ' ') {
+                                       data++;
+                               }
+                               if ((arg = strchr(data, '='))) {
+                                       *arg++ = '\0';
+                                       /*
+                                          if (!strcasecmp(data, "bitrate")) {
+                                          bit_rate = atoi(arg);
+                                          }
+                                        */
+                                       if (codec_settings) {
+                                               if (!strcasecmp(data, "octet-align")) {
+                                                       if (atoi(arg)) {
+                                                               switch_set_flag(codec_settings, AMR_OPT_OCTET_ALIGN);
+                                                       }
+                                               } else if (!strcasecmp(data, "mode-change-neighbor")) {
+                                                       if (atoi(arg)) {
+                                                               switch_set_flag(codec_settings, AMR_OPT_MODE_CHANGE_NEIGHBOR);
+                                                       }
+                                               } else if (!strcasecmp(data, "crc")) {
+                                                       if (atoi(arg)) {
+                                                               switch_set_flag(codec_settings, AMR_OPT_CRC);
+                                                       }
+                                               } else if (!strcasecmp(data, "robust-sorting")) {
+                                                       if (atoi(arg)) {
+                                                               switch_set_flag(codec_settings, AMR_OPT_ROBUST_SORTING);
+                                                       }
+                                               } else if (!strcasecmp(data, "interveaving")) {
+                                                       if (atoi(arg)) {
+                                                               switch_set_flag(codec_settings, AMR_OPT_INTERLEAVING);
+                                                       }
+                                               } else if (!strcasecmp(data, "mode-change-period")) {
+                                                       codec_settings->change_period = atoi(arg);
+                                               } else if (!strcasecmp(data, "ptime")) {
+                                                       codec_settings->ptime = (switch_byte_t) atoi(arg);
+                                               } else if (!strcasecmp(data, "channels")) {
+                                                       codec_settings->channels = (switch_byte_t) atoi(arg);
+                                               } else if (!strcasecmp(data, "maxptime")) {
+                                                       codec_settings->max_ptime = (switch_byte_t) atoi(arg);
+                                               } else if (!strcasecmp(data, "mode-set")) {
+                                                       int y, m_argc;
+                                                       char *m_argv[7];
+                                                       m_argc = switch_separate_string(arg, ',', m_argv, (sizeof(m_argv) / sizeof(m_argv[0])));
+                                                       for (y = 0; y < m_argc; y++) {
+                                                               codec_settings->enc_modes |= (1 << atoi(m_argv[y]));
+                                                       }
+                                               } else if (!strcasecmp(data, "dtx")) {
+                                                       codec_settings->dtx_mode = (atoi(arg)) ? AMR_DTX_ENABLED : AMR_DTX_DISABLED;
+                                               }
+                                       }
+
+                               }
+                       }
+                       free(fmtp_dup);
+               }
+               //codec_fmtp->bits_per_second = bit_rate;
+               return SWITCH_STATUS_SUCCESS;
+       }
+       return SWITCH_STATUS_FALSE;
+}
+
 #endif
 
 static switch_status_t switch_amr_init(switch_codec_t *codec, switch_codec_flag_t flags, const switch_codec_settings_t *codec_settings)
@@ -128,7 +225,10 @@ static switch_status_t switch_amr_init(switch_codec_t *codec, switch_codec_flag_
        }
        return SWITCH_STATUS_SUCCESS;
 #else
+
        struct amr_context *context = NULL;
+       switch_codec_fmtp_t codec_fmtp;
+       amr_codec_settings_t amr_codec_settings;
        int encoding, decoding;
        int x, i, argc;
        char *argv[10];
@@ -141,58 +241,9 @@ static switch_status_t switch_amr_init(switch_codec_t *codec, switch_codec_flag_
                return SWITCH_STATUS_FALSE;
        } else {
 
-               context->dtx_mode = AMR_DTX_ENABLED;
-               if (codec->fmtp_in) {
-                       argc = switch_separate_string(codec->fmtp_in, ';', argv, (sizeof(argv) / sizeof(argv[0])));
-                       for (x = 0; x < argc; x++) {
-                               char *data = argv[x];
-                               char *arg;
-                               while (*data && *data == ' ') {
-                                       data++;
-                               }
-                               if ((arg = strchr(data, '='))) {
-                                       *arg++ = '\0';
-                                       if (!strcasecmp(data, "octet-align")) {
-                                               if (atoi(arg)) {
-                                                       switch_set_flag(context, AMR_OPT_OCTET_ALIGN);
-                                               }
-                                       } else if (!strcasecmp(data, "mode-change-neighbor")) {
-                                               if (atoi(arg)) {
-                                                       switch_set_flag(context, AMR_OPT_MODE_CHANGE_NEIGHBOR);
-                                               }
-                                       } else if (!strcasecmp(data, "crc")) {
-                                               if (atoi(arg)) {
-                                                       switch_set_flag(context, AMR_OPT_CRC);
-                                               }
-                                       } else if (!strcasecmp(data, "robust-sorting")) {
-                                               if (atoi(arg)) {
-                                                       switch_set_flag(context, AMR_OPT_ROBUST_SORTING);
-                                               }
-                                       } else if (!strcasecmp(data, "interveaving")) {
-                                               if (atoi(arg)) {
-                                                       switch_set_flag(context, AMR_OPT_INTERLEAVING);
-                                               }
-                                       } else if (!strcasecmp(data, "mode-change-period")) {
-                                               context->change_period = atoi(arg);
-                                       } else if (!strcasecmp(data, "ptime")) {
-                                               context->ptime = (switch_byte_t) atoi(arg);
-                                       } else if (!strcasecmp(data, "channels")) {
-                                               context->channels = (switch_byte_t) atoi(arg);
-                                       } else if (!strcasecmp(data, "maxptime")) {
-                                               context->max_ptime = (switch_byte_t) atoi(arg);
-                                       } else if (!strcasecmp(data, "mode-set")) {
-                                               int y, m_argc;
-                                               char *m_argv[7];
-                                               m_argc = switch_separate_string(arg, ',', m_argv, (sizeof(m_argv) / sizeof(m_argv[0])));
-                                               for (y = 0; y < m_argc; y++) {
-                                                       context->enc_modes |= (1 << atoi(m_argv[y]));
-                                               }
-                                       } else if (!strcasecmp(data, "dtx")) {
-                                               context->dtx_mode = (atoi(arg)) ? AMR_DTX_ENABLED : AMR_DTX_DISABLED;
-                                       }
-                               }
-                       }
-               }
+               memset(&codec_fmtp, '\0', sizeof(struct switch_codec_fmtp));
+               codec_fmtp.private_info = &amr_codec_settings;
+               switch_amr_fmtp_parse(codec->fmtp_in, &codec_fmtp);
 
                if (context->enc_modes) {
                        for (i = 7; i > -1; i++) {
@@ -321,6 +372,9 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_amr_load)
        *module_interface = switch_loadable_module_create_module_interface(pool, modname);
 
        SWITCH_ADD_CODEC(codec_interface, "AMR");
+#ifndef AMR_PASSTHROUGH
+       codec_interface->parse_fmtp = switch_amr_fmtp_parse;
+#endif 
        switch_core_codec_add_implementation(pool, codec_interface, SWITCH_CODEC_TYPE_AUDIO,    /* enumeration defining the type of the codec */
                                                                                 96,    /* the IANA code number */
                                                                                 "AMR", /* the IANA code name */
index b37056c393d0bf2ba329b88d315bbbd4e38ec2b1..85298375db31c9c5d703f06458b11d8a1229bcf3 100644 (file)
@@ -40,6 +40,27 @@ struct ilbc_context {
        ilbc_decode_state_t decoder_object;
 };
 
+static switch_status_t switch_ilbc_fmtp_parse(const char *fmtp, switch_codec_fmtp_t *codec_fmtp)
+{
+       if (codec_fmtp) {
+               char *mode = NULL;
+               int codec_ms = 0;
+
+               memset(codec_fmtp, '\0', sizeof(struct switch_codec_fmtp));
+
+               if (fmtp && (mode = strstr(fmtp, "mode=")) && (mode + 5)) {
+                       codec_ms = atoi(mode + 5);
+               }
+               if (!codec_ms) {
+                       /* default to 30 when no mode is defined for ilbc ONLY */
+                       codec_ms = 30;
+               }
+               codec_fmtp->microseconds_per_packet = (codec_ms * 1000);
+               return SWITCH_STATUS_SUCCESS;
+       }
+       return SWITCH_STATUS_FALSE;
+}
+
 static switch_status_t switch_ilbc_init(switch_codec_t *codec, switch_codec_flag_t flags, const switch_codec_settings_t *codec_settings)
 {
        struct ilbc_context *context;
@@ -51,26 +72,6 @@ static switch_status_t switch_ilbc_init(switch_codec_t *codec, switch_codec_flag
                return SWITCH_STATUS_FALSE;
        }
 
-       if (codec->fmtp_in) {
-               int x, argc;
-               char *argv[10];
-               argc = switch_separate_string(codec->fmtp_in, ';', argv, (sizeof(argv) / sizeof(argv[0])));
-               for (x = 0; x < argc; x++) {
-                       char *data = argv[x];
-                       char *arg;
-                       switch_assert(data);
-                       while (*data == ' ') {
-                               data++;
-                       }
-                       if ((arg = strchr(data, '='))) {
-                               *arg++ = '\0';
-                               if (!strcasecmp(data, "mode")) {
-                                       mode = atoi(arg);
-                               }
-                       }
-               }
-       }
-
        codec->fmtp_out = switch_core_sprintf(codec->memory_pool, "mode=%d", mode);
 
        if (encoding) {
@@ -136,6 +137,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_ilbc_load)
        *module_interface = switch_loadable_module_create_module_interface(pool, modname);
 
        SWITCH_ADD_CODEC(codec_interface, "iLBC");
+       codec_interface->parse_fmtp = switch_ilbc_fmtp_parse;
 
        switch_core_codec_add_implementation(pool, codec_interface, SWITCH_CODEC_TYPE_AUDIO,    /* enumeration defining the type of the codec */
                                                                                 98,    /* the IANA code number */
index 9d0abcdf8b9382beb89193e470760bb5946ea0e7..ff8c2304e7211eb43e53a8568259843a804fc54a 100644 (file)
@@ -41,6 +41,22 @@ SWITCH_MODULE_DEFINITION(mod_silk, mod_silk_load, NULL, NULL);
 #define MAX_LBRR_DELAY                 2
 #define MAX_FRAME_LENGTH               480
 
+/*! \brief Various codec settings */
+struct silk_codec_settings {
+       SKP_int useinbandfec;
+       SKP_int usedtx;
+       SKP_int maxaveragebitrate;
+       SKP_int plpct;
+};
+typedef struct silk_codec_settings silk_codec_settings_t;
+
+static silk_codec_settings_t default_codec_settings = {
+       /*.useinbandfec */ 0,
+       /*.usedtx */ 0,
+       /*.maxaveragebitrate */ 0,
+       /*.plpct */ 10, // 10% for now
+};
+
 struct silk_context {
        SKP_SILK_SDK_EncControlStruct encoder_object;
        SKP_SILK_SDK_DecControlStruct decoder_object;
@@ -48,92 +64,122 @@ struct silk_context {
        void *dec_state;
 };
 
-static switch_status_t switch_silk_init(switch_codec_t *codec, 
-                                                                               switch_codec_flag_t freeswitch_flags, 
-                                                                               const switch_codec_settings_t *codec_settings)
+static switch_status_t switch_silk_fmtp_parse(const char *fmtp, switch_codec_fmtp_t *codec_fmtp)
 {
-       struct silk_context *context = NULL;
-       SKP_int useinbandfec = 0, usedtx = 0, maxaveragebitrate = 0, plpct =0;
-       SKP_int32 encSizeBytes;
-       SKP_int32 decSizeBytes;
-       int encoding = (freeswitch_flags & SWITCH_CODEC_FLAG_ENCODE);
-       int decoding = (freeswitch_flags & SWITCH_CODEC_FLAG_DECODE);
+       if (codec_fmtp) {
+               silk_codec_settings_t *codec_settings = NULL;
 
-       if (!(encoding || decoding) || (!(context = switch_core_alloc(codec->memory_pool, sizeof(*context))))) {
-               return SWITCH_STATUS_FALSE;
-       }
-       
-       if (codec->fmtp_in) {
-               int x, argc;
-               char *argv[10];
-               argc = switch_separate_string(codec->fmtp_in, ';', argv, (sizeof(argv) / sizeof(argv[0])));
-               for (x = 0; x < argc; x++) {
-                       char *data = argv[x];
-                       char *arg;
-                       switch_assert(data);
-                       while (*data == ' ') {
-                               data++;
-                       }
-                       if ((arg = strchr(data, '='))) {
-                               *arg++ = '\0';
-                               if (!strcasecmp(data, "useinbandfec")) {
-                                       if (switch_true(arg)) {
-                                               useinbandfec = 1;
-                                               plpct = 10;// 10% for now
-                                       }
-                               }
-                               if (!strcasecmp(data, "usedtx")) {
-                                       if (switch_true(arg)) {
-                                               usedtx = 1;
-                                       }
+               if (codec_fmtp->private_info) {
+                       codec_settings = codec_fmtp->private_info;
+                       memcpy(codec_settings, &default_codec_settings, sizeof(*codec_settings));
+               }
+
+               if (fmtp) {
+                       int x, argc;
+                       char *argv[10];
+                       char *fmtp_dup = strdup(fmtp);
+
+                       switch_assert(fmtp_dup);
+
+                       argc = switch_separate_string(fmtp_dup, ';', argv, (sizeof(argv) / sizeof(argv[0])));
+                       for (x = 0; x < argc; x++) {
+                               char *data = argv[x];
+                               char *arg;
+                               switch_assert(data);
+                               while (*data == ' ') {
+                                       data++;
                                }
-                               if (!strcasecmp(data, "maxaveragebitrate")) {
-                                       maxaveragebitrate = atoi(arg);
-                                       switch(codec->implementation->actual_samples_per_second) {
-                                       case 8000:
-                                               {
-                                                       if(maxaveragebitrate < 6000 || maxaveragebitrate > 20000) {
-                                                               maxaveragebitrate = 20000;
+                               if ((arg = strchr(data, '='))) {
+                                       *arg++ = '\0';
+                                       if (codec_settings) {
+                                               if (!strcasecmp(data, "useinbandfec")) {
+                                                       if (switch_true(arg)) {
+                                                               codec_settings->useinbandfec = 1;
                                                        }
-                                                       break;
                                                }
-                                       case 12000:
-                                               {
-                                                       if(maxaveragebitrate < 7000 || maxaveragebitrate > 25000) {
-                                                               maxaveragebitrate = 25000;
+                                               if (!strcasecmp(data, "usedtx")) {
+                                                       if (switch_true(arg)) {
+                                                               codec_settings->usedtx = 1;
                                                        }
-                                                       break;
                                                }
-                                       case 16000:
-                                               {
-                                                       if(maxaveragebitrate < 8000 || maxaveragebitrate > 30000) {
-                                                               maxaveragebitrate = 30000;
-                                                       }
-                                                       break;
-                                               }
-                                       case 24000:
-                                               {
-                                                       if(maxaveragebitrate < 12000 || maxaveragebitrate > 40000) {
-                                                               maxaveragebitrate = 40000;
+                                               if (!strcasecmp(data, "axaveragebitrate")) {
+                                                       codec_settings->maxaveragebitrate = atoi(arg);
+                                                       switch(codec_fmtp->actual_samples_per_second) {
+                                                               case 8000:
+                                                                       {
+                                                                               if(codec_settings->maxaveragebitrate < 6000 || codec_settings->maxaveragebitrate > 20000) {
+                                                                                       codec_settings->maxaveragebitrate = 20000;
+                                                                               }
+                                                                               break;
+                                                                       }
+                                                               case 12000:
+                                                                       {
+                                                                               if(codec_settings->maxaveragebitrate < 7000 || codec_settings->maxaveragebitrate > 25000) {
+                                                                                       codec_settings->maxaveragebitrate = 25000;
+                                                                               }
+                                                                               break;
+                                                                       }
+                                                               case 16000:
+                                                                       {
+                                                                               if(codec_settings->maxaveragebitrate < 8000 || codec_settings->maxaveragebitrate > 30000) {
+                                                                                       codec_settings->maxaveragebitrate = 30000;
+                                                                               }
+                                                                               break;
+                                                                       }
+                                                               case 24000:
+                                                                       {
+                                                                               if(codec_settings->maxaveragebitrate < 12000 || codec_settings->maxaveragebitrate > 40000) {
+                                                                                       codec_settings->maxaveragebitrate = 40000;
+                                                                               }
+                                                                               break;
+                                                                       }
+
+                                                               default:
+                                                                       /* this should never happen but 20000 is common among all rates */
+                                                                       codec_settings->maxaveragebitrate = 20000;
+                                                                       break;
                                                        }
-                                                       break;
+
                                                }
-                                               
-                                       default:
-                                               /* this should never happen but 20000 is common among all rates */
-                                               maxaveragebitrate = 20000;
-                                               break;
+
                                        }
-                                       
                                }
                        }
+                       free(fmtp_dup);
                }
+               //codec_fmtp->bits_per_second = bit_rate;
+               return SWITCH_STATUS_SUCCESS;
+       }
+       return SWITCH_STATUS_FALSE;
+}
+
+
+
+
+static switch_status_t switch_silk_init(switch_codec_t *codec, 
+                                                                               switch_codec_flag_t freeswitch_flags, 
+                                                                               const switch_codec_settings_t *codec_settings)
+{
+       struct silk_context *context = NULL;
+       switch_codec_fmtp_t codec_fmtp;
+       silk_codec_settings_t silk_codec_settings;
+       SKP_int32 encSizeBytes;
+       SKP_int32 decSizeBytes;
+       int encoding = (freeswitch_flags & SWITCH_CODEC_FLAG_ENCODE);
+       int decoding = (freeswitch_flags & SWITCH_CODEC_FLAG_DECODE);
+
+       if (!(encoding || decoding) || (!(context = switch_core_alloc(codec->memory_pool, sizeof(*context))))) {
+               return SWITCH_STATUS_FALSE;
        }
+
+       memset(&codec_fmtp, '\0', sizeof(struct switch_codec_fmtp));
+       codec_fmtp.private_info = &silk_codec_settings;
+       switch_silk_fmtp_parse(codec->fmtp_in, &codec_fmtp);
        
        codec->fmtp_out = switch_core_sprintf(codec->memory_pool, "useinbandfec=%s; usedtx=%s; maxaveragebitrate=%d",
-                                                                                 useinbandfec ? "1" : "0",
-                                                                                 usedtx ? "1" : "0",
-                                                                                 maxaveragebitrate ? maxaveragebitrate : codec->implementation->bits_per_second);
+                                                                                 silk_codec_settings.useinbandfec ? "1" : "0",
+                                                                                 silk_codec_settings.usedtx ? "1" : "0",
+                                                                                 silk_codec_settings.maxaveragebitrate ? silk_codec_settings.maxaveragebitrate : codec->implementation->bits_per_second);
 
        if (encoding) {
                if (SKP_Silk_SDK_Get_Encoder_Size(&encSizeBytes)) {
@@ -148,11 +194,11 @@ static switch_status_t switch_silk_init(switch_codec_t *codec,
                
                context->encoder_object.sampleRate = codec->implementation->actual_samples_per_second;
                context->encoder_object.packetSize = codec->implementation->samples_per_packet;
-               context->encoder_object.useInBandFEC = useinbandfec;
+               context->encoder_object.useInBandFEC = silk_codec_settings.useinbandfec;
                context->encoder_object.complexity = 0;
-               context->encoder_object.bitRate = maxaveragebitrate ? maxaveragebitrate : codec->implementation->bits_per_second;
-               context->encoder_object.useDTX = usedtx;
-               context->encoder_object.packetLossPercentage = plpct;;
+               context->encoder_object.bitRate = silk_codec_settings.maxaveragebitrate ? silk_codec_settings.maxaveragebitrate : codec->implementation->bits_per_second;
+               context->encoder_object.useDTX = silk_codec_settings.usedtx;
+               context->encoder_object.packetLossPercentage = silk_codec_settings.plpct;
        }
 
        if (decoding) {
@@ -299,6 +345,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_silk_load)
        *module_interface = switch_loadable_module_create_module_interface(pool, modname);
 
        SWITCH_ADD_CODEC(codec_interface, "SILK");
+       codec_interface->parse_fmtp = switch_silk_fmtp_parse;
        switch_core_codec_add_implementation(pool, codec_interface,
                                                                                 SWITCH_CODEC_TYPE_AUDIO,       /* enumeration defining the type of the codec */
                                                                                 117,                                           /* the IANA code number */
index 1ccd36eafb731a9cb68493068b3a760623c3a134..4646ffc5ae12e22fba5bd246f5c1c3b6c6c1bdf5 100644 (file)
@@ -47,6 +47,40 @@ struct siren_context {
        g722_1_encode_state_t encoder_object;
 };
 
+static switch_status_t switch_siren_fmtp_parse(const char *fmtp, switch_codec_fmtp_t *codec_fmtp)
+{
+       if (codec_fmtp) {
+               int bit_rate = 0;
+               memset(codec_fmtp, '\0', sizeof(struct switch_codec_fmtp));
+               if (fmtp) {
+                       int x, argc;
+                       char *argv[10];
+                       char *fmtp_dup = strdup(fmtp);
+
+                       switch_assert(fmtp_dup);
+                       argc = switch_separate_string(fmtp_dup, ';', argv, (sizeof(argv) / sizeof(argv[0])));
+                       for (x = 0; x < argc; x++) {
+                               char *data = argv[x];
+                               char *arg;
+                               switch_assert(data);
+                               while (*data == ' ') {
+                                       data++;
+                               }
+                               if ((arg = strchr(data, '='))) {
+                                       *arg++ = '\0';
+                                       if (!strcasecmp(data, "bitrate")) {
+                                               bit_rate = atoi(arg);
+                                       }
+                               }
+                       }
+                       free(fmtp_dup);
+               }
+               codec_fmtp->bits_per_second = bit_rate;
+               return SWITCH_STATUS_SUCCESS;
+       }
+       return SWITCH_STATUS_FALSE;
+}
+
 static switch_status_t switch_siren_init(switch_codec_t *codec, switch_codec_flag_t flags, const switch_codec_settings_t *codec_settings)
 {
        struct siren_context *context = NULL;
@@ -58,26 +92,6 @@ static switch_status_t switch_siren_init(switch_codec_t *codec, switch_codec_fla
                return SWITCH_STATUS_FALSE;
        }
 
-       if (codec->fmtp_in) {
-               int x, argc;
-               char *argv[10];
-               argc = switch_separate_string(codec->fmtp_in, ';', argv, (sizeof(argv) / sizeof(argv[0])));
-               for (x = 0; x < argc; x++) {
-                       char *data = argv[x];
-                       char *arg;
-                       switch_assert(data);
-                       while (*data == ' ') {
-                               data++;
-                       }
-                       if ((arg = strchr(data, '='))) {
-                               *arg++ = '\0';
-                               if (!strcasecmp(data, "bitrate")) {
-                                       bit_rate = atoi(arg);
-                               }
-                       }
-               }
-       }
-
        codec->fmtp_out = switch_core_sprintf(codec->memory_pool, "bitrate=%d", bit_rate);
 
        if (encoding) {
@@ -145,6 +159,28 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_siren_load)
        *module_interface = switch_loadable_module_create_module_interface(pool, modname);
 
        SWITCH_ADD_CODEC(codec_interface, "Polycom(R) G722.1/G722.1C");
+       codec_interface->parse_fmtp = switch_siren_fmtp_parse;
+
+       spf = 320, bpf = 640;
+       for (count = 3; count > 0; count--) {
+               switch_core_codec_add_implementation(pool, codec_interface, SWITCH_CODEC_TYPE_AUDIO,    /* enumeration defining the type of the codec */
+                               107,   /* the IANA code number */
+                               "G7221",       /* the IANA code name */
+                               "bitrate=24000",       /* default fmtp to send (can be overridden by the init function) */
+                               16000, /* samples transferred per second */
+                               16000, /* actual samples transferred per second */
+                               24000, /* bits transferred per second */
+                               mpf * count,   /* number of microseconds per frame */
+                               spf * count,   /* number of samples per frame */
+                               bpf * count,   /* number of bytes per frame decompressed */
+                               0,     /* number of bytes per frame compressed */
+                               1,     /* number of channels represented */
+                               1,     /* number of frames per network packet */
+                               switch_siren_init,     /* function to initialize a codec handle using this implementation */
+                               switch_siren_encode,   /* function to encode raw data into encoded data */
+                               switch_siren_decode,   /* function to decode encoded data into raw data */
+                               switch_siren_destroy); /* deinitalize a codec handle using this implementation */
+       }
 
        spf = 320, bpf = 640;
        for (count = 3; count > 0; count--) {
index 1d4a0409b89ceb025ce519517ec7c1976e83436f..a951b12d8435e457e7aa886bc8b9c9ba7253dbca 100644 (file)
 SWITCH_MODULE_LOAD_FUNCTION(mod_speex_load);
 SWITCH_MODULE_DEFINITION(mod_speex, mod_speex_load, NULL, NULL);
 
-static switch_codec_settings_t default_codec_settings = {
+/* nobody has more setting than speex so we will let them set the standard */
+/*! \brief Various codec settings (currently only relevant to speex) */
+struct speex_codec_settings {
+       /*! desired quality */
+       int quality;
+       /*! desired complexity */
+       int complexity;
+       /*! desired enhancement */
+       int enhancement;
+       /*! desired vad level */
+       int vad;
+       /*! desired vbr level */
+       int vbr;
+       /*! desired vbr quality */
+       float vbr_quality;
+       /*! desired abr level */
+       int abr;
+       /*! desired dtx setting */
+       int dtx;
+       /*! desired preprocessor settings */
+       int preproc;
+       /*! preprocessor vad settings */
+       int pp_vad;
+       /*! preprocessor gain control settings */
+       int pp_agc;
+       /*! preprocessor gain level */
+       float pp_agc_level;
+       /*! preprocessor denoise level */
+       int pp_denoise;
+       /*! preprocessor dereverb settings */
+       int pp_dereverb;
+       /*! preprocessor dereverb decay level */
+       float pp_dereverb_decay;
+       /*! preprocessor dereverb level */
+       float pp_dereverb_level;
+};
+
+typedef struct speex_codec_settings speex_codec_settings_t;
+
+static speex_codec_settings_t default_codec_settings = {
        /*.quality */ 5,
        /*.complexity */ 5,
        /*.enhancement */ 1,
@@ -58,6 +97,7 @@ static switch_codec_settings_t default_codec_settings = {
 
 struct speex_context {
        switch_codec_t *codec;
+       speex_codec_settings_t codec_settings; 
        unsigned int flags;
 
        /* Encoder */
@@ -74,6 +114,56 @@ struct speex_context {
        int decoder_mode;
 };
 
+static switch_status_t switch_speex_fmtp_parse(const char *fmtp, switch_codec_fmtp_t *codec_fmtp)
+{
+       if (codec_fmtp) {
+               speex_codec_settings_t *codec_settings = NULL;
+               if (codec_fmtp->private_info) {
+                       codec_settings = codec_fmtp->private_info;
+                       memcpy(codec_settings, &default_codec_settings, sizeof(*codec_settings));
+               }
+
+               if (fmtp) {
+                       int x, argc;
+                       char *argv[10];
+                       char *fmtp_dup = strdup(fmtp);
+
+                       switch_assert(fmtp_dup);
+
+                       argc = switch_separate_string(fmtp_dup, ';', argv, (sizeof(argv) / sizeof(argv[0])));
+
+                       for (x = 0; x < argc; x++) {
+                               char *data = argv[x];
+                               char *arg;
+                               switch_assert(data);
+                               while (*data == ' ') {
+                                       data++;
+                               }
+                               if ((arg = strchr(data, '='))) {
+                                       *arg++ = '\0';
+                                       /*
+                                          if (!strcasecmp(data, "bitrate")) {
+                                          bit_rate = atoi(arg);
+                                          }
+                                        */
+                                       /*
+                                          if (codec_settings) {
+                                          if (!strcasecmp(data, "vad")) {
+                                          bit_rate = atoi(arg);
+                                          }
+                                          }
+                                        */                     
+                               }
+                       }
+                       free(fmtp_dup);
+               }
+               /*codec_fmtp->bits_per_second = bit_rate;*/
+               return SWITCH_STATUS_SUCCESS;
+       }
+       return SWITCH_STATUS_FALSE;
+}
+
+
 static switch_status_t switch_speex_init(switch_codec_t *codec, switch_codec_flag_t flags, const switch_codec_settings_t *codec_settings)
 {
        struct speex_context *context = NULL;
@@ -82,16 +172,18 @@ static switch_status_t switch_speex_init(switch_codec_t *codec, switch_codec_fla
        encoding = (flags & SWITCH_CODEC_FLAG_ENCODE);
        decoding = (flags & SWITCH_CODEC_FLAG_DECODE);
 
-       if (!codec_settings) {
-               codec_settings = &default_codec_settings;
-       }
-
-       memcpy(&codec->codec_settings, codec_settings, sizeof(codec->codec_settings));
-
        if (!(encoding || decoding) || ((context = switch_core_alloc(codec->memory_pool, sizeof(*context))) == 0)) {
                return SWITCH_STATUS_FALSE;
        } else {
                const SpeexMode *mode = NULL;
+               switch_codec_fmtp_t codec_fmtp;
+               speex_codec_settings_t codec_settings;
+
+               memset(&codec_fmtp, '\0', sizeof(struct switch_codec_fmtp));
+               codec_fmtp.private_info = &codec_settings;
+               switch_speex_fmtp_parse(codec->fmtp_in, &codec_fmtp);
+
+               memcpy(&context->codec_settings, &codec_settings, sizeof(context->codec_settings));
 
                context->codec = codec;
                if (codec->implementation->actual_samples_per_second == 8000) {
@@ -110,41 +202,41 @@ static switch_status_t switch_speex_init(switch_codec_t *codec, switch_codec_fla
                        speex_bits_init(&context->encoder_bits);
                        context->encoder_state = speex_encoder_init(mode);
                        speex_encoder_ctl(context->encoder_state, SPEEX_GET_FRAME_SIZE, &context->encoder_frame_size);
-                       speex_encoder_ctl(context->encoder_state, SPEEX_SET_COMPLEXITY, &codec->codec_settings.complexity);
-                       if (codec->codec_settings.preproc) {
+                       speex_encoder_ctl(context->encoder_state, SPEEX_SET_COMPLEXITY, &context->codec_settings.complexity);
+                       if (context->codec_settings.preproc) {
                                context->pp = speex_preprocess_state_init(context->encoder_frame_size, codec->implementation->actual_samples_per_second);
-                               speex_preprocess_ctl(context->pp, SPEEX_PREPROCESS_SET_VAD, &codec->codec_settings.pp_vad);
-                               speex_preprocess_ctl(context->pp, SPEEX_PREPROCESS_SET_AGC, &codec->codec_settings.pp_agc);
-                               speex_preprocess_ctl(context->pp, SPEEX_PREPROCESS_SET_AGC_LEVEL, &codec->codec_settings.pp_agc_level);
-                               speex_preprocess_ctl(context->pp, SPEEX_PREPROCESS_SET_DENOISE, &codec->codec_settings.pp_denoise);
-                               speex_preprocess_ctl(context->pp, SPEEX_PREPROCESS_SET_DEREVERB, &codec->codec_settings.pp_dereverb);
-                               speex_preprocess_ctl(context->pp, SPEEX_PREPROCESS_SET_DEREVERB_DECAY, &codec->codec_settings.pp_dereverb_decay);
-                               speex_preprocess_ctl(context->pp, SPEEX_PREPROCESS_SET_DEREVERB_LEVEL, &codec->codec_settings.pp_dereverb_level);
+                               speex_preprocess_ctl(context->pp, SPEEX_PREPROCESS_SET_VAD, &context->codec_settings.pp_vad);
+                               speex_preprocess_ctl(context->pp, SPEEX_PREPROCESS_SET_AGC, &context->codec_settings.pp_agc);
+                               speex_preprocess_ctl(context->pp, SPEEX_PREPROCESS_SET_AGC_LEVEL, &context->codec_settings.pp_agc_level);
+                               speex_preprocess_ctl(context->pp, SPEEX_PREPROCESS_SET_DENOISE, &context->codec_settings.pp_denoise);
+                               speex_preprocess_ctl(context->pp, SPEEX_PREPROCESS_SET_DEREVERB, &context->codec_settings.pp_dereverb);
+                               speex_preprocess_ctl(context->pp, SPEEX_PREPROCESS_SET_DEREVERB_DECAY, &context->codec_settings.pp_dereverb_decay);
+                               speex_preprocess_ctl(context->pp, SPEEX_PREPROCESS_SET_DEREVERB_LEVEL, &context->codec_settings.pp_dereverb_level);
                        }
 
-                       if (!codec->codec_settings.abr && !codec->codec_settings.vbr) {
-                               speex_encoder_ctl(context->encoder_state, SPEEX_SET_QUALITY, &codec->codec_settings.quality);
-                               if (codec->codec_settings.vad) {
-                                       speex_encoder_ctl(context->encoder_state, SPEEX_SET_VAD, &codec->codec_settings.vad);
+                       if (!context->codec_settings.abr && !context->codec_settings.vbr) {
+                               speex_encoder_ctl(context->encoder_state, SPEEX_SET_QUALITY, &context->codec_settings.quality);
+                               if (context->codec_settings.vad) {
+                                       speex_encoder_ctl(context->encoder_state, SPEEX_SET_VAD, &context->codec_settings.vad);
                                }
                        }
-                       if (codec->codec_settings.vbr) {
-                               speex_encoder_ctl(context->encoder_state, SPEEX_SET_VBR, &codec->codec_settings.vbr);
-                               speex_encoder_ctl(context->encoder_state, SPEEX_SET_VBR_QUALITY, &codec->codec_settings.vbr_quality);
+                       if (context->codec_settings.vbr) {
+                               speex_encoder_ctl(context->encoder_state, SPEEX_SET_VBR, &context->codec_settings.vbr);
+                               speex_encoder_ctl(context->encoder_state, SPEEX_SET_VBR_QUALITY, &context->codec_settings.vbr_quality);
                        }
-                       if (codec->codec_settings.abr) {
-                               speex_encoder_ctl(context->encoder_state, SPEEX_SET_ABR, &codec->codec_settings.abr);
+                       if (context->codec_settings.abr) {
+                               speex_encoder_ctl(context->encoder_state, SPEEX_SET_ABR, &context->codec_settings.abr);
                        }
-                       if (codec->codec_settings.dtx) {
-                               speex_encoder_ctl(context->encoder_state, SPEEX_SET_DTX, &codec->codec_settings.dtx);
+                       if (context->codec_settings.dtx) {
+                               speex_encoder_ctl(context->encoder_state, SPEEX_SET_DTX, &context->codec_settings.dtx);
                        }
                }
 
                if (decoding) {
                        speex_bits_init(&context->decoder_bits);
                        context->decoder_state = speex_decoder_init(mode);
-                       if (codec->codec_settings.enhancement) {
-                               speex_decoder_ctl(context->decoder_state, SPEEX_SET_ENH, &codec->codec_settings.enhancement);
+                       if (context->codec_settings.enhancement) {
+                               speex_decoder_ctl(context->decoder_state, SPEEX_SET_ENH, &context->codec_settings.enhancement);
                        }
                }
 
@@ -178,7 +270,7 @@ static switch_status_t switch_speex_encode(switch_codec_t *codec,
 
        if (is_speech) {
                is_speech = speex_encode_int(context->encoder_state, buf, &context->encoder_bits)
-                       || !context->codec->codec_settings.dtx;
+                       || !context->codec_settings.dtx;
        } else {
                speex_bits_pack(&context->encoder_bits, 0, 5);
        }
@@ -270,6 +362,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_speex_load)
        /* connect my internal structure to the blank pointer passed to me */
        *module_interface = switch_loadable_module_create_module_interface(pool, modname);
        SWITCH_ADD_CODEC(codec_interface, "Speex");
+       codec_interface->parse_fmtp = switch_speex_fmtp_parse;
        for (counta = 1; counta <= 3; counta++) {
                for (countb = 1; countb > 0; countb--) {
                        switch_core_codec_add_implementation(pool, codec_interface, SWITCH_CODEC_TYPE_AUDIO,    /* enumeration defining the type of the codec */
index 58eef2918c094f2fc4e5690e09708e59597484a2..0cd4b27a51433c1832104fdc5a34a3c6951efad3 100644 (file)
@@ -577,6 +577,7 @@ struct private_object {
        switch_codec_t read_codec;
        switch_codec_t write_codec;
        uint32_t codec_ms;
+       uint32_t bitrate;
        switch_caller_profile_t *caller_profile;
        uint32_t timestamp_send;
        switch_rtp_t *rtp_session;
index 3dc90b9a68796a401b4bf2442843629b4269993e..9d4b0ae51b8b10cd93c62086dfd104b9d9f111dd 100644 (file)
@@ -205,7 +205,7 @@ void sofia_glue_set_local_sdp(private_object_t *tech_pvt, const char *ip, uint32
        switch_event_t *map = NULL, *ptmap = NULL;
        const char *b_sdp = NULL;
 
-       if ((b_sdp = switch_channel_get_variable(tech_pvt->channel, SWITCH_B_SDP_VARIABLE))) {
+       if (!tech_pvt->rm_encoding && (b_sdp = switch_channel_get_variable(tech_pvt->channel, SWITCH_B_SDP_VARIABLE))) {
                sofia_glue_sdp_map(b_sdp, &map, &ptmap);
        }
 
@@ -354,12 +354,18 @@ void sofia_glue_set_local_sdp(private_object_t *tech_pvt, const char *ip, uint32
                        rate = imp->samples_per_second;
 
                        if (map) {
-                               fmtp = switch_event_get_header(map, imp->iananame);
-                       }
-
+                               char key[128] = "";
+                               char *check = NULL;
+                               switch_snprintf(key, sizeof(key), "%s:%u", imp->iananame, imp->bits_per_second);
 
+                               if ((check = switch_event_get_header(map, key)) || (check = switch_event_get_header(map, imp->iananame))) {
+                                       fmtp = check;
+                               }
+                       }
+                       
                        switch_snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "a=rtpmap:%d %s/%d\n", imp->ianacode, imp->iananame, rate);
-                       if (imp->fmtp) {
+
+                       if (fmtp) {
                                switch_snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "a=fmtp:%d %s\n", imp->ianacode, fmtp);
                        }
                }
@@ -2535,24 +2541,26 @@ switch_status_t sofia_glue_tech_set_codec(private_object_t *tech_pvt, int force)
                }
        }
 
-       if (switch_core_codec_init(&tech_pvt->read_codec,
+       if (switch_core_codec_init_with_bitrate(&tech_pvt->read_codec,
                                                           tech_pvt->iananame,
                                                           tech_pvt->rm_fmtp,
                                                           tech_pvt->rm_rate,
                                                           tech_pvt->codec_ms,
                                                           1,
+                                                          tech_pvt->bitrate,
                                                           SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE | tech_pvt->profile->codec_flags,
                                                           NULL, switch_core_session_get_pool(tech_pvt->session)) != SWITCH_STATUS_SUCCESS) {
                switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_ERROR, "Can't load codec?\n");
                switch_goto_status(SWITCH_STATUS_FALSE, end);
        }
 
-       if (switch_core_codec_init(&tech_pvt->write_codec,
+       if (switch_core_codec_init_with_bitrate(&tech_pvt->write_codec,
                                                           tech_pvt->iananame,
                                                           tech_pvt->rm_fmtp,
                                                           tech_pvt->rm_rate,
                                                           tech_pvt->codec_ms,
                                                           1,
+                                                          tech_pvt->bitrate,
                                                           SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE | tech_pvt->profile->codec_flags,
                                                           NULL, switch_core_session_get_pool(tech_pvt->session)) != SWITCH_STATUS_SUCCESS) {
                switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_ERROR, "Can't load codec?\n");
@@ -2593,9 +2601,9 @@ switch_status_t sofia_glue_tech_set_codec(private_object_t *tech_pvt, int force)
                switch_goto_status(SWITCH_STATUS_FALSE, end);
        }
 
-       switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_DEBUG, "Set Codec %s %s/%ld %d ms %d samples\n",
+       switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_DEBUG, "Set Codec %s %s/%ld %d ms %d samples %d bits\n",
                                          switch_channel_get_name(tech_pvt->channel), tech_pvt->iananame, tech_pvt->rm_rate, tech_pvt->codec_ms,
-                                         tech_pvt->read_impl.samples_per_packet);
+                                         tech_pvt->read_impl.samples_per_packet, tech_pvt->read_impl.bits_per_second);
        tech_pvt->read_frame.codec = &tech_pvt->read_codec;
 
        tech_pvt->write_codec.agreed_pt = tech_pvt->agreed_pt;
@@ -3685,11 +3693,27 @@ switch_status_t sofia_glue_sdp_map(const char *r_sdp, switch_event_t **fmtp, swi
                        for (map = m->m_rtpmaps; map; map = map->rm_next) {
                                if (map->rm_encoding) {
                                        char buf[25] = "";
+                                       char key[128] = "";
+                                       char *br = NULL;
+
+                                       if (map->rm_fmtp) {
+                                               if ((br = strstr(map->rm_fmtp, "bitrate="))) {
+                                                       br += 8;
+                                               }
+                                       }
+
                                        switch_snprintf(buf, sizeof(buf), "%d", map->rm_pt);
-                                       switch_event_add_header_string(*pt, SWITCH_STACK_BOTTOM, map->rm_encoding, buf);
+
+                                       if (br) {
+                                               switch_snprintf(key, sizeof(key), "%s:%s", map->rm_encoding, br);
+                                       } else {
+                                               switch_snprintf(key, sizeof(key), "%s", map->rm_encoding);
+                                       }
                                        
+                                       switch_event_add_header_string(*pt, SWITCH_STACK_BOTTOM, key, buf);
+
                                        if (map->rm_fmtp) {
-                                               switch_event_add_header_string(*fmtp, SWITCH_STACK_BOTTOM, map->rm_encoding, map->rm_fmtp);
+                                               switch_event_add_header_string(*fmtp, SWITCH_STACK_BOTTOM, key, map->rm_fmtp);
                                        }
                                }
                        }
@@ -3809,7 +3833,6 @@ uint8_t sofia_glue_negotiate_sdp(switch_core_session_t *session, const char *r_s
        sdp_attribute_t *attr;
        int first = 0, last = 0;
        int ptime = 0, dptime = 0, maxptime = 0, dmaxptime = 0;
-       int codec_ms = 0;
        int sendonly = 0;
        int greedy = 0, x = 0, skip = 0, mine = 0;
        switch_channel_t *channel = switch_core_session_get_channel(session);
@@ -4129,8 +4152,12 @@ uint8_t sofia_glue_negotiate_sdp(switch_core_session_t *session, const char *r_s
                        for (map = m->m_rtpmaps; map; map = map->rm_next) {
                                int32_t i;
                                uint32_t near_rate = 0;
+                               uint32_t near_bit_rate = 0;
+                               switch_codec_interface_t *codec_interface;
                                const switch_codec_implementation_t *mimp = NULL, *near_match = NULL;
                                const char *rm_encoding;
+                               uint32_t map_bit_rate = 0;
+                               int codec_ms = 0;
 
                                if (x++ < skip) {
                                        continue;
@@ -4174,31 +4201,38 @@ uint8_t sofia_glue_negotiate_sdp(switch_core_session_t *session, const char *r_s
                                        ptime = switch_default_ptime(rm_encoding, map->rm_pt);
                                }
 
-                               if (!strcasecmp((char *) rm_encoding, "ilbc")) {
-                                       char *mode = NULL;
-                                       if (map->rm_fmtp && (mode = strstr(map->rm_fmtp, "mode=")) && (mode + 5)) {
-                                               codec_ms = atoi(mode + 5);
-                                       }
-                                       if (!codec_ms) {
-                                               /* default to 30 when no mode is defined for ilbc ONLY */
-                                               codec_ms = 30;
+                               /* This will try to use codec specific fmtp parser */
+                               if (map->rm_fmtp && (codec_interface = switch_loadable_module_get_codec_interface(rm_encoding)) != 0) {
+                                       switch_codec_fmtp_t codec_fmtp;
+                                       memset(&codec_fmtp, '\0', sizeof(struct switch_codec_fmtp));
+                                       codec_fmtp.actual_samples_per_second = map->rm_rate;
+                                       if (codec_interface->parse_fmtp && codec_interface->parse_fmtp(map->rm_fmtp, &codec_fmtp) == SWITCH_STATUS_SUCCESS) {
+                                               if (codec_fmtp.bits_per_second) {
+                                                       map_bit_rate = codec_fmtp.bits_per_second;
+                                               }
+                                               if (codec_fmtp.microseconds_per_packet) {
+                                                       ptime = (codec_fmtp.microseconds_per_packet / 1000);
+                                               }
                                        }
-                               } else {
-                                       codec_ms = ptime;
+                                       UNPROTECT_INTERFACE(codec_interface);
                                }
 
 
+                               if (!codec_ms) {
+                                       codec_ms = ptime;
+                               }
 
                                for (i = first; i < last && i < tech_pvt->num_codecs; i++) {
                                        const switch_codec_implementation_t *imp = tech_pvt->codecs[i];
+                                       uint32_t bit_rate = imp->bits_per_second;
                                        uint32_t codec_rate = imp->samples_per_second;
                                        if (imp->codec_type != SWITCH_CODEC_TYPE_AUDIO) {
                                                continue;
                                        }
 
-                                       switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Audio Codec Compare [%s:%d:%u:%d]/[%s:%d:%u:%d]\n",
-                                                                         rm_encoding, map->rm_pt, (int) map->rm_rate, codec_ms,
-                                                                         imp->iananame, imp->ianacode, codec_rate, imp->microseconds_per_packet / 1000);
+                                       switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Audio Codec Compare [%s:%d:%u:%d:%u]/[%s:%d:%u:%d:%u]\n",
+                                                                         rm_encoding, map->rm_pt, (int) map->rm_rate, codec_ms, map_bit_rate,
+                                                                         imp->iananame, imp->ianacode, codec_rate, imp->microseconds_per_packet / 1000, bit_rate);
                                        if ((zstr(map->rm_encoding) || (tech_pvt->profile->ndlb & PFLAG_NDLB_ALLOW_BAD_IANANAME)) && map->rm_pt < 96) {
                                                match = (map->rm_pt == imp->ianacode) ? 1 : 0;
                                        } else {
@@ -4211,8 +4245,13 @@ uint8_t sofia_glue_negotiate_sdp(switch_core_session_t *session, const char *r_s
                                                                                          "Bah HUMBUG! Sticking with %s@%uh@%ui\n",
                                                                                          imp->iananame, imp->samples_per_second, imp->microseconds_per_packet / 1000);
                                                } else {
-                                                       if ((codec_ms && codec_ms * 1000 != imp->microseconds_per_packet) || map->rm_rate != codec_rate) {
+                                                       if ((codec_ms && codec_ms * 1000 != imp->microseconds_per_packet) || map->rm_rate != codec_rate || (map_bit_rate && map_bit_rate != bit_rate) ) {
                                                                near_rate = map->rm_rate;
+                                                               if (map_bit_rate) {
+                                                                       near_bit_rate = map_bit_rate;
+                                                               } else {
+                                                                       near_bit_rate = bit_rate;
+                                                               }
                                                                near_match = imp;
                                                                match = 0;
                                                                continue;
@@ -4225,7 +4264,7 @@ uint8_t sofia_glue_negotiate_sdp(switch_core_session_t *session, const char *r_s
                                        }
                                }
 
-                               if (!match && near_match) {
+                               if (!match && near_match && !map->rm_next) {
                                        const switch_codec_implementation_t *search[1];
                                        char *prefs[1];
                                        char tmp[80];
@@ -4266,6 +4305,7 @@ uint8_t sofia_glue_negotiate_sdp(switch_core_session_t *session, const char *r_s
                                        tech_pvt->pt = (switch_payload_t) map->rm_pt;
                                        tech_pvt->rm_rate = map->rm_rate;
                                        tech_pvt->codec_ms = mimp->microseconds_per_packet / 1000;
+                                       tech_pvt->bitrate = mimp->bits_per_second;
                                        tech_pvt->remote_sdp_audio_ip = switch_core_session_strdup(session, (char *) connection->c_address);
                                        tech_pvt->rm_fmtp = switch_core_session_strdup(session, (char *) map->rm_fmtp);
                                        tech_pvt->remote_sdp_audio_port = (switch_port_t) m->m_port;
index ba5560129bd6abd5888cdca6dc3bba9df66674af..ece3fa27bb2b22477712b461a536a09f8df835e2 100644 (file)
@@ -1834,6 +1834,7 @@ SWITCH_DECLARE(void) switch_channel_event_set_basic_data(switch_channel_t *chann
        if (impl.iananame) {
                switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Channel-Read-Codec-Name", impl.iananame);
                switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Channel-Read-Codec-Rate", "%u", impl.actual_samples_per_second);
+               switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Channel-Read-Codec-Bit-Rate", "%d", impl.bits_per_second);
        }
 
        switch_core_session_get_write_impl(channel->session, &impl);
@@ -1841,6 +1842,7 @@ SWITCH_DECLARE(void) switch_channel_event_set_basic_data(switch_channel_t *chann
        if (impl.iananame) {
                switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Channel-Write-Codec-Name", impl.iananame);
                switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Channel-Write-Codec-Rate", "%u", impl.actual_samples_per_second);
+               switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Channel-Write-Codec-Bit-Rate", "%d", impl.bits_per_second);
        }
 
        /* Index Caller's Profile */
index ba84b0301c0fdcab88af0d87ab7919353fae5988..f21b7cb288428dd4acea4663ef5d1d1bac371f0e 100644 (file)
@@ -165,6 +165,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_set_read_codec(switch_core_s
                        switch_channel_event_set_data(session->channel, event);
                        switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "channel-read-codec-name", session->read_impl.iananame);
                        switch_event_add_header(event, SWITCH_STACK_BOTTOM, "channel-read-codec-rate", "%d", session->read_impl.actual_samples_per_second);
+                       switch_event_add_header(event, SWITCH_STACK_BOTTOM, "channel-read-codec-bit-rate", "%d", session->read_impl.bits_per_second);
                        if (session->read_impl.actual_samples_per_second != session->read_impl.samples_per_second) {
                                switch_event_add_header(event, SWITCH_STACK_BOTTOM, "channel-reported-read-codec-rate", "%d", session->read_impl.samples_per_second);
                        }
@@ -317,6 +318,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_set_write_codec(switch_core_
                        switch_channel_event_set_data(session->channel, event);
                        switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Channel-Write-Codec-Name", session->write_impl.iananame);
                        switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Channel-Write-Codec-Rate", "%d", session->write_impl.actual_samples_per_second);
+                       switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Channel-Write-codec-bit-rate", "%d", session->write_impl.bits_per_second);
                        if (session->write_impl.actual_samples_per_second != session->write_impl.samples_per_second) {
                                switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Channel-Reported-Write-Codec-Rate", "%d",
                                                                                session->write_impl.actual_samples_per_second);
@@ -494,8 +496,8 @@ SWITCH_DECLARE(switch_status_t) switch_core_codec_copy(switch_codec_t *codec, sw
        return SWITCH_STATUS_SUCCESS;
 }
 
-SWITCH_DECLARE(switch_status_t) switch_core_codec_init(switch_codec_t *codec, const char *codec_name, const char *fmtp,
-                                                                                                          uint32_t rate, int ms, int channels, uint32_t flags,
+SWITCH_DECLARE(switch_status_t) switch_core_codec_init_with_bitrate(switch_codec_t *codec, const char *codec_name, const char *fmtp,
+                                                                                                          uint32_t rate, int ms, int channels, uint32_t bitrate, uint32_t flags,
                                                                                                           const switch_codec_settings_t *codec_settings, switch_memory_pool_t *pool)
 {
        switch_codec_interface_t *codec_interface;
@@ -519,7 +521,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_codec_init(switch_codec_t *codec, co
        /* If no specific codec interval is requested opt for 20ms above all else because lots of stuff assumes it */
        if (!ms) {
                for (iptr = codec_interface->implementations; iptr; iptr = iptr->next) {
-                       if ((!rate || rate == iptr->samples_per_second) &&
+                       if ((!rate || rate == iptr->samples_per_second) && (!bitrate || bitrate == iptr->bits_per_second) &&
                                (20 == (iptr->microseconds_per_packet / 1000)) && (!channels || channels == iptr->number_of_channels)) {
                                implementation = iptr;
                                goto found;
@@ -529,7 +531,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_codec_init(switch_codec_t *codec, co
 
        /* Either looking for a specific interval or there was no interval specified and there wasn't one @20ms available */
        for (iptr = codec_interface->implementations; iptr; iptr = iptr->next) {
-               if ((!rate || rate == iptr->samples_per_second) &&
+               if ((!rate || rate == iptr->samples_per_second) && (!bitrate || bitrate == iptr->bits_per_second) &&
                        (!ms || ms == (iptr->microseconds_per_packet / 1000)) && (!channels || channels == iptr->number_of_channels)) {
                        implementation = iptr;
                        break;
index 0cc4da3f1361dddd8abf61acb24296f048762938..7e427b5f03c5f8aaa6093c65f9394950966a3bb7 100644 (file)
@@ -1142,11 +1142,13 @@ static void core_event_handler(switch_event_t *event)
        case SWITCH_EVENT_CODEC:
                new_sql() =
                        switch_mprintf
-                       ("update channels set read_codec='%q',read_rate='%q',write_codec='%q',write_rate='%q' where uuid='%q' and hostname='%q'",
+                       ("update channels set read_codec='%q',read_rate='%q',read_bit_rate='%q',write_codec='%q',write_rate='%q',write_bit_rate='%q' where uuid='%q' and hostname='%q'",
                         switch_event_get_header_nil(event, "channel-read-codec-name"),
                         switch_event_get_header_nil(event, "channel-read-codec-rate"),
+                        switch_event_get_header_nil(event, "channel-read-codec-bit-rate"),
                         switch_event_get_header_nil(event, "channel-write-codec-name"),
                         switch_event_get_header_nil(event, "channel-write-codec-rate"),
+                        switch_event_get_header_nil(event, "channel-write-codec-bit-rate"),
                         switch_event_get_header_nil(event, "unique-id"), switch_core_get_variable("hostname"));
                break;
        case SWITCH_EVENT_CHANNEL_HOLD:
@@ -1471,8 +1473,10 @@ static char create_channels_sql[] =
        "   context VARCHAR(128),\n"
        "   read_codec  VARCHAR(128),\n"
        "   read_rate  VARCHAR(32),\n"
+       "   read_bit_rate  VARCHAR(32),\n"
        "   write_codec  VARCHAR(128),\n"
        "   write_rate  VARCHAR(32),\n"
+       "   write_bit_rate  VARCHAR(32),\n"
        "   secure VARCHAR(32),\n"
        "   hostname VARCHAR(256),\n"
        "   presence_id VARCHAR(4096),\n"
@@ -1613,7 +1617,7 @@ switch_status_t switch_core_sqldb_start(switch_memory_pool_t *pool, switch_bool_
        case SCDB_TYPE_ODBC:
                {
                        char *err;
-                       switch_cache_db_test_reactive(dbh, "select call_uuid from channels", "DROP TABLE channels", create_channels_sql);
+                       switch_cache_db_test_reactive(dbh, "select call_uuid, read_bit_rate from channels", "DROP TABLE channels", create_channels_sql);
                        switch_cache_db_test_reactive(dbh, "select call_uuid from calls", "DROP TABLE calls", create_calls_sql);
                        switch_cache_db_test_reactive(dbh, "select ikey from interfaces", "DROP TABLE interfaces", create_interfaces_sql);
                        switch_cache_db_test_reactive(dbh, "select hostname from tasks", "DROP TABLE tasks", create_tasks_sql);
index fc0db74f0fb3924124759f5f77567c7eeabdd958..5466c189835801169dc6299a5518d12029e5931a 100644 (file)
@@ -183,8 +183,8 @@ static switch_status_t switch_loadable_module_process(char *key, switch_loadable
                                if (load_interface) {
                                        for (impl = ptr->implementations; impl; impl = impl->next) {
                                                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE,
-                                                                                 "Adding Codec '%s' (%s) %dhz %dms\n",
-                                                                                 impl->iananame, ptr->interface_name, impl->actual_samples_per_second, impl->microseconds_per_packet / 1000);
+                                                                                 "Adding Codec '%s' (%s) %dhz %dms %dbps\n",
+                                                                                 impl->iananame, ptr->interface_name, impl->actual_samples_per_second, impl->microseconds_per_packet / 1000, impl->bits_per_second);
                                                if (!switch_core_hash_find(loadable_modules.codec_hash, impl->iananame)) {
                                                        switch_core_hash_insert(loadable_modules.codec_hash, impl->iananame, (const void *) ptr);
                                                }
@@ -1600,7 +1600,7 @@ SWITCH_DECLARE(int) switch_loadable_module_get_codecs_sorted(const switch_codec_
 
        for (x = 0; x < preflen; x++) {
                char *cur, *last = NULL, *next = NULL, *name, *p, buf[256];
-               uint32_t interval = 0, rate = 0;
+               uint32_t interval = 0, rate = 0, bit = 0;
 
                switch_copy_string(buf, prefs[x], sizeof(buf));
                last = name = next = cur = buf;
@@ -1620,6 +1620,8 @@ SWITCH_DECLARE(int) switch_loadable_module_get_codecs_sorted(const switch_codec_
                                        interval = atoi(cur);
                                } else if ((strchr(cur, 'k') || strchr(cur, 'h'))) {
                                        rate = atoi(cur);
+                               } else if (strchr(cur, 'b')) {
+                                       bit = atoi(cur);
                                }
                        }
                        cur = next;
@@ -1643,6 +1645,11 @@ SWITCH_DECLARE(int) switch_loadable_module_get_codecs_sorted(const switch_codec_
                                        if (((!rate && (uint32_t) imp->samples_per_second != 8000) || (rate && (uint32_t) imp->samples_per_second != rate))) {
                                                continue;
                                        }
+
+                                       if (bit && (uint32_t) imp->bits_per_second != bit) {
+                                               continue;
+                                       }
+
                                }
 
 
@@ -1666,6 +1673,11 @@ SWITCH_DECLARE(int) switch_loadable_module_get_codecs_sorted(const switch_codec_
                                        if (rate && (uint32_t) imp->samples_per_second != rate) {
                                                continue;
                                        }
+
+                                       if (bit && (uint32_t) imp->bits_per_second != bit) {
+                                               continue;
+                                       }
+                                       
                                }
 
                                array[i++] = imp;