diff options
Diffstat (limited to 'codecs/G726/G726decode.c')
-rw-r--r-- | codecs/G726/G726decode.c | 86 |
1 files changed, 61 insertions, 25 deletions
diff --git a/codecs/G726/G726decode.c b/codecs/G726/G726decode.c index e454be5ac8..cb157d6c46 100644 --- a/codecs/G726/G726decode.c +++ b/codecs/G726/G726decode.c @@ -24,53 +24,89 @@ #include <glib.h> #ifdef HAVE_SPANDSP -#include "telephony.h" -#include "bitstream.h" -#include "g726.h" +#include "spandsp.h" #include "G726decode.h" -/* this isn't reentrant. Making it might involve quite a few changes to be able to pass a g726 state - * variable to the various functions involved in G.726 decoding. - */ -static g726_state_t state; +typedef struct _g726_codec_ctx { + g726_state_t *state; + int bit_rate; +} g726_codec_ctx; -/* Currently, only G.726-32, linear encoding, left packed is supported */ -void * -codec_g726_init(void) +static inline void * +codec_g726_init(int bit_rate, int packing) { - memset (&state, 0, sizeof (state)); - g726_init(&state, 32000, 0, 1); + g726_state_t *decoder = g726_init(NULL, bit_rate, G726_ENCODING_LINEAR, packing); + + if (!decoder) { + return NULL; /* out-of-memory; */ + } + + g726_codec_ctx *state = g_new(g726_codec_ctx, 1); + state->state = decoder; + state->bit_rate = bit_rate; - return NULL; + return state; } +void *codec_g726_16_init(void) { return codec_g726_init(16000, G726_PACKING_RIGHT); } +void *codec_g726_24_init(void) { return codec_g726_init(24000, G726_PACKING_RIGHT); } +void *codec_g726_32_init(void) { return codec_g726_init(32000, G726_PACKING_RIGHT); } +void *codec_g726_40_init(void) { return codec_g726_init(40000, G726_PACKING_RIGHT); } +void *codec_aal2_g726_16_init(void) { return codec_g726_init(16000, G726_PACKING_LEFT); } +void *codec_aal2_g726_24_init(void) { return codec_g726_init(24000, G726_PACKING_LEFT); } +void *codec_aal2_g726_32_init(void) { return codec_g726_init(32000, G726_PACKING_LEFT); } +void *codec_aal2_g726_40_init(void) { return codec_g726_init(40000, G726_PACKING_LEFT); } + void -codec_g726_release(void *ctx _U_) +codec_g726_release(void *ctx) { + g726_codec_ctx *state = (g726_codec_ctx *)ctx; + + if (!state) { + return; /* out-of-memory; */ + } + /* Note: replaces g726_release since spandsp 20090211 */ + g726_free(state->state); + g_free(state); } -int +unsigned codec_g726_get_channels(void *ctx _U_) { return 1; } -int +unsigned codec_g726_get_frequency(void *ctx _U_) { - return 32000; + return 8000; } -/* Packing should be user defined (via the decode dialog) since due to historical reasons two diverging - * de facto standards are in use today (see RFC3551). - */ -int -codec_g726_decode(void *ctx _U_, const void *input, int inputSizeBytes, void *output, - int *outputSizeBytes) +size_t +codec_g726_decode(void *ctx, const void *input, size_t inputSizeBytes, void *output, + size_t *outputSizeBytes) { - *outputSizeBytes = 2 * g726_decode(&state, output, (void*) input, inputSizeBytes); - return 0; + g726_codec_ctx *state = (g726_codec_ctx *)ctx; + + if (!state) { + return 0; /* out-of-memory; */ + } + + if (!output || !outputSizeBytes) { + /* + * sample rate 8kHz, for bitrate 16kHz we have 16/8 = 2 bits/sample, so + * 1 input byte (8 bits) will expand to four 16-bit samples. Likewise, + * for bitrate 40kHz we have 40/8 = 5 bits/sample. Alternatively: + * bitsPerSample = bitRate / sampleRate (8kHz). + * outputBytes = (inputBits / bitsPerSample) * sizeof(sample) + */ + return inputSizeBytes * 8 / (state->bit_rate / 8000) * 2; + } + + /* g726_decode returns the number of 16-bit samples. */ + *outputSizeBytes = 2 * g726_decode(state->state, (int16_t *)output, (const uint8_t *) input, (int)inputSizeBytes); + return *outputSizeBytes; } #endif |