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

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: rebase and a small fix 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>
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,
32 }; 36 };
33 37
34 int16_t WebRtcOpus_EncoderCreate(OpusEncInst** inst, 38 int16_t WebRtcOpus_EncoderCreate(OpusEncInst** inst,
35 int32_t channels, 39 int32_t channels,
36 int32_t application) { 40 int32_t application) {
37 OpusEncInst* state; 41 if (!inst)
38 if (inst != NULL) { 42 return -1;
39 state = (OpusEncInst*) calloc(1, sizeof(OpusEncInst));
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 43
57 int error; 44 int opus_app;
kwiberg-webrtc 2015/11/01 02:01:55 You're declaring variables not immediately followi
minyue-webrtc 2015/11/06 10:33:17 Done.
58 state->encoder = opus_encoder_create(48000, channels, opus_app, 45 switch (application) {
59 &error); 46 case 0: {
60 state->in_dtx_mode = 0; 47 opus_app = OPUS_APPLICATION_VOIP;
61 if (error == OPUS_OK && state->encoder != NULL) { 48 break;
62 *inst = state; 49 }
63 return 0; 50 case 1: {
64 } 51 opus_app = OPUS_APPLICATION_AUDIO;
65 free(state); 52 break;
53 }
54 default: {
55 return -1;
66 } 56 }
67 } 57 }
kwiberg-webrtc 2015/11/01 02:01:55 You don't need the braces for each case in the swi
minyue-webrtc 2015/11/06 10:33:17 I see. this existed before. But I can just change
68 return -1; 58
59 OpusEncInst* state = calloc(1, sizeof(OpusEncInst));
60 assert(state);
61
62 // Allocate zero counters.
63 state->zero_counts = calloc(channels, sizeof(size_t));
64 assert(state->zero_counts);
65
66 int error;
67 state->encoder = opus_encoder_create(48000, channels, opus_app,
68 &error);
69 if (error != OPUS_OK || !state->encoder) {
70 WebRtcOpus_EncoderFree(state);
71 return -1;
72 }
73
74 state->in_dtx_mode = 0;
75 state->channels = channels;
76
77 *inst = state;
78 return 0;
69 } 79 }
70 80
71 int16_t WebRtcOpus_EncoderFree(OpusEncInst* inst) { 81 int16_t WebRtcOpus_EncoderFree(OpusEncInst* inst) {
72 if (inst) { 82 if (inst) {
73 opus_encoder_destroy(inst->encoder); 83 opus_encoder_destroy(inst->encoder);
84 free(inst->zero_counts);
74 free(inst); 85 free(inst);
75 return 0; 86 return 0;
76 } else { 87 } else {
77 return -1; 88 return -1;
78 } 89 }
79 } 90 }
80 91
81 int WebRtcOpus_Encode(OpusEncInst* inst, 92 int WebRtcOpus_Encode(OpusEncInst* inst,
82 const int16_t* audio_in, 93 const int16_t* audio_in,
83 size_t samples, 94 size_t samples,
84 size_t length_encoded_buffer, 95 size_t length_encoded_buffer,
85 uint8_t* encoded) { 96 uint8_t* encoded) {
86 int res; 97 int res;
98 int16_t buffer[2 * 48 * kWebRtcOpusMaxEncodeFrameSizeMs];
87 99
88 if (samples > 48 * kWebRtcOpusMaxEncodeFrameSizeMs) { 100 if (samples > 48 * kWebRtcOpusMaxEncodeFrameSizeMs) {
89 return -1; 101 return -1;
90 } 102 }
91 103
104 const int channels = inst->channels;
105 int use_buffer = 0;
106
107 // Break long consecutive zeros by forcing a "1" every |kZeroBreakCount|
108 // samples.
109 if (inst->in_dtx_mode) {
110 size_t i;
111 int c;
112 for (i = 0; i < samples; ++i) {
113 for (c = 0; c < channels; ++c) {
114 if (audio_in[i * channels + c] == 0) {
115 ++inst->zero_counts[c];
116 if (inst->zero_counts[c] == kZeroBreakCount) {
117 if (!use_buffer) {
118 memcpy(buffer, audio_in, samples * channels * sizeof(int16_t));
119 use_buffer = 1;
120 }
121 buffer[i * channels + c] = 1;
122 inst->zero_counts[c] = 0;
123 }
124 } else {
125 inst->zero_counts[c] = 0;
126 }
127 }
128 }
129 }
130
131
132
92 res = opus_encode(inst->encoder, 133 res = opus_encode(inst->encoder,
93 (const opus_int16*)audio_in, 134 use_buffer ? buffer : audio_in,
kwiberg-webrtc 2015/11/01 02:01:55 The loop looks good now. But you have three blank
minyue-webrtc 2015/11/06 10:33:17 :)
94 (int)samples, 135 (int)samples,
95 encoded, 136 encoded,
96 (opus_int32)length_encoded_buffer); 137 (opus_int32)length_encoded_buffer);
97 138
98 if (res == 1) { 139 if (res == 1) {
99 // Indicates DTX since the packet has nothing but a header. In principle, 140 // 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 141 // 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. 142 // occurrence to let the decoder know that the encoder enters DTX mode.
102 if (inst->in_dtx_mode) { 143 if (inst->in_dtx_mode) {
103 return 0; 144 return 0;
(...skipping 348 matching lines...) Expand 10 before | Expand all | Expand 10 after
452 return 0; 493 return 0;
453 } 494 }
454 495
455 for (n = 0; n < channels; n++) { 496 for (n = 0; n < channels; n++) {
456 if (frame_data[0][0] & (0x80 >> ((n + 1) * (frames + 1) - 1))) 497 if (frame_data[0][0] & (0x80 >> ((n + 1) * (frames + 1) - 1)))
457 return 1; 498 return 1;
458 } 499 }
459 500
460 return 0; 501 return 0;
461 } 502 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698