]> git.ipfire.org Git - thirdparty/freeswitch.git/commitdiff
pack this mutha %^%$^&
authorAnthony Minessale <anthony.minessale@gmail.com>
Sat, 2 Sep 2006 23:04:25 +0000 (23:04 +0000)
committerAnthony Minessale <anthony.minessale@gmail.com>
Sat, 2 Sep 2006 23:04:25 +0000 (23:04 +0000)
git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@2483 d0543943-73ff-0310-b7d9-9358b9ac24b2

src/include/switch_bitpack.h [new file with mode: 0644]
src/include/switch_types.h
src/mod/codecs/mod_g726/Makefile
src/mod/codecs/mod_g726/mod_g726.c
src/mod/endpoints/mod_sofia/mod_sofia.c

diff --git a/src/include/switch_bitpack.h b/src/include/switch_bitpack.h
new file mode 100644 (file)
index 0000000..40333f5
--- /dev/null
@@ -0,0 +1,272 @@
+/* 
+ * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
+ * Copyright (C) 2005/2006, Anthony Minessale II <anthmct@yahoo.com>
+ *
+ * Version: MPL 1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
+ *
+ * The Initial Developer of the Original Code is
+ * Anthony Minessale II <anthmct@yahoo.com>
+ * Portions created by the Initial Developer are Copyright (C)
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * 
+ * Anthony Minessale II <anthmct@yahoo.com>
+ *
+ *
+ * switch_utils.h -- Compatability and Helper Code
+ *
+ */
+/*! \file switch_bitpack.h
+    \brief BITPACKING code for RFC3551 and AAL2 packing
+
+*/
+#ifndef SWITCH_BITPACK_H
+#define SWITCH_BITPACK_H
+BEGIN_EXTERN_C
+
+#include <switch.h>
+
+#ifdef DEBUG_BITS
+static char bb[80] = "";
+static inline char *print_bits(switch_byte_t byte, char *x)
+{
+
+    int i,j = 0;
+    x[j++] = '[';
+    for (i=7;i>=0;i--) {
+        x[j++] = (byte & (1 << i)) ? '1' : '0';
+    }
+    x[j++] = ']';
+    x[j++] = '\0';
+    return x;
+}
+#endif
+
+
+
+/*!
+  \defgroup bp1 Bitpacking 
+  \ingroup core1
+  \{ 
+*/
+
+static const int8_t SWITCH_BITPACKED_MASKS[] = {0, 1, 3, 7, 15, 31, 63, 127, 255};
+static const int8_t SWITCH_REVERSE_BITPACKED_MASKS[] = {255, 254, 252, 248, 240, 224, 192, 128};
+
+/*!
+  \brief Initialize a bitpack object
+  \param pack the pack object
+  \param bitlen the number of bits per packet
+  \param buf the buffer to use for storage
+  \param buflen the length of the storage buffer
+  \param mode RFC3551 or AAL2 mode (curse you backwards folks) 
+*/
+static inline void switch_bitpack_init(switch_bitpack_t *pack, int32_t bitlen, switch_byte_t *buf, uint32_t buflen, switch_bitpack_mode_t mode)
+{
+       memset(pack, 0, sizeof(*pack));
+       memset(buf, 0, buflen);
+       pack->frame_bits = bitlen;
+       pack->buf = buf;
+       pack->buflen = buflen;
+       pack->cur = pack->buf;
+       pack->mode = mode;
+}
+
+static inline void pack_check_over(switch_bitpack_t *pack)
+{
+       switch_byte_t this = pack->this;        
+
+       if (pack->over) {
+               pack->bits_cur = pack->over;
+
+               if (pack->mode == SWITCH_BITPACK_MODE_RFC3551) {
+                       this &= SWITCH_BITPACKED_MASKS[pack->over];
+                       this <<= pack->under;
+                       *pack->cur |= this;
+                       pack->cur++;
+               } else {
+                       switch_byte_t mask = SWITCH_BITS_PER_BYTE - pack->over;
+                       this &= SWITCH_REVERSE_BITPACKED_MASKS[mask];
+                       this >>= mask;
+
+                       *pack->cur <<= pack->over;
+                       *pack->cur |= this;
+                       pack->cur++;
+               }
+
+
+               pack->bytes++;
+               pack->over = pack->under = 0;
+       }       
+}
+
+/*!
+  \brief finalize a bitpack object
+  \param pack the pack/unpack object
+*/
+static inline int8_t switch_bitpack_done(switch_bitpack_t *pack)
+{
+
+       if (pack->bits_cur && pack->bits_cur < SWITCH_BITS_PER_BYTE) {
+               pack->bytes++;
+               if (pack->mode == SWITCH_BITPACK_MODE_AAL2) {
+            *pack->cur <<= SWITCH_BITS_PER_BYTE - pack->bits_cur;
+        }
+       }
+
+       if (pack->over) {
+               pack_check_over(pack);
+       }
+       return 0;
+}
+
+
+/*!
+  \brief pull data out of a bitpack object into it's buffer
+  \param unpack the pack/unpack object
+  \param in a 1 byte int packed with bits
+  \return -1 if the buffer is full otherwise 0
+*/
+static inline int8_t switch_bitpack_out(switch_bitpack_t *unpack, switch_byte_t in)
+{
+       switch_byte_t this;
+
+       if (unpack->cur - unpack->buf > unpack->buflen) {
+               return -1;
+       }
+
+       unpack->bits_cur = 0;
+       unpack->this = this = in;
+
+
+
+       pack_check_over(unpack);
+       while(unpack->bits_cur <= SWITCH_BITS_PER_BYTE) {
+               switch_byte_t next = unpack->bits_cur + unpack->frame_bits;
+               switch_byte_t under_in;
+               switch_byte_t mask;
+               this = unpack->this;
+
+               if (next > SWITCH_BITS_PER_BYTE) {
+                       unpack->over = next - SWITCH_BITS_PER_BYTE;
+                       unpack->under = unpack->frame_bits - unpack->over;
+
+                       if (unpack->mode == SWITCH_BITPACK_MODE_RFC3551) {
+                               mask = SWITCH_BITS_PER_BYTE - unpack->under;
+
+                               under_in = this & SWITCH_REVERSE_BITPACKED_MASKS[mask];
+                               under_in >>= mask;
+                               *unpack->cur |= under_in;
+                       } else {
+                               mask = unpack->under;
+                               under_in = this & SWITCH_BITPACKED_MASKS[mask];
+                               *unpack->cur <<= mask;
+                               *unpack->cur |= under_in;
+                       }
+
+                       break;
+               }
+
+               if (unpack->mode == SWITCH_BITPACK_MODE_RFC3551) {
+                       this >>= unpack->bits_cur;
+                       this &= SWITCH_BITPACKED_MASKS[unpack->frame_bits];
+                       *unpack->cur |= this;
+                       unpack->cur++;
+               } else {
+                       this >>= (SWITCH_BITS_PER_BYTE - next);
+                       this &= SWITCH_BITPACKED_MASKS[unpack->frame_bits];
+
+                       *unpack->cur |= this;
+                       unpack->cur++;
+               }
+
+               unpack->bits_cur = next;
+               unpack->bytes++;
+
+
+       }
+
+
+       return 0;
+}
+
+
+/*!
+  \brief pack data into a bitpack object's buffer
+  \param pack the pack/unpack object
+  \param in a 1 byte int with 1 packet worth of bits
+  \return -1 if the buffer is full otherwise 0
+*/
+static inline int8_t switch_bitpack_in(switch_bitpack_t *pack, switch_byte_t in)
+{
+       int next = pack->bits_cur + pack->frame_bits;
+
+       if (pack->cur - pack->buf > pack->buflen) {
+               return -1;
+       } 
+
+       pack->bits_tot += pack->frame_bits;
+
+       if (next > SWITCH_BITS_PER_BYTE) {
+               int a = 0, b = 0, rem, nxt;
+               rem = SWITCH_BITS_PER_BYTE - pack->bits_cur;
+               nxt = pack->frame_bits - rem ;
+               if (pack->mode == SWITCH_BITPACK_MODE_RFC3551) {
+                       a = in & SWITCH_BITPACKED_MASKS[rem];
+                       b = in >> rem;
+                       a <<= pack->shiftby;
+                       *pack->cur |= a;
+                       pack->cur++;
+                       *pack->cur |= b;
+                       pack->bits_cur = pack->shiftby = nxt;
+               } else {
+                       a = in >> nxt;
+                       b = in & SWITCH_BITPACKED_MASKS[nxt];
+                       *pack->cur <<= rem;
+                       *pack->cur |= a;
+                       pack->cur++;
+                       *pack->cur |= b;
+                       pack->bits_cur = nxt;
+                       
+               }
+               pack->bytes++;
+
+       } else {
+
+               if (pack->mode == SWITCH_BITPACK_MODE_RFC3551) {
+                       in <<= pack->shiftby;
+                       *pack->cur |= in;
+                       pack->shiftby += pack->frame_bits;
+               } else {
+                       *pack->cur <<= pack->frame_bits;
+                       *pack->cur |= in;
+               }
+
+               if (next == SWITCH_BITS_PER_BYTE) {
+                       pack->cur++;                    
+                       pack->bytes++;
+                       pack->bits_cur = pack->shiftby = 0;
+               } else {
+                       pack->bits_cur = next;
+               }
+       }
+
+       return 0;
+}
+///\}
+
+END_EXTERN_C
+#endif
index 906c7caf5903f82766c1fd98ed18a205974a841f..83d11a456a63dd74b6fdde9368c3791f4ade1f5c 100644 (file)
@@ -72,6 +72,32 @@ BEGIN_EXTERN_C
 #define SWITCH_HTDOCS_DIR SWITCH_PREFIX_DIR SWITCH_PATH_SEPARATOR "htdocs"
 #endif
 
+#define SWITCH_BITS_PER_BYTE 8
+typedef uint8_t switch_byte_t;
+
+typedef enum {
+       SWITCH_BITPACK_MODE_RFC3551,
+       SWITCH_BITPACK_MODE_AAL2
+} switch_bitpack_mode_t;
+
+
+typedef struct {
+       switch_byte_t *buf;
+       uint32_t buflen;
+       switch_byte_t *cur;
+       uint32_t bytes;
+       uint32_t bits_tot;
+       switch_byte_t bits_cur;
+       switch_byte_t bits_rem;
+       switch_byte_t frame_bits;
+       switch_byte_t shiftby;
+       switch_byte_t this;
+       switch_byte_t under;
+       switch_byte_t over;
+       switch_bitpack_mode_t mode;
+} switch_bitpack_t;
+
+
 struct switch_directories {
        char *base_dir;
        char *mod_dir;
@@ -417,6 +443,7 @@ SWITCH_CODEC_FLAG_SILENCE_START =   (1 <<  2) - Start period of silence
 SWITCH_CODEC_FLAG_SILENCE_STOP =       (1 <<  3) - End period of silence
 SWITCH_CODEC_FLAG_SILENCE =                    (1 <<  4) - Silence
 SWITCH_CODEC_FLAG_FREE_POOL =          (1 <<  5) - Free codec's pool on destruction
+SWITCH_CODEC_FLAG_AAL2 =                       (1 <<  6) - USE AAL2 Bitpacking
 </pre>
 */
 typedef enum {
@@ -426,7 +453,7 @@ typedef enum {
        SWITCH_CODEC_FLAG_SILENCE_STOP =        (1 <<  3),
        SWITCH_CODEC_FLAG_SILENCE =                     (1 <<  4),
        SWITCH_CODEC_FLAG_FREE_POOL =           (1 <<  5),
-
+       SWITCH_CODEC_FLAG_AAL2 =                        (1 <<  6)
 } switch_codec_flag_t;
 
 
index 1ff7d9bd918576e4dd1b0a5f28462ad3948c5268..268ee99fcffbcf466bcc21ecd550f1734b49e05d 100644 (file)
@@ -5,7 +5,7 @@ all:    depends $(MODNAME).$(DYNAMIC_LIB_EXTEN)
 depends:
        MAKE=$(MAKE) $(BASE)/build/buildlib.sh $(BASE) install codec/g726 --prefix=$(PREFIX)
 
-$(MODNAME).$(DYNAMIC_LIB_EXTEN): $(MODNAME).c
+$(MODNAME).$(DYNAMIC_LIB_EXTEN): $(MODNAME).c ../../../include/switch_bitpack.h
        $(CC) $(CFLAGS) -fPIC -c $(MODNAME).c -o $(MODNAME).o
        $(CC) $(SOLINK) $(MODNAME).o -o $(MODNAME).$(DYNAMIC_LIB_EXTEN) $(LDFLAGS)
 
index d6aed9c45f2b6583f6c8f818b80b9458646556a5..7e63506357dad1c64172719cad41c9a1d7e406cf 100644 (file)
  */  
 #include "switch.h"
 #include "g72x.h"
-#define BITS_IN_A_BYTE 8
+#include "switch_bitpack.h"
 
 static const char modname[] = "mod_g726";
 
+typedef int (*encoder_t)(int, int, g726_state *);
+typedef int (*decoder_t)(int, int, g726_state *);
+
 
 typedef struct {
        g726_state context;
-       uint8_t buf[5];
-       uint8_t *ptr;
        uint8_t bits_per_frame;
-       uint8_t bits;
-       uint8_t bbits;
-       uint8_t ecount;
-       uint8_t d_bits;
-       uint8_t d_bbits;
-       uint8_t dcount;
-       uint8_t save;
+       encoder_t encoder;
+       decoder_t decoder;
+       switch_bitpack_t pack;
+       switch_bitpack_t unpack;
+       switch_bitpack_mode_t mode;
+       switch_byte_t loops;
+       switch_byte_t bytes;
+       switch_byte_t buf[160];
 } g726_handle_t;
 
 static switch_status_t switch_g726_init(switch_codec_t *codec, switch_codec_flag_t flags,
                                                                          const switch_codec_settings_t *codec_settings) 
 {
-       int encoding, decoding;
+       switch_byte_t encoding, decoding;
        g726_handle_t *handle;
 
        encoding = (flags & SWITCH_CODEC_FLAG_ENCODE);
@@ -62,10 +64,40 @@ static switch_status_t switch_g726_init(switch_codec_t *codec, switch_codec_flag
        if (!(encoding || decoding) || (!(handle = switch_core_alloc(codec->memory_pool, sizeof(*handle))))) {
                return SWITCH_STATUS_FALSE;
        } else {
+               handle->bytes = codec->implementation->encoded_bytes_per_frame;
+               
+               switch(handle->bytes) {
+               case 100:
+                       handle->encoder = g726_40_encoder;
+                       handle->decoder = g726_40_decoder;
+                       handle->loops = 160;
+                       break;
+               case 80:
+                       handle->encoder = g726_32_encoder;
+                       handle->decoder = g726_32_decoder;
+                       handle->loops = 40;
+                       break;
+               case 60:
+                       handle->encoder = g726_24_encoder;
+                       handle->decoder = g726_24_decoder;
+                       handle->loops = 160;
+                       break;
+               case 40:
+                       handle->encoder = g726_16_encoder;
+                       handle->decoder = g726_16_decoder;
+                       handle->loops = 160;
+                       break;
+               default:
+                       switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "invalid Encoding Size %d!\n", codec->implementation->encoded_bytes_per_frame);
+                       return SWITCH_STATUS_FALSE;
+                       break;
+               }
+
                g726_init_state(&handle->context);
                codec->private_info = handle;
-               handle->bits_per_frame = (uint8_t)(codec->implementation->bits_per_second / (codec->implementation->samples_per_second));
-               handle->ptr = handle->buf;
+               handle->bits_per_frame = codec->implementation->bits_per_second / (codec->implementation->samples_per_second);
+               handle->mode = (flags & SWITCH_CODEC_FLAG_AAL2 || strstr(codec->implementation->iananame, "AAL2")) 
+                       ? SWITCH_BITPACK_MODE_AAL2 : SWITCH_BITPACK_MODE_RFC3551;
                return SWITCH_STATUS_SUCCESS;
        }
 }
@@ -77,27 +109,6 @@ static switch_status_t switch_g726_destroy(switch_codec_t *codec)
        return SWITCH_STATUS_SUCCESS;
 }
 
-typedef int (*encoder_t)(int, int, g726_state *);
-typedef int (*decoder_t)(int, int, g726_state *);
-
-
-static void print_bits(uint8_t byte)
-{
-       int i;
-
-       for (i=7;i>=0;i--) {
-               //for (i=0;i<=7;i++) {
-               if(byte & (1 << i)) {
-                       printf("1");
-               } else {
-                       printf("0");
-               }
-       }
-}
-
-
-
-
 
 
 static switch_status_t switch_g726_encode(switch_codec_t *codec, 
@@ -116,27 +127,7 @@ static switch_status_t switch_g726_encode(switch_codec_t *codec,
        g726_handle_t *handle = codec->private_info;
        g726_state *context = &handle->context;
        uint32_t len = codec->implementation->bytes_per_frame;
-       uint32_t elen = codec->implementation->encoded_bytes_per_frame;
-       encoder_t encoder;
-
-       switch(elen) {
-       case 100:
-               encoder = g726_40_encoder;
-               break;
-       case 80:
-               encoder = g726_32_encoder;
-               break;
-       case 60:
-               encoder = g726_24_encoder;
-               break;
-       case 40:
-               encoder = g726_16_encoder;
-               break;
-       default:
-               switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "invalid Encoding Size %d!\n", elen);
-               return SWITCH_STATUS_FALSE;
-               break;
-       }
+       //uint32_t elen = codec->implementation->encoded_bytes_per_frame;
 
        if (!context) {
                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error!\n");
@@ -147,72 +138,18 @@ static switch_status_t switch_g726_encode(switch_codec_t *codec,
                uint32_t new_len = 0;
                int16_t *ddp = decoded_data;
                uint8_t *edp = encoded_data;
-               uint32_t x;
+               int x;
                uint32_t loops = decoded_data_len / (sizeof(*ddp));
 
+               switch_bitpack_init(&handle->pack, handle->bits_per_frame, edp, *encoded_data_len, handle->mode);
+
                for (x = 0; x < loops && new_len < *encoded_data_len; x++) {
-                       int edata = encoder(*ddp, AUDIO_ENCODING_LINEAR, context);
-                       int bits = handle->bbits + handle->bits_per_frame;
-                       
-                       handle->ecount++;
-                       if (!handle->bbits) {
-                               //printf("new byte assign the %d bits\n", handle->bits_per_frame);
-                               *handle->ptr = edata;
-                       } else if (bits <= BITS_IN_A_BYTE) {
-                               int shift_by = ((handle->bits_per_frame * (handle->ecount -1)));
-                               //printf ("shift by %d and add %d bits\n", shift_by, handle->bits_per_frame);
-                               //*handle->ptr <<= shift_by;
-                               //*handle->ptr |= edata;
-                               if (shift_by);
-
-                               //printf("edata\n");
-                               //print_bits(edata);
-                               //printf("\n");
-                               
-                               *handle->ptr <<= shift_by;
-                               *handle->ptr |= edata;
-
-                               //printf("handle\n");
-                               //print_bits(*handle->ptr);
-                               //printf("\n");                         
-
-                       } else {
-                               int remain, next, rdata, ndata;
-
-                               remain = BITS_IN_A_BYTE - handle->bits_per_frame;
-                               next = handle->bits_per_frame - remain;
-                               rdata = edata;
-                               ndata = edata;
-
-                               *handle->ptr += (uint8_t)(edata << remain);
-                               *handle->ptr = ndata;
-
-                               handle->bbits = 0;
-                               handle->ecount = 0;
-                       }
-                       handle->bits = bits;
-                       handle->bbits += handle->bits_per_frame;
-
-                       if (0) {
-                       for(x = 0; x < 5; x++) {
-                               print_bits(handle->buf[x]);
-                               printf(" ");
-                       }
-                       printf("\n");
-                       }
-
-                       if ((handle->bits % BITS_IN_A_BYTE) == 0) {
-                               int bytes = handle->bits / BITS_IN_A_BYTE, count;
-                               for(count = 0; count < bytes; count++) {
-                                       edp[new_len++] = handle->buf[count];
-                               }
-                               handle->bits = handle->bbits = 0;
-                               handle->ptr = handle->buf;
-                               handle->ecount = 0;
-                               memset(handle->buf, 0, sizeof(handle->buf));
-                       }
+                       int edata = handle->encoder(*ddp, AUDIO_ENCODING_LINEAR, context);
+                       switch_bitpack_in(&handle->pack, edata);
                        ddp++;
                }
+               switch_bitpack_done(&handle->pack);
+               new_len = handle->pack.bytes;
 
                if (new_len <= *encoded_data_len) {
                        *encoded_data_len = new_len;
@@ -242,95 +179,35 @@ static switch_status_t switch_g726_decode(switch_codec_t *codec,
 
        g726_handle_t *handle = codec->private_info;
        g726_state *context = &handle->context;
-       //uint32_t len = codec->implementation->bytes_per_frame;
-       uint32_t elen = codec->implementation->encoded_bytes_per_frame;
-       decoder_t decoder;
-
+       int16_t *ddp = decoded_data;
+       uint32_t new_len = 0, z = 0, y;
 
-       switch(elen) {
-       case 100:
-               decoder = g726_40_decoder;
-               break;
-       case 80:
-               decoder = g726_32_decoder;
-               break;
-       case 60:
-               decoder = g726_24_decoder;
-               break;
-       case 40:
-               decoder = g726_16_decoder;
-               break;
-       default:
-               switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "invalid Encoding Size %d!\n", elen);
-               return SWITCH_STATUS_FALSE;
-               break;
-       }
+       switch_byte_t *in = (switch_byte_t *) encoded_data;
 
-       if (!context) {
+       if (!handle || !context) {
                return SWITCH_STATUS_FALSE;
-
        }
 
-
-       {
-
-               int loops = ((int)encoded_data_len * BITS_IN_A_BYTE) / handle->bits_per_frame;
-               int8_t *edp = encoded_data;
-               int16_t *ddp = decoded_data;
-               int x;
-               uint32_t new_len = 0;
-
-               for (x = 0; x < loops && new_len < *decoded_data_len; x++) {
-                       int in = 0;
-                       int bits = 0;
-                       int8_t over = 0;
-                       int8_t under = 0;
-
-                       if (handle->save) {
-                               in = handle->save;
-                               handle->save = 0;
-                       }
-                       
-                       handle->d_bits += handle->bits_per_frame;
-                       bits = handle->d_bbits + handle->bits_per_frame;
-
-                       if (bits > BITS_IN_A_BYTE) {
-                               int tmp;
-                               over = bits - BITS_IN_A_BYTE;
-                               under = handle->bits_per_frame - over;
-                               handle->dcount = 0;
-                               tmp = *edp >> (BITS_IN_A_BYTE - (handle->bits_per_frame * handle->dcount));
-                               in = tmp >> over;
-                               handle->save = tmp;
-                               handle->save  &= (1 << under) - 1;
-                               edp++;
-                       } else if (bits == BITS_IN_A_BYTE) {
-                               handle->d_bbits = 0;
-                               in = *edp;
-                               edp++;
-                               handle->dcount = 0;
-                       } else {
-                               in |= *edp >> (BITS_IN_A_BYTE - (handle->bits_per_frame * handle->dcount));
-                               handle->d_bbits = bits;
-                       }
-
-                       
-
-                       handle->dcount++;
-
-                       *ddp++ = decoder(in, AUDIO_ENCODING_LINEAR, context);
-                       new_len += 2;
+       while (z < encoded_data_len && new_len <= *decoded_data_len) {
+               switch_bitpack_init(&handle->unpack, handle->bits_per_frame, handle->buf, sizeof(handle->buf), handle->mode);
+               for (y = 0; y < handle->loops; y++) {
+                       switch_bitpack_out(&handle->unpack, in[z++]);
                }
-
-               if (new_len <= *decoded_data_len) {
-                       *decoded_data_len = new_len;
-               } else {
-                       switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "buffer overflow!!!\n");
-                       return SWITCH_STATUS_FALSE;
+               for(y = 0; y < handle->bytes; y++) {
+                       *ddp++ = handle->decoder(handle->buf[y], AUDIO_ENCODING_LINEAR, context);
+            new_len += 2;
                }
-
+               switch_bitpack_done(&handle->unpack);
+       }
+       
+       if (new_len <= *decoded_data_len) {
+               *decoded_data_len = new_len;
+       } else {
+               switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "buffer overflow!!!\n");
+               return SWITCH_STATUS_FALSE;
        }
 
+
        return SWITCH_STATUS_SUCCESS;
 
 }
@@ -361,7 +238,7 @@ static const switch_codec_implementation_t g726_16k_implementation = {
 
 static const switch_codec_implementation_t g726_24k_implementation = { 
        /*.codec_type */ SWITCH_CODEC_TYPE_AUDIO, 
-       /*.ianacode */ 2
+       /*.ianacode */ 126
        /*.iananame */ "G726-24", 
        /*.samples_per_second */ 8000, 
        /*.bits_per_second */ 24000, 
@@ -399,7 +276,7 @@ static const switch_codec_implementation_t g726_32k_implementation = {
 
 static const switch_codec_implementation_t g726_40k_implementation = { 
        /*.codec_type */ SWITCH_CODEC_TYPE_AUDIO, 
-       /*.ianacode */ 2
+       /*.ianacode */ 125
        /*.iananame */ "G726-40", 
        /*.samples_per_second */ 8000,
        /*.bits_per_second */ 40000, 
@@ -416,32 +293,142 @@ static const switch_codec_implementation_t g726_40k_implementation = {
        /*.destroy */ switch_g726_destroy, 
 };
 
+
+
+static const switch_codec_implementation_t aal2_g726_16k_implementation = { 
+       /*.codec_type */ SWITCH_CODEC_TYPE_AUDIO, 
+       /*.ianacode */ 124, 
+       /*.iananame */ "AAL2-G726-16", 
+       /*.samples_per_second */ 8000, 
+       /*.bits_per_second */ 16000, 
+       /*.microseconds_per_frame */ 20000, 
+       /*.samples_per_frame */ 160, 
+       /*.bytes_per_frame */ 320, 
+       /*.encoded_bytes_per_frame */ 40, 
+       /*.number_of_channels */ 1, 
+       /*.pref_frames_per_packet */ 1, 
+       /*.max_frames_per_packet */ 1, 
+       /*.init */ switch_g726_init, 
+       /*.encode */ switch_g726_encode, 
+       /*.decode */ switch_g726_decode, 
+       /*.destroy */ switch_g726_destroy, 
+};
+
+
+static const switch_codec_implementation_t aal2_g726_24k_implementation = { 
+       /*.codec_type */ SWITCH_CODEC_TYPE_AUDIO, 
+       /*.ianacode */ 123, 
+       /*.iananame */ "AAL2-G726-24", 
+       /*.samples_per_second */ 8000, 
+       /*.bits_per_second */ 24000, 
+       /*.microseconds_per_frame */ 20000, 
+       /*.samples_per_frame */ 160, 
+       /*.bytes_per_frame */ 320, 
+       /*.encoded_bytes_per_frame */ 60, 
+       /*.number_of_channels */ 1, 
+       /*.pref_frames_per_packet */ 1, 
+       /*.max_frames_per_packet */ 1, 
+       /*.init */ switch_g726_init, 
+       /*.encode */ switch_g726_encode, 
+       /*.decode */ switch_g726_decode, 
+       /*.destroy */ switch_g726_destroy, 
+};
+
+static const switch_codec_implementation_t aal2_g726_32k_implementation = { 
+       /*.codec_type */ SWITCH_CODEC_TYPE_AUDIO, 
+       /*.ianacode */ 2, 
+       /*.iananame */ "AAL2-G726-32", 
+       /*.samples_per_second */ 8000, 
+       /*.bits_per_second */ 32000, 
+       /*.microseconds_per_frame */ 20000, 
+       /*.samples_per_frame */ 160, 
+       /*.bytes_per_frame */ 320, 
+       /*.encoded_bytes_per_frame */ 80, 
+       /*.number_of_channels */ 1, 
+       /*.pref_frames_per_packet */ 1, 
+       /*.max_frames_per_packet */ 1, 
+       /*.init */ switch_g726_init, 
+       /*.encode */ switch_g726_encode, 
+       /*.decode */ switch_g726_decode, 
+       /*.destroy */ switch_g726_destroy, 
+};
+
+static const switch_codec_implementation_t aal2_g726_40k_implementation = { 
+       /*.codec_type */ SWITCH_CODEC_TYPE_AUDIO, 
+       /*.ianacode */ 122, 
+       /*.iananame */ "AAL2-G726-40", 
+       /*.samples_per_second */ 8000,
+       /*.bits_per_second */ 40000, 
+       /*.microseconds_per_frame */ 20000, 
+       /*.samples_per_frame */ 160, 
+       /*.bytes_per_frame */ 320, 
+       /*.encoded_bytes_per_frame */ 100, 
+       /*.number_of_channels */ 1, 
+       /*.pref_frames_per_packet */ 1, 
+       /*.max_frames_per_packet */ 1, 
+       /*.init */ switch_g726_init, 
+       /*.encode */ switch_g726_encode, 
+       /*.decode */ switch_g726_decode, 
+       /*.destroy */ switch_g726_destroy, 
+};
+
 const switch_codec_interface_t g726_16k_codec_interface = { 
        /*.interface_name */ "G.726 16k", 
        /*.implementations */ &g726_16k_implementation, 
 };
+
 const switch_codec_interface_t g726_24k_codec_interface = { 
        /*.interface_name */ "G.726 24k", 
        /*.implementations */ &g726_24k_implementation, 
        /*.next */ &g726_16k_codec_interface
 };
+
 const switch_codec_interface_t g726_32k_codec_interface = { 
        /*.interface_name */ "G.726 32k", 
        /*.implementations */ &g726_32k_implementation, 
        /*.next */ &g726_24k_codec_interface
 };
+
 const switch_codec_interface_t g726_40k_codec_interface = { 
        /*.interface_name */ "G.726 40k", 
        /*.implementations */ &g726_40k_implementation, 
        /*.next */ &g726_32k_codec_interface
 };
 
+
+
+const switch_codec_interface_t aal2_g726_16k_codec_interface = { 
+       /*.interface_name */ "G.726 16k (aal2)", 
+       /*.implementations */ &aal2_g726_16k_implementation, 
+       /*.next */ &g726_40k_codec_interface
+};
+
+const switch_codec_interface_t aal2_g726_24k_codec_interface = { 
+       /*.interface_name */ "G.726 24k (aal2)", 
+       /*.implementations */ &aal2_g726_24k_implementation, 
+       /*.next */ &aal2_g726_16k_codec_interface
+};
+
+const switch_codec_interface_t aal2_g726_32k_codec_interface = { 
+       /*.interface_name */ "G.726 32k (aal2)", 
+       /*.implementations */ &aal2_g726_32k_implementation, 
+       /*.next */ &aal2_g726_24k_codec_interface
+};
+
+const switch_codec_interface_t aal2_g726_40k_codec_interface = { 
+       /*.interface_name */ "G.726 40k (aal2)", 
+       /*.implementations */ &aal2_g726_40k_implementation, 
+       /*.next */ &aal2_g726_32k_codec_interface
+};
+
+
+
 static switch_loadable_module_interface_t g726_module_interface = { 
        /*.module_name */ modname, 
        /*.endpoint_interface */ NULL, 
        /*.timer_interface */ NULL, 
        /*.dialplan_interface */ NULL, 
-       /*.codec_interface */ &g726_40k_codec_interface, 
+       /*.codec_interface */ &aal2_g726_40k_codec_interface, 
        /*.application_interface */ NULL 
 };
 
index ad915ca65a3b02a8e26f8bd22b875d0b7aa5ef27..2e446535d6e84e5a0e3e90c01b34844fa4e893a0 100644 (file)
@@ -125,6 +125,7 @@ struct sofia_profile {
        su_root_t *s_root;
        sip_alias_node_t *aliases;
        switch_payload_t te;
+       uint32_t codec_flags;
 };
 
 
@@ -300,7 +301,7 @@ static void set_local_sdp(private_object_t *tech_pvt)
                for (i = 0; i < tech_pvt->num_codecs; i++) {
                        const switch_codec_implementation_t *imp = tech_pvt->codecs[i];
                        snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "a=rtpmap:%d %s/%d\n", imp->ianacode, imp->iananame, imp->samples_per_second);
-                       snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "a=ptime:%d", imp->microseconds_per_frame / 1000);
+                       snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "a=ptime:%d\n", imp->microseconds_per_frame / 1000);
                }
        }
        
@@ -607,7 +608,7 @@ static switch_status_t tech_set_codec(private_object_t *tech_pvt)
                                                           tech_pvt->rm_rate,
                                                           tech_pvt->codec_ms,
                                                           1,
-                                                          SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE,
+                                                          SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE | tech_pvt->profile->codec_flags,
                                                           NULL,
                                                           switch_core_session_get_pool(tech_pvt->session)) != SWITCH_STATUS_SUCCESS) {
                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Can't load codec?\n");
@@ -619,7 +620,7 @@ static switch_status_t tech_set_codec(private_object_t *tech_pvt)
                                                                   tech_pvt->rm_rate,
                                                                   tech_pvt->codec_ms,
                                                                   1,
-                                                                  SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE,
+                                                                  SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE | tech_pvt->profile->codec_flags,
                                                                   NULL,
                                                                   switch_core_session_get_pool(tech_pvt->session)) != SWITCH_STATUS_SUCCESS) {
                        switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Can't load codec?\n");
@@ -1683,6 +1684,10 @@ static switch_status_t config_sofia(int reload)
                                profile->sipdomain = switch_core_strdup(profile->pool, val);
                        } else if (!strcmp(var, "ext-sip-ip")) {
                                profile->extsipip = switch_core_strdup(profile->pool, val);
+                       } else if (!strcmp(var, "bitpacking")) {
+                               if (!strcasecmp(val, "aal2")) {
+                                       profile->codec_flags = SWITCH_CODEC_FLAG_AAL2;
+                               } 
                        } else if (!strcmp(var, "username")) {
                                profile->username = switch_core_strdup(profile->pool, val);
                        } else if (!strcmp(var, "context")) {