]> git.ipfire.org Git - thirdparty/freeswitch.git/commitdiff
FS-8364: mod_codec2 : improvements, add extra modes: 3200,1400,1200. add config file.
authorDragos Oancea <droancea@yahoo.com>
Tue, 20 Oct 2015 00:56:44 +0000 (20:56 -0400)
committerDragos Oancea <droancea@yahoo.com>
Fri, 27 Nov 2015 17:09:29 +0000 (12:09 -0500)
src/mod/codecs/mod_codec2/mod_codec2.c

index cee954499a81c11117c7bc4f4c4af244d79fff0c..998fb3c3e4f529352d442172023f7b6bc59814fd 100644 (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,14 +91,39 @@ 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;
        
@@ -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 */