From 611449f4b36f6bf0ab74984f10d1265e864b7f79 Mon Sep 17 00:00:00 2001 From: Dragos Oancea Date: Mon, 19 Oct 2015 20:56:44 -0400 Subject: [PATCH] FS-8364: mod_codec2 : improvements, add extra modes: 3200,1400,1200. add config file. --- src/mod/codecs/mod_codec2/mod_codec2.c | 107 ++++++++++++++++++++++--- 1 file changed, 94 insertions(+), 13 deletions(-) diff --git a/src/mod/codecs/mod_codec2/mod_codec2.c b/src/mod/codecs/mod_codec2/mod_codec2.c index cee954499a..998fb3c3e4 100644 --- a/src/mod/codecs/mod_codec2/mod_codec2.c +++ b/src/mod/codecs/mod_codec2/mod_codec2.c @@ -23,6 +23,7 @@ * * Contributor(s): * Mathieu Rene + * Dragos Oancea * * mod_codec2 -- FreeSWITCH CODEC2 Module * @@ -51,6 +52,10 @@ SWITCH_MODULE_DEFINITION(mod_codec2, mod_codec2_load, NULL, NULL); struct codec2_context { void *encoder; void *decoder; + int mode; /* codec2 operation mode */ + int nbit; /* nr of bits per frame */ + int nbyte; /* nr of bytes per frame */ + int nsam; /* nr of samples per frame */ #ifdef LOG_DATA FILE *encoder_in; FILE *encoder_out; @@ -61,6 +66,12 @@ struct codec2_context { #endif }; +struct { + int mode; + int ptime; + int samples_per_frame; +} codec2_prefs; + #ifdef LOG_DATA static int c2_count = 0; #endif @@ -80,15 +91,40 @@ static switch_status_t switch_codec2_init(switch_codec_t *codec, switch_codec_fl if (!(context = switch_core_alloc(codec->memory_pool, sizeof(*context)))) { return SWITCH_STATUS_FALSE; } + + if (!codec2_prefs.mode) { + codec2_prefs.mode = CODEC2_MODE_2400; + } + + if (codec2_prefs.mode == 3200) { + context->mode = CODEC2_MODE_3200; + } else if (codec2_prefs.mode == 2400) { + context->mode = CODEC2_MODE_2400; + } else if (codec2_prefs.mode == 1400) { + context->mode = CODEC2_MODE_1400; + } else if (codec2_prefs.mode == 1200) { + context->mode = CODEC2_MODE_1200; + } else { + /* 3200 might be better for VOIP, but forcing 2400 for backwards compatibility */ + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "mode not supported, forcing CODEC2_MODE_2400. You can try mode 3200 too!\n"); + context->mode = CODEC2_MODE_2400; + } if (encoding) { - context->encoder = codec2_create(CODEC2_MODE_2400); + context->encoder = codec2_create(context->mode); } if (decoding) { - context->decoder = codec2_create(CODEC2_MODE_2400); + context->decoder = codec2_create(context->mode); } + context->nsam = codec2_samples_per_frame(context->encoder); + if (!context->nsam) { + context->nsam = CODEC2_SAMPLES_PER_FRAME; + } + context->nbit = codec2_bits_per_frame(context->encoder); + context->nbyte = (context->nbit + 7) / 8; + codec->private_info = context; #ifdef LOG_DATA @@ -136,7 +172,7 @@ static switch_status_t switch_codec2_encode(switch_codec_t *codec, switch_codec_ { struct codec2_context *context = codec->private_info; - codec2_assert(decoded_data_len == CODEC2_SAMPLES_PER_FRAME * 2); + codec2_assert(decoded_data_len == context->nsam * 2); #ifdef LOG_DATA fwrite(decoded_data, decoded_data_len, 1, context->encoder_in); @@ -148,11 +184,11 @@ static switch_status_t switch_codec2_encode(switch_codec_t *codec, switch_codec_ #ifdef LOG_DATA fwrite(encode_buf, sizeof(encode_buf), 1, context->encoder_out_unpacked); fflush(context->encoder_out_unpacked); - fwrite(encoded_data, 8, 1, context->encoder_out); + fwrite(encoded_data, context->nbyte, 1, context->encoder_out); fflush(context->encoder_out); #endif - *encoded_data_len = 6; + *encoded_data_len = context->nbyte; return SWITCH_STATUS_SUCCESS; } @@ -169,7 +205,7 @@ static switch_status_t switch_codec2_decode(switch_codec_t *codec, { struct codec2_context *context = codec->private_info; - codec2_assert(encoded_data_len == 8 /* aligned to 8 */); + codec2_assert(encoded_data_len == 8); #ifdef LOG_DATA fwrite(encoded_data, encoded_data_len, 1, context->decoder_in); @@ -181,11 +217,11 @@ static switch_status_t switch_codec2_decode(switch_codec_t *codec, codec2_decode(context->decoder, decoded_data, encoded_data); #ifdef LOG_DATA - fwrite(decoded_data, CODEC2_SAMPLES_PER_FRAME, 2, context->decoder_out); + fwrite(decoded_data, context->nsam, 2, context->decoder_out); fflush(context->decoder_out); #endif - *decoded_data_len = CODEC2_SAMPLES_PER_FRAME * 2; /* 160 samples */ + *decoded_data_len = context->nsam * 2; /* eg: 160 samples for 3200,2400 */ return SWITCH_STATUS_SUCCESS; } @@ -224,13 +260,58 @@ static switch_status_t switch_codec2_destroy(switch_codec_t *codec) return SWITCH_STATUS_SUCCESS; } +static switch_status_t codec2_load_config(switch_bool_t reload) { + + char *cf = "codec2.conf"; + switch_xml_t cfg, xml = NULL, param, settings; + switch_status_t status = SWITCH_STATUS_SUCCESS; + + codec2_prefs.mode = 2400 ; + + if (!(xml = switch_xml_open_cfg(cf, &cfg, NULL))) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Opening of %s failed\n", cf); + return status; + } + + if ((settings = switch_xml_child(cfg, "settings"))) { + for (param = switch_xml_child(settings, "param"); param; param = param->next) { + char *key = (char *) switch_xml_attr_soft(param, "name"); + char *val = (char *) switch_xml_attr_soft(param, "value"); + + if (!strcasecmp(key, "mode") && !zstr(val)) { + codec2_prefs.mode = atoi(val); + } + } + } + + if (xml) { + switch_xml_free(xml); + } + + return status; +} + SWITCH_MODULE_LOAD_FUNCTION(mod_codec2_load) { switch_codec_interface_t *codec_interface; + switch_status_t status = SWITCH_STATUS_SUCCESS; + + if ((status = codec2_load_config(SWITCH_FALSE)) != SWITCH_STATUS_SUCCESS) { + return status; + } *module_interface = switch_loadable_module_create_module_interface(pool, modname); + + /*there is no API call to retrieve ptime per mode, so hardcoding here*/ + if ((codec2_prefs.mode == 3200) ||(codec2_prefs.mode == 2400)) { + codec2_prefs.ptime = 20000; + codec2_prefs.samples_per_frame = CODEC2_SAMPLES_PER_FRAME; + } else { + codec2_prefs.ptime = 40000; + codec2_prefs.samples_per_frame = CODEC2_SAMPLES_PER_FRAME * 2; + } - SWITCH_ADD_CODEC(codec_interface, "CODEC2 2400bps"); + SWITCH_ADD_CODEC(codec_interface, "CODEC2 3200/2400/1400/1200bps"); switch_core_codec_add_implementation(pool, codec_interface, SWITCH_CODEC_TYPE_AUDIO, @@ -239,10 +320,10 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_codec2_load) NULL, 8000, /* samples/sec */ 8000, /* samples/sec */ - 2400, /* bps */ - 20000, /* ptime */ - CODEC2_SAMPLES_PER_FRAME, /* samples decoded */ - CODEC2_SAMPLES_PER_FRAME*2, /* bytes decoded */ + codec2_prefs.mode, /* bps */ + codec2_prefs.ptime, /* ptime */ + codec2_prefs.samples_per_frame, /* samples decoded */ + codec2_prefs.samples_per_frame * 2, /* bytes decoded */ 0, /* bytes encoded */ 1, /* channels */ 1, /* frames/packet */