]> git.ipfire.org Git - thirdparty/freeswitch.git/commitdiff
codec2: working prototype, still for testing only
authorMathieu Rene <mrene@avgs.ca>
Tue, 21 Sep 2010 14:57:34 +0000 (10:57 -0400)
committerMathieu Rene <mrene@avgs.ca>
Tue, 21 Sep 2010 14:57:34 +0000 (10:57 -0400)
src/mod/codecs/mod_codec2/mod_codec2.c

index 65780e8a74a73e436ea26fe02925d9c0fd3dfb13..e0a7ff63801a87fb8f71a57c4a76b5c2c0eab907 100644 (file)
@@ -22,6 +22,7 @@
  * the Initial Developer. All Rights Reserved.
  *
  * Contributor(s):
+ * Mathieu Rene <mrene@avgs.ca>
  *
  * mod_codec2 -- FreeSWITCH CODEC2 Module
  *
 #include <switch.h>
 #include <codec2.h>
 
+/* Uncomment to log input/output data for debugging 
+#define LOG_DATA 
+#define CODEC2_DEBUG
+*/
+
+#ifdef CODEC2_DEBUG
+#define codec2_assert(_x) switch_assert(_x)
+#else
+#define codec2_assert(_x) 
+#endif
+
 SWITCH_MODULE_LOAD_FUNCTION(mod_codec2_load);
 
 SWITCH_MODULE_DEFINITION(mod_codec2, mod_codec2_load, NULL, NULL);
@@ -37,8 +49,47 @@ SWITCH_MODULE_DEFINITION(mod_codec2, mod_codec2_load, NULL, NULL);
 struct codec2_context {
        void *encoder;
        void *decoder;
+#ifdef LOG_DATA        
+       FILE *encoder_in;
+       FILE *encoder_out;
+       FILE *encoder_out_unpacked;
+       FILE *decoder_in;
+       FILE *decoder_in_unpacked;
+       FILE *decoder_out;
+#endif
 };
 
+#ifdef LOG_DATA
+static int c2_count = 0;
+#endif
+
+static void pack(uint8_t *dst, char* bits, int n)
+{
+       int i;
+       
+       for (i = 0; i < n; i++) {
+               int index = i / 8;
+               int bit = i % 8;
+
+               if (bits[i]) {
+                       dst[index] |= (1 << bit);
+               } else {
+                       dst[index] &= ~(1 << bit);
+               }
+       }
+}
+
+static void unpack(uint8_t *src, char* bits, int n) 
+{
+       int i;
+       for (i = 0; i < n; i++) {
+               int index = i / 8;
+               int bit = i % 8;
+               
+               bits[i] = !!(src[index] & (1 << bit));
+       }
+}
+
 static switch_status_t switch_codec2_init(switch_codec_t *codec, switch_codec_flag_t flags, const switch_codec_settings_t *codec_settings)
 {
        uint32_t encoding, decoding;
@@ -54,10 +105,47 @@ 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;
        }
-       context->encoder = codec2_create();
-       context->decoder = codec2_create();
+       
+       if (encoding) {
+               context->encoder = codec2_create();             
+       }
+       
+       if (decoding) {
+               context->decoder = codec2_create();
+       }
 
        codec->private_info = context;
+       
+#ifdef LOG_DATA                
+       {
+               
+               int c = c2_count++;
+               char buf[1024];
+               
+               switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Logging as /tmp/c2-%d-*\n", c);
+               
+               if (encoding) {
+                       snprintf(buf, sizeof(buf), "/tmp/c2-%d-enc-in", c);
+                       context->encoder_in = fopen(buf, "w");
+               
+                       snprintf(buf, sizeof(buf), "/tmp/c2-%d-enc-out", c);
+                       context->encoder_out = fopen(buf, "w");
+               
+                       snprintf(buf, sizeof(buf), "/tmp/c2-%d-enc-out-unpacked", c);
+                       context->encoder_out_unpacked = fopen(buf, "w");
+               }
+               if (decoding) {
+                       snprintf(buf, sizeof(buf), "/tmp/c2-%d-dec-in", c);
+                       context->decoder_in = fopen(buf, "w");
+               
+                       snprintf(buf, sizeof(buf), "/tmp/c2-%d-dec-out", c);
+                       context->decoder_out = fopen(buf, "w");
+               
+                       snprintf(buf, sizeof(buf), "/tmp/c2-%d-dec-out-unpacked", c);
+                       context->decoder_in_unpacked = fopen(buf, "w");
+               }
+       }
+#endif
 
        return SWITCH_STATUS_SUCCESS;
 }
@@ -72,13 +160,47 @@ static switch_status_t switch_codec2_encode(switch_codec_t *codec, switch_codec_
                                                                                  unsigned int *flag)
 {
        struct codec2_context *context = codec->private_info;
+       char encode_buf[CODEC2_BITS_PER_FRAME];
        
-       switch_assert(decoded_data_len == 160 * 2);
+       codec2_assert(decoded_data_len == CODEC2_SAMPLES_PER_FRAME * 2);
        
-       codec2_encode(context->encoder, encoded_data, decoded_data);
+#ifdef LOG_DATA        
+       fwrite(decoded_data, decoded_data_len, 1, context->encoder_in);
+       fflush(context->encoder_in);
+#endif
+
+       {
+               /*  Workaround for assertion failure until it makes it into codec2 svn */
+               uint8_t *p = (uint8_t*)decoded_data;
+               int i;
+               for (i = 0; i < 10; i++) {
+                       if (*p != 0) {
+                               break;
+                       }
+               }
+               if (i == 10) {
+                       memset(encoded_data, 0, 8);
+                       *encoded_data_len = 8;
+                       if (flag) {
+                               *flag |= SFF_CNG;
+                       }
+                       return SWITCH_STATUS_SUCCESS;
+               }
+       }
+
+       codec2_encode(context->encoder, encode_buf, decoded_data);
+       
+       memset(encoded_data, 0, 8);
+       pack(encoded_data, encode_buf, sizeof(encode_buf));
        
-       *encoded_data_len = 7; /* 51 bits */
-       *encoded_rate = 8000;
+#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);
+       fflush(context->encoder_out);
+#endif
+       
+       *encoded_data_len = 8;
 
        return SWITCH_STATUS_SUCCESS;
 }
@@ -94,13 +216,27 @@ static switch_status_t switch_codec2_decode(switch_codec_t *codec,
                                                                                  unsigned int *flag)
 {
        struct codec2_context *context = codec->private_info;
+       char bits[CODEC2_BITS_PER_FRAME];
+       
+       codec2_assert(encoded_data_len == 8 /* aligned to 8 */);
+       
+       unpack(encoded_data, bits, sizeof(bits));
 
-       switch_assert(encoded_data_len == 7);
+#ifdef LOG_DATA        
+       fwrite(encoded_data, encoded_data_len, 1, context->decoder_in);
+       fflush(context->decoder_in);
+       fwrite(bits, sizeof(bits), 1, context->decoder_in_unpacked);
+       fflush(context->decoder_in_unpacked);
+#endif
+       
+       codec2_decode(context->decoder, decoded_data, bits);
 
-       codec2_encode(context->decoder, decoded_data, encoded_data);
+#ifdef LOG_DATA        
+       fwrite(decoded_data, CODEC2_SAMPLES_PER_FRAME, 2, context->decoder_out);
+       fflush(context->decoder_out);
+#endif
 
-       *decoded_data_len = 160 * 2; /* 160 samples */
-       *decoded_rate = 8000;
+       *decoded_data_len = CODEC2_SAMPLES_PER_FRAME * 2; /* 160 samples */
        
        return SWITCH_STATUS_SUCCESS;
 }
@@ -111,11 +247,31 @@ static switch_status_t switch_codec2_destroy(switch_codec_t *codec)
        
        codec2_destroy(context->encoder);
        codec2_destroy(context->decoder);
-       
-       
+
        context->encoder = NULL;
        context->decoder = NULL;
-       
+
+#ifdef LOG_DATA
+       if (context->encoder_in) {
+               fclose(context->encoder_in);
+       }
+       if (context->encoder_out) {
+               fclose(context->encoder_out);
+       }
+       if (context->encoder_out_unpacked) {
+               fclose(context->encoder_out_unpacked);
+       }
+       if (context->decoder_in) {
+               fclose(context->decoder_in);
+       }
+       if (context->decoder_in_unpacked) {
+               fclose(context->decoder_in_unpacked);
+       }
+       if (context->decoder_out) {
+               fclose(context->decoder_out);
+       }
+#endif
+
        return SWITCH_STATUS_SUCCESS;
 }
 
@@ -128,23 +284,23 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_codec2_load)
        SWITCH_ADD_CODEC(codec_interface, "CODEC2 2550bps");
 
        switch_core_codec_add_implementation(pool, codec_interface,
-                                                                                SWITCH_CODEC_TYPE_AUDIO,
-                                                                                0,
-                                                                                "CODEC2",
-                                                                                NULL,
-                                                                                8000, /* samples/sec */
-                                                                                8000, /* samples/sec */
-                                                                                2550, /* bps */
-                                                                                20000, /* ptime */
-                                                                                160,   /* samples decoded */
-                                                                                320,   /* bytes decoded */
-                                                                                7,     /* bytes encoded */
-                                                                                1,     /* channels */
-                                                                                1,     /* frames/packet */
-                                                                                switch_codec2_init,
-                                                                                switch_codec2_encode,
-                                                                                switch_codec2_decode,
-                                                                                switch_codec2_destroy);
+                                                        SWITCH_CODEC_TYPE_AUDIO,
+                                                        111,
+                                                        "CODEC2",
+                                                        NULL,
+                                                        8000, /* samples/sec */
+                                                        8000, /* samples/sec */
+                                                        2550, /* bps */
+                                                        20000, /* ptime */
+                                                        CODEC2_SAMPLES_PER_FRAME,      /* samples decoded */
+                                                        CODEC2_SAMPLES_PER_FRAME*2,    /* bytes decoded */
+                                                        0,     /* bytes encoded */
+                                                        1,     /* channels */
+                                                        1,     /* frames/packet */
+                                                        switch_codec2_init,
+                                                        switch_codec2_encode,
+                                                        switch_codec2_decode,
+                                                        switch_codec2_destroy);
 
        return SWITCH_STATUS_SUCCESS;
 }