]> git.ipfire.org Git - thirdparty/freeswitch.git/commitdiff
FS-4037 --resolve
authorAnthony Minessale <anthm@freeswitch.org>
Wed, 11 Apr 2012 20:31:56 +0000 (15:31 -0500)
committerAnthony Minessale <anthm@freeswitch.org>
Wed, 11 Apr 2012 20:31:56 +0000 (15:31 -0500)
src/mod/codecs/mod_speex/mod_speex.c

index aaec0a6602df1126530d22a9822c8372ded513d7..ab9a044b53a15edb2f20c2fde21794eed6201569 100644 (file)
@@ -117,51 +117,143 @@ struct speex_context {
 
 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));
-               }
+       speex_codec_settings_t *codec_settings = NULL;
+       int x, argc;
+       char *argv[10];
+       char *fmtp_dup = NULL;
 
-               if (fmtp) {
-                       int x, argc;
-                       char *argv[10];
-                       char *fmtp_dup = strdup(fmtp);
+       if (!codec_fmtp) {
+               return SWITCH_STATUS_FALSE;
+       }
 
-                       switch_assert(fmtp_dup);
+       /* load default settings */
+       if (codec_fmtp->private_info) {
+               codec_settings = codec_fmtp->private_info;
+               memcpy(codec_settings, &default_codec_settings, sizeof(*codec_settings));
+       } else {
+               switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "codec_fmtp->private_info is NULL\n");
+               return SWITCH_STATUS_SUCCESS;
+       }
 
-                       argc = switch_separate_string(fmtp_dup, ';', argv, (sizeof(argv) / sizeof(argv[0])));
+       if (!fmtp) {
+               return SWITCH_STATUS_SUCCESS;
+       }
 
-                       for (x = 0; x < argc; x++) {
-                               char *data = argv[x];
-                               char *arg;
-                               switch_assert(data);
-                               while (*data == ' ') {
-                                       data++;
+       switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "got fmtp: %s\n", fmtp);
+
+       fmtp_dup = strdup(fmtp);
+       switch_assert(fmtp_dup);
+
+       /* parse ; separated fmtp args */
+       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, '='))) {
+                       continue;
+               }
+               *arg++ = '\0';
+               if (zstr(arg)) {
+                       continue;
+               }
+
+               if (!strcasecmp("vbr", data)) {
+                       /* vbr can be on/off/vad */
+                       if (!strcasecmp("vad", arg)) {
+                               switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "enabling speex vbr=vad\n");
+                               codec_settings->vbr = 0;
+                               codec_settings->vad = 1;
+                               codec_settings->pp_vad = 1;
+                       } else {
+                               if (switch_true(arg)) {
+                                       switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "enabling speex vbr\n");
+                                       codec_settings->vbr = 1;
+                                       codec_settings->vad = 0;
+                                       codec_settings->pp_vad = 1;
+                               } else {
+                                       switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "disabling speex vbr\n");
+                                       codec_settings->vbr = 0;
+                                       codec_settings->vad = 0;
+                                       codec_settings->pp_vad = 0;
                                }
-                               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);
-                                          }
-                                          }
-                                        */                     
+                       }
+               } else if (!strcasecmp("cng", data)) {
+                       /* TODO don't know how to turn on CNG */
+                       switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "speex cng is unsupported\n");
+               } else if (!strcasecmp("mode", data)) {
+                       /* mode is a comma-separate list of preferred modes.  Use the first mode in the list */
+                       char *arg_dup;
+                       char *mode[2];
+                       if (!strncasecmp("any", arg, 3)) {
+                               /* "any", keep the default setting */
+                               continue;
+                       }
+                       arg_dup = strdup(arg);
+                       if (switch_separate_string(arg_dup, ',', mode, (sizeof(mode) / sizeof(mode[0])))) {
+                               int mode_num = -1;
+                               char *mode_str = mode[0];
+                               if (mode_str[0] == '"') {
+                                       switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "mode starts with \"\n");
+                                       mode_str++;
+                               }
+                               if (switch_is_number(mode_str)) {
+                                       mode_num = atoi(mode_str);
+                               }
+                               /* TODO there might be a way to set the mode directly instead of changing the quality */
+                               if (codec_fmtp->actual_samples_per_second == 8000) {
+                                       switch (mode_num) {
+                                       case 1:
+                                               codec_settings->quality = 0;
+                                               break;
+                                       case 2:
+                                               codec_settings->quality = 2;
+                                               break;
+                                       case 3:
+                                               codec_settings->quality = 4;
+                                               break;
+                                       case 4:
+                                               codec_settings->quality = 6;
+                                               break;
+                                       case 5:
+                                               codec_settings->quality = 8;
+                                               break;
+                                       case 6:
+                                               codec_settings->quality = 9;
+                                               break;
+                                       case 7:
+                                               codec_settings->quality = 10;
+                                               break;
+                                       case 8:
+                                               codec_settings->quality = 1;
+                                               break;
+                                       default:
+                                               switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "ignoring invalid speex/8000 mode %s\n", mode_str);
+                                               continue;
+                                       }
+                                       switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "choosing speex/8000 mode %s\n", mode_str);
+                                       codec_settings->quality = codec_settings->quality;
+                                       codec_settings->vbr_quality = codec_settings->quality;
+                               } else {
+                                       if (mode_num >= 0 && mode_num <= 10) {
+                                               switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "choosing speex/%d mode %s\n", codec_fmtp->actual_samples_per_second, mode_str);
+                                               codec_settings->quality = mode_num;
+                                               codec_settings->vbr_quality = mode_num;
+                                       } else {
+                                               switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "ignoring invalid speex/%d mode %s\n", codec_fmtp->actual_samples_per_second, mode_str);
+                                               continue;
+                                       }
                                }
                        }
-                       free(fmtp_dup);
+                       free(arg_dup);
                }
-               /*codec_fmtp->bits_per_second = bit_rate;*/
-               return SWITCH_STATUS_SUCCESS;
        }
-       return SWITCH_STATUS_FALSE;
+       free(fmtp_dup);
+       /*codec_fmtp->bits_per_second = bit_rate;*/
+       return SWITCH_STATUS_SUCCESS;
 }
 
 
@@ -182,6 +274,7 @@ static switch_status_t switch_speex_init(switch_codec_t *codec, switch_codec_fla
 
                memset(&codec_fmtp, '\0', sizeof(struct switch_codec_fmtp));
                codec_fmtp.private_info = &codec_settings;
+               codec_fmtp.actual_samples_per_second = codec->implementation->actual_samples_per_second;
                switch_speex_fmtp_parse(codec->fmtp_in, &codec_fmtp);
 
                memcpy(&context->codec_settings, &codec_settings, sizeof(context->codec_settings));
@@ -205,11 +298,24 @@ static switch_status_t switch_speex_init(switch_codec_t *codec, switch_codec_fla
                        speex_encoder_ctl(context->encoder_state, SPEEX_GET_FRAME_SIZE, &context->encoder_frame_size);
                        speex_encoder_ctl(context->encoder_state, SPEEX_SET_COMPLEXITY, &context->codec_settings.complexity);
                        if (context->codec_settings.preproc) {
+                               switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "preprocessor on\n");
                                context->pp = speex_preprocess_state_init(context->encoder_frame_size, codec->implementation->actual_samples_per_second);
+                               if (context->codec_settings.pp_vad) {
+                                       switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "preprocessor vad on\n");
+                               }
                                speex_preprocess_ctl(context->pp, SPEEX_PREPROCESS_SET_VAD, &context->codec_settings.pp_vad);
+                               if (context->codec_settings.pp_agc) {
+                                       switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "preprocessor agc on\n");
+                               }
                                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);
+                               if (context->codec_settings.pp_denoise) {
+                                       switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "preprocessor denoise on\n");
+                               }
                                speex_preprocess_ctl(context->pp, SPEEX_PREPROCESS_SET_DENOISE, &context->codec_settings.pp_denoise);
+                               if (context->codec_settings.pp_dereverb) {
+                                       switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "preprocessor dereverb on\n");
+                               }
                                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);
@@ -218,17 +324,21 @@ static switch_status_t switch_speex_init(switch_codec_t *codec, switch_codec_fla
                        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) {
+                                       switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "vad on\n");
                                        speex_encoder_ctl(context->encoder_state, SPEEX_SET_VAD, &context->codec_settings.vad);
                                }
                        }
                        if (context->codec_settings.vbr) {
+                               switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "vbr on\n");
                                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 (context->codec_settings.abr) {
+                               switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "abr on\n");
                                speex_encoder_ctl(context->encoder_state, SPEEX_SET_ABR, &context->codec_settings.abr);
                        }
                        if (context->codec_settings.dtx) {
+                               switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "dtx on\n");
                                speex_encoder_ctl(context->encoder_state, SPEEX_SET_DTX, &context->codec_settings.dtx);
                        }
                }
@@ -243,6 +353,7 @@ static switch_status_t switch_speex_init(switch_codec_t *codec, switch_codec_fla
 
 
 
+               switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "initialized Speex codec \n");
                codec->private_info = context;
                return SWITCH_STATUS_SUCCESS;
        }
@@ -279,17 +390,15 @@ static switch_status_t switch_speex_encode(switch_codec_t *codec,
 
        if (is_speech) {
                switch_clear_flag(context, SWITCH_CODEC_FLAG_SILENCE);
-               *flag |= SWITCH_CODEC_FLAG_SILENCE_STOP;
                *flag &= ~SFF_CNG;
        } else {
                if (switch_test_flag(context, SWITCH_CODEC_FLAG_SILENCE)) {
                        *encoded_data_len = 0;
-                       *flag |= SWITCH_CODEC_FLAG_SILENCE | SFF_CNG;
+                       *flag |= SFF_CNG;
                        return SWITCH_STATUS_SUCCESS;
                }
 
                switch_set_flag(context, SWITCH_CODEC_FLAG_SILENCE);
-               *flag |= SWITCH_CODEC_FLAG_SILENCE_START;
        }