diff options
Diffstat (limited to 'webrtc/modules/audio_coding/codecs/opus/opus_interface.c')
-rw-r--r-- | webrtc/modules/audio_coding/codecs/opus/opus_interface.c | 115 |
1 files changed, 79 insertions, 36 deletions
diff --git a/webrtc/modules/audio_coding/codecs/opus/opus_interface.c b/webrtc/modules/audio_coding/codecs/opus/opus_interface.c index 1a632422c5..9dc7ef95fe 100644 --- a/webrtc/modules/audio_coding/codecs/opus/opus_interface.c +++ b/webrtc/modules/audio_coding/codecs/opus/opus_interface.c @@ -8,9 +8,10 @@ * be found in the AUTHORS file in the root of the source tree. */ -#include "webrtc/modules/audio_coding/codecs/opus/include/opus_interface.h" +#include "webrtc/modules/audio_coding/codecs/opus/opus_interface.h" #include "webrtc/modules/audio_coding/codecs/opus/opus_inst.h" +#include <assert.h> #include <stdlib.h> #include <string.h> @@ -29,48 +30,61 @@ enum { /* Default frame size, 20 ms @ 48 kHz, in samples (for one channel). */ kWebRtcOpusDefaultFrameSize = 960, + + // Maximum number of consecutive zeros, beyond or equal to which DTX can fail. + kZeroBreakCount = 157, + +#if defined(OPUS_FIXED_POINT) + kZeroBreakValue = 10, +#else + kZeroBreakValue = 1, +#endif }; int16_t WebRtcOpus_EncoderCreate(OpusEncInst** inst, - int32_t channels, + size_t channels, int32_t application) { - OpusEncInst* state; - if (inst != NULL) { - state = (OpusEncInst*) calloc(1, sizeof(OpusEncInst)); - if (state) { - int opus_app; - switch (application) { - case 0: { - opus_app = OPUS_APPLICATION_VOIP; - break; - } - case 1: { - opus_app = OPUS_APPLICATION_AUDIO; - break; - } - default: { - free(state); - return -1; - } - } + int opus_app; + if (!inst) + return -1; - int error; - state->encoder = opus_encoder_create(48000, channels, opus_app, - &error); - state->in_dtx_mode = 0; - if (error == OPUS_OK && state->encoder != NULL) { - *inst = state; - return 0; - } - free(state); - } + switch (application) { + case 0: + opus_app = OPUS_APPLICATION_VOIP; + break; + case 1: + opus_app = OPUS_APPLICATION_AUDIO; + break; + default: + return -1; } - return -1; + + OpusEncInst* state = calloc(1, sizeof(OpusEncInst)); + assert(state); + + // Allocate zero counters. + state->zero_counts = calloc(channels, sizeof(size_t)); + assert(state->zero_counts); + + int error; + state->encoder = opus_encoder_create(48000, (int)channels, opus_app, + &error); + if (error != OPUS_OK || !state->encoder) { + WebRtcOpus_EncoderFree(state); + return -1; + } + + state->in_dtx_mode = 0; + state->channels = channels; + + *inst = state; + return 0; } int16_t WebRtcOpus_EncoderFree(OpusEncInst* inst) { if (inst) { opus_encoder_destroy(inst->encoder); + free(inst->zero_counts); free(inst); return 0; } else { @@ -84,13 +98,42 @@ int WebRtcOpus_Encode(OpusEncInst* inst, size_t length_encoded_buffer, uint8_t* encoded) { int res; + size_t i; + size_t c; + + int16_t buffer[2 * 48 * kWebRtcOpusMaxEncodeFrameSizeMs]; if (samples > 48 * kWebRtcOpusMaxEncodeFrameSizeMs) { return -1; } + const size_t channels = inst->channels; + int use_buffer = 0; + + // Break long consecutive zeros by forcing a "1" every |kZeroBreakCount| + // samples. + if (inst->in_dtx_mode) { + for (i = 0; i < samples; ++i) { + for (c = 0; c < channels; ++c) { + if (audio_in[i * channels + c] == 0) { + ++inst->zero_counts[c]; + if (inst->zero_counts[c] == kZeroBreakCount) { + if (!use_buffer) { + memcpy(buffer, audio_in, samples * channels * sizeof(int16_t)); + use_buffer = 1; + } + buffer[i * channels + c] = kZeroBreakValue; + inst->zero_counts[c] = 0; + } + } else { + inst->zero_counts[c] = 0; + } + } + } + } + res = opus_encode(inst->encoder, - (const opus_int16*)audio_in, + use_buffer ? buffer : audio_in, (int)samples, encoded, (opus_int32)length_encoded_buffer); @@ -205,7 +248,7 @@ int16_t WebRtcOpus_SetComplexity(OpusEncInst* inst, int32_t complexity) { } } -int16_t WebRtcOpus_DecoderCreate(OpusDecInst** inst, int channels) { +int16_t WebRtcOpus_DecoderCreate(OpusDecInst** inst, size_t channels) { int error; OpusDecInst* state; @@ -217,7 +260,7 @@ int16_t WebRtcOpus_DecoderCreate(OpusDecInst** inst, int channels) { } /* Create new memory, always at 48000 Hz. */ - state->decoder = opus_decoder_create(48000, channels, &error); + state->decoder = opus_decoder_create(48000, (int)channels, &error); if (error == OPUS_OK && state->decoder != NULL) { /* Creation of memory all ok. */ state->channels = channels; @@ -246,7 +289,7 @@ int16_t WebRtcOpus_DecoderFree(OpusDecInst* inst) { } } -int WebRtcOpus_DecoderChannels(OpusDecInst* inst) { +size_t WebRtcOpus_DecoderChannels(OpusDecInst* inst) { return inst->channels; } |