aboutsummaryrefslogtreecommitdiff
path: root/webrtc/modules/audio_coding/codecs/opus/opus_interface.c
diff options
context:
space:
mode:
Diffstat (limited to 'webrtc/modules/audio_coding/codecs/opus/opus_interface.c')
-rw-r--r--webrtc/modules/audio_coding/codecs/opus/opus_interface.c115
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;
}