Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(150)

Side by Side Diff: webrtc/modules/audio_coding/codecs/opus/opus_interface.c

Issue 1415173005: Prevent Opus DTX from generating intermittent noise during silence (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@master
Patch Set: a fix after rebase Created 5 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 /* 1 /*
2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. 2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
3 * 3 *
4 * Use of this source code is governed by a BSD-style license 4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source 5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found 6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may 7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree. 8 * be found in the AUTHORS file in the root of the source tree.
9 */ 9 */
10 10
11 #include "webrtc/modules/audio_coding/codecs/opus/include/opus_interface.h" 11 #include "webrtc/modules/audio_coding/codecs/opus/include/opus_interface.h"
12 #include "webrtc/modules/audio_coding/codecs/opus/opus_inst.h" 12 #include "webrtc/modules/audio_coding/codecs/opus/opus_inst.h"
13 13
14 #include <assert.h>
the sun 2015/11/09 12:41:00 Why is this a .c file? Can we make it a .cc and us
minyue-webrtc 2015/11/09 15:13:00 Good idea. but it might be a outreach for this CL.
14 #include <stdlib.h> 15 #include <stdlib.h>
15 #include <string.h> 16 #include <string.h>
16 17
17 enum { 18 enum {
18 /* Maximum supported frame size in WebRTC is 60 ms. */ 19 /* Maximum supported frame size in WebRTC is 60 ms. */
19 kWebRtcOpusMaxEncodeFrameSizeMs = 60, 20 kWebRtcOpusMaxEncodeFrameSizeMs = 60,
20 21
21 /* The format allows up to 120 ms frames. Since we don't control the other 22 /* The format allows up to 120 ms frames. Since we don't control the other
22 * side, we must allow for packets of that size. NetEq is currently limited 23 * side, we must allow for packets of that size. NetEq is currently limited
23 * to 60 ms on the receive side. */ 24 * to 60 ms on the receive side. */
24 kWebRtcOpusMaxDecodeFrameSizeMs = 120, 25 kWebRtcOpusMaxDecodeFrameSizeMs = 120,
25 26
26 /* Maximum sample count per channel is 48 kHz * maximum frame size in 27 /* Maximum sample count per channel is 48 kHz * maximum frame size in
27 * milliseconds. */ 28 * milliseconds. */
28 kWebRtcOpusMaxFrameSizePerChannel = 48 * kWebRtcOpusMaxDecodeFrameSizeMs, 29 kWebRtcOpusMaxFrameSizePerChannel = 48 * kWebRtcOpusMaxDecodeFrameSizeMs,
29 30
30 /* Default frame size, 20 ms @ 48 kHz, in samples (for one channel). */ 31 /* Default frame size, 20 ms @ 48 kHz, in samples (for one channel). */
31 kWebRtcOpusDefaultFrameSize = 960, 32 kWebRtcOpusDefaultFrameSize = 960,
33
34 // Maximum number of consecutive zeros, beyond or equal to which DTX can fail.
35 kZeroBreakCount = 157,
36
37 #if defined(OPUS_FIXED_POINT)
38 kZeroBreakValue = 10,
39 #else
40 kZeroBreakValue = 1,
41 #endif
32 }; 42 };
33 43
34 int16_t WebRtcOpus_EncoderCreate(OpusEncInst** inst, 44 int16_t WebRtcOpus_EncoderCreate(OpusEncInst** inst,
35 int32_t channels, 45 int32_t channels,
36 int32_t application) { 46 int32_t application) {
37 OpusEncInst* state; 47 int opus_app;
38 if (inst != NULL) { 48 if (!inst)
39 state = (OpusEncInst*) calloc(1, sizeof(OpusEncInst)); 49 return -1;
40 if (state) {
41 int opus_app;
42 switch (application) {
43 case 0: {
44 opus_app = OPUS_APPLICATION_VOIP;
45 break;
46 }
47 case 1: {
48 opus_app = OPUS_APPLICATION_AUDIO;
49 break;
50 }
51 default: {
52 free(state);
53 return -1;
54 }
55 }
56 50
57 int error; 51 switch (application) {
58 state->encoder = opus_encoder_create(48000, channels, opus_app, 52 case 0:
59 &error); 53 opus_app = OPUS_APPLICATION_VOIP;
60 state->in_dtx_mode = 0; 54 break;
61 if (error == OPUS_OK && state->encoder != NULL) { 55 case 1:
62 *inst = state; 56 opus_app = OPUS_APPLICATION_AUDIO;
63 return 0; 57 break;
64 } 58 default:
65 free(state); 59 return -1;
66 }
67 } 60 }
68 return -1; 61
62 OpusEncInst* state = calloc(1, sizeof(OpusEncInst));
63 assert(state);
the sun 2015/11/09 12:41:00 This should really be an RTC_CHECK() as it is a po
minyue-webrtc 2015/11/09 15:13:00 c file made this a limit. may consider in a separa
64
65 // Allocate zero counters.
66 state->zero_counts = calloc(channels, sizeof(size_t));
67 assert(state->zero_counts);
68
69 int error;
70 state->encoder = opus_encoder_create(48000, channels, opus_app,
71 &error);
72 if (error != OPUS_OK || !state->encoder) {
73 WebRtcOpus_EncoderFree(state);
74 return -1;
75 }
76
77 state->in_dtx_mode = 0;
78 state->channels = channels;
79
80 *inst = state;
81 return 0;
69 } 82 }
70 83
71 int16_t WebRtcOpus_EncoderFree(OpusEncInst* inst) { 84 int16_t WebRtcOpus_EncoderFree(OpusEncInst* inst) {
72 if (inst) { 85 if (inst) {
73 opus_encoder_destroy(inst->encoder); 86 opus_encoder_destroy(inst->encoder);
87 free(inst->zero_counts);
74 free(inst); 88 free(inst);
75 return 0; 89 return 0;
76 } else { 90 } else {
77 return -1; 91 return -1;
78 } 92 }
79 } 93 }
80 94
81 int WebRtcOpus_Encode(OpusEncInst* inst, 95 int WebRtcOpus_Encode(OpusEncInst* inst,
82 const int16_t* audio_in, 96 const int16_t* audio_in,
83 size_t samples, 97 size_t samples,
84 size_t length_encoded_buffer, 98 size_t length_encoded_buffer,
85 uint8_t* encoded) { 99 uint8_t* encoded) {
86 int res; 100 int res;
101 size_t i;
the sun 2015/11/09 12:41:00 declare when these are used; even C99 supports tha
minyue-webrtc 2015/11/09 15:13:00 Karl wanted this be pre-C99 compatible. But, true
kwiberg-webrtc 2015/11/09 19:15:05 It's not that I *want* C89, it's just that the las
102 int c;
103
104 int16_t buffer[2 * 48 * kWebRtcOpusMaxEncodeFrameSizeMs];
the sun 2015/11/09 12:41:00 what if inst->channels > 2 ?
minyue-webrtc 2015/11/09 15:13:00 Emm, we really wanted this be statically allocated
the sun 2015/11/09 15:29:56 The problem is if channels > 2 we will get buffer
minyue-webrtc 2015/11/09 16:03:02 Yes, it can in principle happen, but the creation
87 105
88 if (samples > 48 * kWebRtcOpusMaxEncodeFrameSizeMs) { 106 if (samples > 48 * kWebRtcOpusMaxEncodeFrameSizeMs) {
89 return -1; 107 return -1;
90 } 108 }
91 109
110 const int channels = inst->channels;
111 int use_buffer = 0;
112
113 // Break long consecutive zeros by forcing a "1" every |kZeroBreakCount|
114 // samples.
115 if (inst->in_dtx_mode) {
116 for (i = 0; i < samples; ++i) {
117 for (c = 0; c < channels; ++c) {
118 if (audio_in[i * channels + c] == 0) {
119 ++inst->zero_counts[c];
120 if (inst->zero_counts[c] == kZeroBreakCount) {
121 if (!use_buffer) {
122 memcpy(buffer, audio_in, samples * channels * sizeof(int16_t));
the sun 2015/11/09 12:41:00 this looks like it will break if the count is reac
minyue-webrtc 2015/11/09 15:13:00 Doesn't use_buffer prevent multi-entry? Regarding
the sun 2015/11/09 15:29:56 Ah, my bad! You're quite right, should work like i
123 use_buffer = 1;
124 }
125 buffer[i * channels + c] = kZeroBreakValue;
126 inst->zero_counts[c] = 0;
127 }
128 } else {
129 inst->zero_counts[c] = 0;
130 }
131 }
132 }
133 }
134
92 res = opus_encode(inst->encoder, 135 res = opus_encode(inst->encoder,
93 (const opus_int16*)audio_in, 136 use_buffer ? buffer : audio_in,
94 (int)samples, 137 (int)samples,
95 encoded, 138 encoded,
96 (opus_int32)length_encoded_buffer); 139 (opus_int32)length_encoded_buffer);
97 140
98 if (res == 1) { 141 if (res == 1) {
99 // Indicates DTX since the packet has nothing but a header. In principle, 142 // Indicates DTX since the packet has nothing but a header. In principle,
100 // there is no need to send this packet. However, we do transmit the first 143 // there is no need to send this packet. However, we do transmit the first
101 // occurrence to let the decoder know that the encoder enters DTX mode. 144 // occurrence to let the decoder know that the encoder enters DTX mode.
102 if (inst->in_dtx_mode) { 145 if (inst->in_dtx_mode) {
103 return 0; 146 return 0;
(...skipping 348 matching lines...) Expand 10 before | Expand all | Expand 10 after
452 return 0; 495 return 0;
453 } 496 }
454 497
455 for (n = 0; n < channels; n++) { 498 for (n = 0; n < channels; n++) {
456 if (frame_data[0][0] & (0x80 >> ((n + 1) * (frames + 1) - 1))) 499 if (frame_data[0][0] & (0x80 >> ((n + 1) * (frames + 1) - 1)))
457 return 1; 500 return 1;
458 } 501 }
459 502
460 return 0; 503 return 0;
461 } 504 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698