FS-8364: mod_codec2 : improvements, add extra modes: 3200,1400,1200. add config file.

This commit is contained in:
Dragos Oancea 2015-10-19 20:56:44 -04:00
parent 8fc1acbb6c
commit 611449f4b3
1 changed files with 94 additions and 13 deletions

View File

@ -23,6 +23,7 @@
*
* Contributor(s):
* Mathieu Rene <mrene@avgs.ca>
* Dragos Oancea <droancea@yahoo.com>
*
* 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 */