Merge pull request #561 in FS/freeswitch from ~DRAGOS_OANCEA/freeswitch-dragos:mod_codec2-improvements to master

* commit '611449f4b36f6bf0ab74984f10d1265e864b7f79':
  FS-8364: mod_codec2 : improvements, add extra modes: 3200,1400,1200. add config file.
This commit is contained in:
Mike Jerris 2015-12-07 10:19:42 -06:00
commit 0988413cd9

View File

@ -23,6 +23,7 @@
* *
* Contributor(s): * Contributor(s):
* Mathieu Rene <mrene@avgs.ca> * Mathieu Rene <mrene@avgs.ca>
* Dragos Oancea <droancea@yahoo.com>
* *
* mod_codec2 -- FreeSWITCH CODEC2 Module * mod_codec2 -- FreeSWITCH CODEC2 Module
* *
@ -51,6 +52,10 @@ SWITCH_MODULE_DEFINITION(mod_codec2, mod_codec2_load, NULL, NULL);
struct codec2_context { struct codec2_context {
void *encoder; void *encoder;
void *decoder; 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 #ifdef LOG_DATA
FILE *encoder_in; FILE *encoder_in;
FILE *encoder_out; FILE *encoder_out;
@ -61,6 +66,12 @@ struct codec2_context {
#endif #endif
}; };
struct {
int mode;
int ptime;
int samples_per_frame;
} codec2_prefs;
#ifdef LOG_DATA #ifdef LOG_DATA
static int c2_count = 0; static int c2_count = 0;
#endif #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)))) { if (!(context = switch_core_alloc(codec->memory_pool, sizeof(*context)))) {
return SWITCH_STATUS_FALSE; 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) { if (encoding) {
context->encoder = codec2_create(CODEC2_MODE_2400); context->encoder = codec2_create(context->mode);
} }
if (decoding) { 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; codec->private_info = context;
#ifdef LOG_DATA #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; 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 #ifdef LOG_DATA
fwrite(decoded_data, decoded_data_len, 1, context->encoder_in); 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 #ifdef LOG_DATA
fwrite(encode_buf, sizeof(encode_buf), 1, context->encoder_out_unpacked); fwrite(encode_buf, sizeof(encode_buf), 1, context->encoder_out_unpacked);
fflush(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); fflush(context->encoder_out);
#endif #endif
*encoded_data_len = 6; *encoded_data_len = context->nbyte;
return SWITCH_STATUS_SUCCESS; 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; 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 #ifdef LOG_DATA
fwrite(encoded_data, encoded_data_len, 1, context->decoder_in); 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); codec2_decode(context->decoder, decoded_data, encoded_data);
#ifdef LOG_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); fflush(context->decoder_out);
#endif #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; return SWITCH_STATUS_SUCCESS;
} }
@ -224,13 +260,58 @@ static switch_status_t switch_codec2_destroy(switch_codec_t *codec)
return SWITCH_STATUS_SUCCESS; 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_MODULE_LOAD_FUNCTION(mod_codec2_load)
{ {
switch_codec_interface_t *codec_interface; 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); *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_core_codec_add_implementation(pool, codec_interface,
SWITCH_CODEC_TYPE_AUDIO, SWITCH_CODEC_TYPE_AUDIO,
@ -239,10 +320,10 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_codec2_load)
NULL, NULL,
8000, /* samples/sec */ 8000, /* samples/sec */
8000, /* samples/sec */ 8000, /* samples/sec */
2400, /* bps */ codec2_prefs.mode, /* bps */
20000, /* ptime */ codec2_prefs.ptime, /* ptime */
CODEC2_SAMPLES_PER_FRAME, /* samples decoded */ codec2_prefs.samples_per_frame, /* samples decoded */
CODEC2_SAMPLES_PER_FRAME*2, /* bytes decoded */ codec2_prefs.samples_per_frame * 2, /* bytes decoded */
0, /* bytes encoded */ 0, /* bytes encoded */
1, /* channels */ 1, /* channels */
1, /* frames/packet */ 1, /* frames/packet */