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

Side by Side Diff: webrtc/modules/audio_coding/main/acm2/rent_a_codec_unittest.cc

Issue 1443653004: Move CNG and RED management into the Rent-A-Codec (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@master
Patch Set: Extract subroutine 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) 2015 The WebRTC project authors. All Rights Reserved. 2 * Copyright (c) 2015 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 "testing/gtest/include/gtest/gtest.h" 11 #include "testing/gtest/include/gtest/gtest.h"
12 #include "webrtc/base/arraysize.h"
13 #include "webrtc/modules/audio_coding/codecs/mock/mock_audio_encoder.h"
12 #include "webrtc/modules/audio_coding/main/acm2/rent_a_codec.h" 14 #include "webrtc/modules/audio_coding/main/acm2/rent_a_codec.h"
13 15
14 namespace webrtc { 16 namespace webrtc {
15 namespace acm2 { 17 namespace acm2 {
16 18
19 using ::testing::Return;
20
21 namespace {
22 const int kDataLengthSamples = 80;
23 const int kPacketSizeSamples = 2 * kDataLengthSamples;
24 const int16_t kZeroData[kDataLengthSamples] = {0};
25 const CodecInst kDefaultCodecInst = {0, "pcmu", 8000, kPacketSizeSamples,
26 1, 64000};
27 const int kCngPt = 13;
28 } // namespace
29
30 class RentACodecTestF : public ::testing::Test {
31 protected:
32 void CreateCodec() {
33 speech_encoder_ = rent_a_codec_.RentEncoder(kDefaultCodecInst);
34 ASSERT_TRUE(speech_encoder_);
35 encoder_ = rent_a_codec_.RentEncoderStack(
36 speech_encoder_, rtc::Optional<RentACodec::CngConfig>(
37 RentACodec::CngConfig{kCngPt, VADNormal}),
38 rtc::Optional<int>());
39 }
40
41 void EncodeAndVerify(size_t expected_out_length,
42 uint32_t expected_timestamp,
43 int expected_payload_type,
44 int expected_send_even_if_empty) {
45 uint8_t out[kPacketSizeSamples];
46 AudioEncoder::EncodedInfo encoded_info;
47 encoded_info =
48 encoder_->Encode(timestamp_, kZeroData, kPacketSizeSamples, out);
49 timestamp_ += kDataLengthSamples;
50 EXPECT_TRUE(encoded_info.redundant.empty());
51 EXPECT_EQ(expected_out_length, encoded_info.encoded_bytes);
52 EXPECT_EQ(expected_timestamp, encoded_info.encoded_timestamp);
53 if (expected_payload_type >= 0)
54 EXPECT_EQ(expected_payload_type, encoded_info.payload_type);
55 if (expected_send_even_if_empty >= 0)
56 EXPECT_EQ(static_cast<bool>(expected_send_even_if_empty),
57 encoded_info.send_even_if_empty);
58 }
59
60 RentACodec rent_a_codec_;
61 AudioEncoder* speech_encoder_ = nullptr;
62 AudioEncoder* encoder_ = nullptr;
63 uint32_t timestamp_ = 0;
64 };
65
66 // This test verifies that CNG frames are delivered as expected. Since the frame
67 // size is set to 20 ms, we expect the first encode call to produce no output
68 // (which is signaled as 0 bytes output of type kNoEncoding). The next encode
69 // call should produce one SID frame of 9 bytes. The third call should not
70 // result in any output (just like the first one). The fourth and final encode
71 // call should produce an "empty frame", which is like no output, but with
72 // AudioEncoder::EncodedInfo::send_even_if_empty set to true. (The reason to
73 // produce an empty frame is to drive sending of DTMF packets in the RTP/RTCP
74 // module.)
75 TEST_F(RentACodecTestF, VerifyCngFrames) {
76 CreateCodec();
77 uint32_t expected_timestamp = timestamp_;
78 // Verify no frame.
79 {
80 SCOPED_TRACE("First encoding");
81 EncodeAndVerify(0, expected_timestamp, -1, -1);
82 }
83
84 // Verify SID frame delivered.
85 {
86 SCOPED_TRACE("Second encoding");
87 EncodeAndVerify(9, expected_timestamp, kCngPt, 1);
88 }
89
90 // Verify no frame.
91 {
92 SCOPED_TRACE("Third encoding");
93 EncodeAndVerify(0, expected_timestamp, -1, -1);
94 }
95
96 // Verify NoEncoding.
97 expected_timestamp += 2 * kDataLengthSamples;
98 {
99 SCOPED_TRACE("Fourth encoding");
100 EncodeAndVerify(0, expected_timestamp, kCngPt, 1);
101 }
102 }
103
104 TEST(RentACodecTest, ExternalEncoder) {
105 MockAudioEncoder external_encoder;
106 RentACodec rac;
107 EXPECT_EQ(&external_encoder,
108 rac.RentEncoderStack(&external_encoder,
109 rtc::Optional<RentACodec::CngConfig>(),
110 rtc::Optional<int>()));
111 const int kSampleRateHz = 8000;
112 const int kPacketSizeSamples = kSampleRateHz / 100;
113 int16_t audio[kPacketSizeSamples] = {0};
114 uint8_t encoded[kPacketSizeSamples];
115 AudioEncoder::EncodedInfo info;
116 EXPECT_CALL(external_encoder, SampleRateHz())
117 .WillRepeatedly(Return(kSampleRateHz));
118 EXPECT_CALL(external_encoder, NumChannels()).WillRepeatedly(Return(1));
119
120 {
121 ::testing::InSequence s;
122 info.encoded_timestamp = 0;
123 EXPECT_CALL(external_encoder,
124 EncodeInternal(0, rtc::ArrayView<const int16_t>(audio),
125 arraysize(encoded), encoded))
126 .WillOnce(Return(info));
127 EXPECT_CALL(external_encoder, Mark("A"));
128 EXPECT_CALL(external_encoder, Mark("B"));
129 info.encoded_timestamp = 2;
130 EXPECT_CALL(external_encoder,
131 EncodeInternal(2, rtc::ArrayView<const int16_t>(audio),
132 arraysize(encoded), encoded))
133 .WillOnce(Return(info));
134 EXPECT_CALL(external_encoder, Die());
135 }
136
137 info = rac.GetEncoderStack()->Encode(0, audio, arraysize(encoded), encoded);
138 EXPECT_EQ(0u, info.encoded_timestamp);
139 external_encoder.Mark("A");
140
141 // Change to internal encoder.
142 CodecInst codec_inst = kDefaultCodecInst;
143 codec_inst.pacsize = kPacketSizeSamples;
144 AudioEncoder* enc = rac.RentEncoder(codec_inst);
145 ASSERT_TRUE(enc);
146 EXPECT_EQ(enc,
147 rac.RentEncoderStack(enc, rtc::Optional<RentACodec::CngConfig>(),
148 rtc::Optional<int>()));
149
150 // Don't expect any more calls to the external encoder.
151 info = rac.GetEncoderStack()->Encode(1, audio, arraysize(encoded), encoded);
152 external_encoder.Mark("B");
153
154 // Change back to external encoder again.
155 EXPECT_EQ(&external_encoder,
156 rac.RentEncoderStack(&external_encoder,
157 rtc::Optional<RentACodec::CngConfig>(),
158 rtc::Optional<int>()));
159 info = rac.GetEncoderStack()->Encode(2, audio, arraysize(encoded), encoded);
160 EXPECT_EQ(2u, info.encoded_timestamp);
161 }
162
163 // Verify that the speech encoder's Reset method is called when CNG or RED
164 // (or both) are switched on, but not when they're switched off.
165 void TestCngAndRedResetSpeechEncoder(bool use_cng, bool use_red) {
166 MockAudioEncoder speech_encoder;
167 EXPECT_CALL(speech_encoder, NumChannels()).WillRepeatedly(Return(1));
168 EXPECT_CALL(speech_encoder, Max10MsFramesInAPacket())
169 .WillRepeatedly(Return(2));
170 EXPECT_CALL(speech_encoder, SampleRateHz()).WillRepeatedly(Return(8000));
171 {
172 ::testing::InSequence s;
173 EXPECT_CALL(speech_encoder, Mark("disabled"));
174 EXPECT_CALL(speech_encoder, Mark("enabled"));
175 if (use_cng || use_red)
176 EXPECT_CALL(speech_encoder, Reset());
177 EXPECT_CALL(speech_encoder, Die());
178 }
179
180 auto cng_cfg = use_cng ? rtc::Optional<RentACodec::CngConfig>(
181 RentACodec::CngConfig{17, VADNormal})
182 : rtc::Optional<RentACodec::CngConfig>();
183 auto red_pt = use_red ? rtc::Optional<int>(19) : rtc::Optional<int>();
184 speech_encoder.Mark("disabled");
185 RentACodec rac;
186 rac.RentEncoderStack(&speech_encoder, rtc::Optional<RentACodec::CngConfig>(),
187 rtc::Optional<int>());
188 speech_encoder.Mark("enabled");
189 rac.RentEncoderStack(&speech_encoder, cng_cfg, red_pt);
190 }
191
192 TEST(RentACodecTest, CngResetsSpeechEncoder) {
193 TestCngAndRedResetSpeechEncoder(true, false);
194 }
195
196 TEST(RentACodecTest, RedResetsSpeechEncoder) {
197 TestCngAndRedResetSpeechEncoder(false, true);
198 }
199
200 TEST(RentACodecTest, CngAndRedResetsSpeechEncoder) {
201 TestCngAndRedResetSpeechEncoder(true, true);
202 }
203
204 TEST(RentACodecTest, NoCngAndRedNoSpeechEncoderReset) {
205 TestCngAndRedResetSpeechEncoder(false, false);
206 }
207
17 TEST(RentACodecTest, RentEncoderError) { 208 TEST(RentACodecTest, RentEncoderError) {
18 const CodecInst codec_inst = { 209 const CodecInst codec_inst = {
19 0, "Robert'); DROP TABLE Students;", 8000, 160, 1, 64000}; 210 0, "Robert'); DROP TABLE Students;", 8000, 160, 1, 64000};
20 RentACodec rent_a_codec; 211 RentACodec rent_a_codec;
21 EXPECT_FALSE(rent_a_codec.RentEncoder(codec_inst)); 212 EXPECT_FALSE(rent_a_codec.RentEncoder(codec_inst));
22 } 213 }
23 214
24 } // namespace acm2 215 } // namespace acm2
25 } // namespace webrtc 216 } // namespace webrtc
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698