From 8543778b7c48a26142c8dfc78e63323c7d753d52 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Sat, 2 Sep 2006 23:04:25 +0000 Subject: [PATCH] pack this mutha %^%$^& git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@2483 d0543943-73ff-0310-b7d9-9358b9ac24b2 --- src/include/switch_bitpack.h | 272 +++++++++++++++++ src/include/switch_types.h | 29 +- src/mod/codecs/mod_g726/Makefile | 2 +- src/mod/codecs/mod_g726/mod_g726.c | 385 ++++++++++++------------ src/mod/endpoints/mod_sofia/mod_sofia.c | 11 +- 5 files changed, 495 insertions(+), 204 deletions(-) create mode 100644 src/include/switch_bitpack.h diff --git a/src/include/switch_bitpack.h b/src/include/switch_bitpack.h new file mode 100644 index 0000000000..40333f50d7 --- /dev/null +++ b/src/include/switch_bitpack.h @@ -0,0 +1,272 @@ +/* + * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application + * Copyright (C) 2005/2006, Anthony Minessale II + * + * 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 + * Portions created by the Initial Developer are Copyright (C) + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Anthony Minessale II + * + * + * 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 + +#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 diff --git a/src/include/switch_types.h b/src/include/switch_types.h index 906c7caf59..83d11a456a 100644 --- a/src/include/switch_types.h +++ b/src/include/switch_types.h @@ -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 */ 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; diff --git a/src/mod/codecs/mod_g726/Makefile b/src/mod/codecs/mod_g726/Makefile index 1ff7d9bd91..268ee99fcf 100644 --- a/src/mod/codecs/mod_g726/Makefile +++ b/src/mod/codecs/mod_g726/Makefile @@ -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) diff --git a/src/mod/codecs/mod_g726/mod_g726.c b/src/mod/codecs/mod_g726/mod_g726.c index d6aed9c45f..7e63506357 100644 --- a/src/mod/codecs/mod_g726/mod_g726.c +++ b/src/mod/codecs/mod_g726/mod_g726.c @@ -31,29 +31,31 @@ */ #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_byte_t *in = (switch_byte_t *) encoded_data; - 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); + if (!handle || !context) { return SWITCH_STATUS_FALSE; - break; } - if (!context) { + 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++]); + } + 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; - } - { - - 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; - } - - 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 }; diff --git a/src/mod/endpoints/mod_sofia/mod_sofia.c b/src/mod/endpoints/mod_sofia/mod_sofia.c index ad915ca65a..2e446535d6 100644 --- a/src/mod/endpoints/mod_sofia/mod_sofia.c +++ b/src/mod/endpoints/mod_sofia/mod_sofia.c @@ -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")) {