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

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

Issue 1415163002: Removing AudioCoding class, a.k.a the new ACM API (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@master
Patch Set: Created 5 years, 2 months 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
(Empty)
1 /*
2 * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
3 *
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
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
11 #include "webrtc/modules/audio_coding/main/acm2/acm_receiver.h"
12
13 #include <algorithm> // std::min
14
15 #include "testing/gtest/include/gtest/gtest.h"
16 #include "webrtc/base/scoped_ptr.h"
17 #include "webrtc/modules/audio_coding/main/interface/audio_coding_module.h"
18 #include "webrtc/modules/audio_coding/main/acm2/audio_coding_module_impl.h"
19 #include "webrtc/modules/audio_coding/main/acm2/acm_codec_database.h"
20 #include "webrtc/modules/audio_coding/neteq/tools/rtp_generator.h"
21 #include "webrtc/system_wrappers/interface/clock.h"
22 #include "webrtc/test/test_suite.h"
23 #include "webrtc/test/testsupport/fileutils.h"
24 #include "webrtc/test/testsupport/gtest_disable.h"
25
26 namespace webrtc {
27
28 namespace acm2 {
29 namespace {
30
31 bool CodecsEqual(const CodecInst& codec_a, const CodecInst& codec_b) {
32 if (strcmp(codec_a.plname, codec_b.plname) != 0 ||
33 codec_a.plfreq != codec_b.plfreq ||
34 codec_a.pltype != codec_b.pltype ||
35 codec_b.channels != codec_a.channels)
36 return false;
37 return true;
38 }
39
40 } // namespace
41
42 class AcmReceiverTest : public AudioPacketizationCallback,
43 public ::testing::Test {
44 protected:
45 AcmReceiverTest()
46 : timestamp_(0),
47 packet_sent_(false),
48 last_packet_send_timestamp_(timestamp_),
49 last_frame_type_(kEmptyFrame) {
50 AudioCoding::Config config;
51 config.transport = this;
52 acm_.reset(new AudioCodingImpl(config));
53 receiver_.reset(new AcmReceiver(config.ToOldConfig()));
54 }
55
56 ~AcmReceiverTest() {}
57
58 void SetUp() override {
59 ASSERT_TRUE(receiver_.get() != NULL);
60 ASSERT_TRUE(acm_.get() != NULL);
61 for (int n = 0; n < ACMCodecDB::kNumCodecs; n++) {
62 ASSERT_EQ(0, ACMCodecDB::Codec(n, &codecs_[n]));
63 }
64
65 rtp_header_.header.sequenceNumber = 0;
66 rtp_header_.header.timestamp = 0;
67 rtp_header_.header.markerBit = false;
68 rtp_header_.header.ssrc = 0x12345678; // Arbitrary.
69 rtp_header_.header.numCSRCs = 0;
70 rtp_header_.header.payloadType = 0;
71 rtp_header_.frameType = kAudioFrameSpeech;
72 rtp_header_.type.Audio.isCNG = false;
73 }
74
75 void TearDown() override {}
76
77 void InsertOnePacketOfSilence(int codec_id) {
78 CodecInst codec;
79 ACMCodecDB::Codec(codec_id, &codec);
80 if (timestamp_ == 0) { // This is the first time inserting audio.
81 ASSERT_TRUE(acm_->RegisterSendCodec(codec_id, codec.pltype));
82 } else {
83 const CodecInst* current_codec = acm_->GetSenderCodecInst();
84 ASSERT_TRUE(current_codec);
85 if (!CodecsEqual(codec, *current_codec))
86 ASSERT_TRUE(acm_->RegisterSendCodec(codec_id, codec.pltype));
87 }
88 AudioFrame frame;
89 // Frame setup according to the codec.
90 frame.sample_rate_hz_ = codec.plfreq;
91 frame.samples_per_channel_ = codec.plfreq / 100; // 10 ms.
92 frame.num_channels_ = codec.channels;
93 memset(frame.data_, 0, frame.samples_per_channel_ * frame.num_channels_ *
94 sizeof(int16_t));
95 int num_bytes = 0;
96 packet_sent_ = false;
97 last_packet_send_timestamp_ = timestamp_;
98 while (num_bytes == 0) {
99 frame.timestamp_ = timestamp_;
100 timestamp_ += frame.samples_per_channel_;
101 num_bytes = acm_->Add10MsAudio(frame);
102 ASSERT_GE(num_bytes, 0);
103 }
104 ASSERT_TRUE(packet_sent_); // Sanity check.
105 }
106
107 // Last element of id should be negative.
108 void AddSetOfCodecs(const int* id) {
109 int n = 0;
110 while (id[n] >= 0) {
111 ASSERT_EQ(0, receiver_->AddCodec(id[n], codecs_[id[n]].pltype,
112 codecs_[id[n]].channels,
113 codecs_[id[n]].plfreq, NULL));
114 ++n;
115 }
116 }
117
118 int32_t SendData(FrameType frame_type,
119 uint8_t payload_type,
120 uint32_t timestamp,
121 const uint8_t* payload_data,
122 size_t payload_len_bytes,
123 const RTPFragmentationHeader* fragmentation) override {
124 if (frame_type == kEmptyFrame)
125 return 0;
126
127 rtp_header_.header.payloadType = payload_type;
128 rtp_header_.frameType = frame_type;
129 if (frame_type == kAudioFrameSpeech)
130 rtp_header_.type.Audio.isCNG = false;
131 else
132 rtp_header_.type.Audio.isCNG = true;
133 rtp_header_.header.timestamp = timestamp;
134
135 int ret_val = receiver_->InsertPacket(rtp_header_, payload_data,
136 payload_len_bytes);
137 if (ret_val < 0) {
138 assert(false);
139 return -1;
140 }
141 rtp_header_.header.sequenceNumber++;
142 packet_sent_ = true;
143 last_frame_type_ = frame_type;
144 return 0;
145 }
146
147 rtc::scoped_ptr<AcmReceiver> receiver_;
148 CodecInst codecs_[ACMCodecDB::kMaxNumCodecs];
149 rtc::scoped_ptr<AudioCoding> acm_;
150 WebRtcRTPHeader rtp_header_;
151 uint32_t timestamp_;
152 bool packet_sent_; // Set when SendData is called reset when inserting audio.
153 uint32_t last_packet_send_timestamp_;
154 FrameType last_frame_type_;
155 };
156
157 TEST_F(AcmReceiverTest, DISABLED_ON_ANDROID(AddCodecGetCodec)) {
158 // Add codec.
159 for (int n = 0; n < ACMCodecDB::kNumCodecs; ++n) {
160 if (n & 0x1) // Just add codecs with odd index.
161 EXPECT_EQ(0,
162 receiver_->AddCodec(n, codecs_[n].pltype, codecs_[n].channels,
163 codecs_[n].plfreq, NULL));
164 }
165 // Get codec and compare.
166 for (int n = 0; n < ACMCodecDB::kNumCodecs; ++n) {
167 CodecInst my_codec;
168 if (n & 0x1) {
169 // Codecs with odd index should match the reference.
170 EXPECT_EQ(0, receiver_->DecoderByPayloadType(codecs_[n].pltype,
171 &my_codec));
172 EXPECT_TRUE(CodecsEqual(codecs_[n], my_codec));
173 } else {
174 // Codecs with even index are not registered.
175 EXPECT_EQ(-1, receiver_->DecoderByPayloadType(codecs_[n].pltype,
176 &my_codec));
177 }
178 }
179 }
180
181 TEST_F(AcmReceiverTest, DISABLED_ON_ANDROID(AddCodecChangePayloadType)) {
182 const int codec_id = ACMCodecDB::kPCMA;
183 CodecInst ref_codec1;
184 EXPECT_EQ(0, ACMCodecDB::Codec(codec_id, &ref_codec1));
185 CodecInst ref_codec2 = ref_codec1;
186 ++ref_codec2.pltype;
187 CodecInst test_codec;
188
189 // Register the same codec with different payload types.
190 EXPECT_EQ(
191 0, receiver_->AddCodec(codec_id, ref_codec1.pltype, ref_codec1.channels,
192 ref_codec1.plfreq, NULL));
193 EXPECT_EQ(
194 0, receiver_->AddCodec(codec_id, ref_codec2.pltype, ref_codec2.channels,
195 ref_codec2.plfreq, NULL));
196
197 // Both payload types should exist.
198 EXPECT_EQ(0, receiver_->DecoderByPayloadType(ref_codec1.pltype, &test_codec));
199 EXPECT_EQ(true, CodecsEqual(ref_codec1, test_codec));
200 EXPECT_EQ(0, receiver_->DecoderByPayloadType(ref_codec2.pltype, &test_codec));
201 EXPECT_EQ(true, CodecsEqual(ref_codec2, test_codec));
202 }
203
204 TEST_F(AcmReceiverTest, DISABLED_ON_ANDROID(AddCodecChangeCodecId)) {
205 const int codec_id1 = ACMCodecDB::kPCMU;
206 CodecInst ref_codec1;
207 EXPECT_EQ(0, ACMCodecDB::Codec(codec_id1, &ref_codec1));
208 const int codec_id2 = ACMCodecDB::kPCMA;
209 CodecInst ref_codec2;
210 EXPECT_EQ(0, ACMCodecDB::Codec(codec_id2, &ref_codec2));
211 ref_codec2.pltype = ref_codec1.pltype;
212 CodecInst test_codec;
213
214 // Register the same payload type with different codec ID.
215 EXPECT_EQ(
216 0, receiver_->AddCodec(codec_id1, ref_codec1.pltype, ref_codec1.channels,
217 ref_codec1.plfreq, NULL));
218 EXPECT_EQ(
219 0, receiver_->AddCodec(codec_id2, ref_codec2.pltype, ref_codec2.channels,
220 ref_codec2.plfreq, NULL));
221
222 // Make sure that the last codec is used.
223 EXPECT_EQ(0, receiver_->DecoderByPayloadType(ref_codec2.pltype, &test_codec));
224 EXPECT_EQ(true, CodecsEqual(ref_codec2, test_codec));
225 }
226
227 TEST_F(AcmReceiverTest, DISABLED_ON_ANDROID(AddCodecRemoveCodec)) {
228 CodecInst codec;
229 const int codec_id = ACMCodecDB::kPCMA;
230 EXPECT_EQ(0, ACMCodecDB::Codec(codec_id, &codec));
231 const int payload_type = codec.pltype;
232 EXPECT_EQ(0, receiver_->AddCodec(codec_id, codec.pltype, codec.channels,
233 codec.plfreq, NULL));
234
235 // Remove non-existing codec should not fail. ACM1 legacy.
236 EXPECT_EQ(0, receiver_->RemoveCodec(payload_type + 1));
237
238 // Remove an existing codec.
239 EXPECT_EQ(0, receiver_->RemoveCodec(payload_type));
240
241 // Ask for the removed codec, must fail.
242 EXPECT_EQ(-1, receiver_->DecoderByPayloadType(payload_type, &codec));
243 }
244
245 TEST_F(AcmReceiverTest, DISABLED_ON_ANDROID(SampleRate)) {
246 const int kCodecId[] = {
247 ACMCodecDB::kISAC, ACMCodecDB::kISACSWB,
248 -1 // Terminator.
249 };
250 AddSetOfCodecs(kCodecId);
251
252 AudioFrame frame;
253 const int kOutSampleRateHz = 8000; // Different than codec sample rate.
254 int n = 0;
255 while (kCodecId[n] >= 0) {
256 const int num_10ms_frames = codecs_[kCodecId[n]].pacsize /
257 (codecs_[kCodecId[n]].plfreq / 100);
258 InsertOnePacketOfSilence(kCodecId[n]);
259 for (int k = 0; k < num_10ms_frames; ++k) {
260 EXPECT_EQ(0, receiver_->GetAudio(kOutSampleRateHz, &frame));
261 }
262 EXPECT_EQ(std::min(32000, codecs_[kCodecId[n]].plfreq),
263 receiver_->current_sample_rate_hz());
264 ++n;
265 }
266 }
267
268 TEST_F(AcmReceiverTest, DISABLED_ON_ANDROID(PostdecodingVad)) {
269 receiver_->EnableVad();
270 EXPECT_TRUE(receiver_->vad_enabled());
271
272 const int id = ACMCodecDB::kPCM16Bwb;
273 ASSERT_EQ(0, receiver_->AddCodec(id, codecs_[id].pltype, codecs_[id].channels,
274 codecs_[id].plfreq, NULL));
275 const int kNumPackets = 5;
276 const int num_10ms_frames = codecs_[id].pacsize / (codecs_[id].plfreq / 100);
277 AudioFrame frame;
278 for (int n = 0; n < kNumPackets; ++n) {
279 InsertOnePacketOfSilence(id);
280 for (int k = 0; k < num_10ms_frames; ++k)
281 ASSERT_EQ(0, receiver_->GetAudio(codecs_[id].plfreq, &frame));
282 }
283 EXPECT_EQ(AudioFrame::kVadPassive, frame.vad_activity_);
284
285 receiver_->DisableVad();
286 EXPECT_FALSE(receiver_->vad_enabled());
287
288 for (int n = 0; n < kNumPackets; ++n) {
289 InsertOnePacketOfSilence(id);
290 for (int k = 0; k < num_10ms_frames; ++k)
291 ASSERT_EQ(0, receiver_->GetAudio(codecs_[id].plfreq, &frame));
292 }
293 EXPECT_EQ(AudioFrame::kVadUnknown, frame.vad_activity_);
294 }
295
296 #ifdef WEBRTC_CODEC_ISAC
297 #define IF_ISAC_FLOAT(x) x
298 #else
299 #define IF_ISAC_FLOAT(x) DISABLED_##x
300 #endif
301
302 TEST_F(AcmReceiverTest, DISABLED_ON_ANDROID(IF_ISAC_FLOAT(LastAudioCodec))) {
303 const int kCodecId[] = {
304 ACMCodecDB::kISAC, ACMCodecDB::kPCMA, ACMCodecDB::kISACSWB,
305 ACMCodecDB::kPCM16Bswb32kHz,
306 -1 // Terminator.
307 };
308 AddSetOfCodecs(kCodecId);
309
310 const int kCngId[] = { // Not including full-band.
311 ACMCodecDB::kCNNB, ACMCodecDB::kCNWB, ACMCodecDB::kCNSWB,
312 -1 // Terminator.
313 };
314 AddSetOfCodecs(kCngId);
315
316 // Register CNG at sender side.
317 int n = 0;
318 while (kCngId[n] > 0) {
319 ASSERT_TRUE(acm_->RegisterSendCodec(kCngId[n], codecs_[kCngId[n]].pltype));
320 ++n;
321 }
322
323 CodecInst codec;
324 // No audio payload is received.
325 EXPECT_EQ(-1, receiver_->LastAudioCodec(&codec));
326
327 // Start with sending DTX.
328 ASSERT_TRUE(acm_->SetVad(true, true, VADVeryAggr));
329 packet_sent_ = false;
330 InsertOnePacketOfSilence(kCodecId[0]); // Enough to test with one codec.
331 ASSERT_TRUE(packet_sent_);
332 EXPECT_EQ(kAudioFrameCN, last_frame_type_);
333
334 // Has received, only, DTX. Last Audio codec is undefined.
335 EXPECT_EQ(-1, receiver_->LastAudioCodec(&codec));
336 EXPECT_EQ(-1, receiver_->last_audio_codec_id());
337
338 n = 0;
339 while (kCodecId[n] >= 0) { // Loop over codecs.
340 // Set DTX off to send audio payload.
341 acm_->SetVad(false, false, VADAggr);
342 packet_sent_ = false;
343 InsertOnePacketOfSilence(kCodecId[n]);
344
345 // Sanity check if Actually an audio payload received, and it should be
346 // of type "speech."
347 ASSERT_TRUE(packet_sent_);
348 ASSERT_EQ(kAudioFrameSpeech, last_frame_type_);
349 EXPECT_EQ(kCodecId[n], receiver_->last_audio_codec_id());
350
351 // Set VAD on to send DTX. Then check if the "Last Audio codec" returns
352 // the expected codec.
353 acm_->SetVad(true, true, VADAggr);
354
355 // Do as many encoding until a DTX is sent.
356 while (last_frame_type_ != kAudioFrameCN) {
357 packet_sent_ = false;
358 InsertOnePacketOfSilence(kCodecId[n]);
359 ASSERT_TRUE(packet_sent_);
360 }
361 EXPECT_EQ(kCodecId[n], receiver_->last_audio_codec_id());
362 EXPECT_EQ(0, receiver_->LastAudioCodec(&codec));
363 EXPECT_TRUE(CodecsEqual(codecs_[kCodecId[n]], codec));
364 ++n;
365 }
366 }
367
368 } // namespace acm2
369
370 } // namespace webrtc
OLDNEW
« no previous file with comments | « webrtc/modules/audio_coding/main/acm2/acm_receive_test.cc ('k') | webrtc/modules/audio_coding/main/acm2/acm_send_test.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698