OLD | NEW |
| (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/acm2/acm_receiver.h" | |
12 | |
13 #include <algorithm> // std::min | |
14 #include <memory> | |
15 | |
16 #include "webrtc/base/checks.h" | |
17 #include "webrtc/base/safe_conversions.h" | |
18 #include "webrtc/modules/audio_coding/codecs/builtin_audio_decoder_factory.h" | |
19 #include "webrtc/modules/audio_coding/include/audio_coding_module.h" | |
20 #include "webrtc/modules/audio_coding/neteq/tools/rtp_generator.h" | |
21 #include "webrtc/system_wrappers/include/clock.h" | |
22 #include "webrtc/test/gtest.h" | |
23 #include "webrtc/test/test_suite.h" | |
24 #include "webrtc/test/testsupport/fileutils.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 struct CodecIdInst { | |
41 explicit CodecIdInst(RentACodec::CodecId codec_id) { | |
42 const auto codec_ix = RentACodec::CodecIndexFromId(codec_id); | |
43 EXPECT_TRUE(codec_ix); | |
44 id = *codec_ix; | |
45 const auto codec_inst = RentACodec::CodecInstById(codec_id); | |
46 EXPECT_TRUE(codec_inst); | |
47 inst = *codec_inst; | |
48 } | |
49 int id; | |
50 CodecInst inst; | |
51 }; | |
52 | |
53 } // namespace | |
54 | |
55 class AcmReceiverTestOldApi : public AudioPacketizationCallback, | |
56 public ::testing::Test { | |
57 protected: | |
58 AcmReceiverTestOldApi() | |
59 : timestamp_(0), | |
60 packet_sent_(false), | |
61 last_packet_send_timestamp_(timestamp_), | |
62 last_frame_type_(kEmptyFrame) { | |
63 config_.decoder_factory = CreateBuiltinAudioDecoderFactory(); | |
64 } | |
65 | |
66 ~AcmReceiverTestOldApi() {} | |
67 | |
68 void SetUp() override { | |
69 acm_.reset(AudioCodingModule::Create(config_)); | |
70 receiver_.reset(new AcmReceiver(config_)); | |
71 ASSERT_TRUE(receiver_.get() != NULL); | |
72 ASSERT_TRUE(acm_.get() != NULL); | |
73 codecs_ = RentACodec::Database(); | |
74 | |
75 acm_->InitializeReceiver(); | |
76 acm_->RegisterTransportCallback(this); | |
77 | |
78 rtp_header_.header.sequenceNumber = 0; | |
79 rtp_header_.header.timestamp = 0; | |
80 rtp_header_.header.markerBit = false; | |
81 rtp_header_.header.ssrc = 0x12345678; // Arbitrary. | |
82 rtp_header_.header.numCSRCs = 0; | |
83 rtp_header_.header.payloadType = 0; | |
84 rtp_header_.frameType = kAudioFrameSpeech; | |
85 rtp_header_.type.Audio.isCNG = false; | |
86 } | |
87 | |
88 void TearDown() override {} | |
89 | |
90 void InsertOnePacketOfSilence(int codec_id) { | |
91 CodecInst codec = | |
92 *RentACodec::CodecInstById(*RentACodec::CodecIdFromIndex(codec_id)); | |
93 if (timestamp_ == 0) { // This is the first time inserting audio. | |
94 ASSERT_EQ(0, acm_->RegisterSendCodec(codec)); | |
95 } else { | |
96 auto current_codec = acm_->SendCodec(); | |
97 ASSERT_TRUE(current_codec); | |
98 if (!CodecsEqual(codec, *current_codec)) | |
99 ASSERT_EQ(0, acm_->RegisterSendCodec(codec)); | |
100 } | |
101 AudioFrame frame; | |
102 // Frame setup according to the codec. | |
103 frame.sample_rate_hz_ = codec.plfreq; | |
104 frame.samples_per_channel_ = codec.plfreq / 100; // 10 ms. | |
105 frame.num_channels_ = codec.channels; | |
106 memset(frame.data_, 0, frame.samples_per_channel_ * frame.num_channels_ * | |
107 sizeof(int16_t)); | |
108 packet_sent_ = false; | |
109 last_packet_send_timestamp_ = timestamp_; | |
110 while (!packet_sent_) { | |
111 frame.timestamp_ = timestamp_; | |
112 timestamp_ += frame.samples_per_channel_; | |
113 ASSERT_GE(acm_->Add10MsData(frame), 0); | |
114 } | |
115 } | |
116 | |
117 template <size_t N> | |
118 void AddSetOfCodecs(const RentACodec::CodecId(&ids)[N]) { | |
119 for (auto id : ids) { | |
120 const auto i = RentACodec::CodecIndexFromId(id); | |
121 ASSERT_TRUE(i); | |
122 ASSERT_EQ(0, receiver_->AddCodec(*i, codecs_[*i].pltype, | |
123 codecs_[*i].channels, codecs_[*i].plfreq, | |
124 nullptr, codecs_[*i].plname)); | |
125 } | |
126 } | |
127 | |
128 int SendData(FrameType frame_type, | |
129 uint8_t payload_type, | |
130 uint32_t timestamp, | |
131 const uint8_t* payload_data, | |
132 size_t payload_len_bytes, | |
133 const RTPFragmentationHeader* fragmentation) override { | |
134 if (frame_type == kEmptyFrame) | |
135 return 0; | |
136 | |
137 rtp_header_.header.payloadType = payload_type; | |
138 rtp_header_.frameType = frame_type; | |
139 if (frame_type == kAudioFrameSpeech) | |
140 rtp_header_.type.Audio.isCNG = false; | |
141 else | |
142 rtp_header_.type.Audio.isCNG = true; | |
143 rtp_header_.header.timestamp = timestamp; | |
144 | |
145 int ret_val = receiver_->InsertPacket( | |
146 rtp_header_, | |
147 rtc::ArrayView<const uint8_t>(payload_data, payload_len_bytes)); | |
148 if (ret_val < 0) { | |
149 assert(false); | |
150 return -1; | |
151 } | |
152 rtp_header_.header.sequenceNumber++; | |
153 packet_sent_ = true; | |
154 last_frame_type_ = frame_type; | |
155 return 0; | |
156 } | |
157 | |
158 AudioCodingModule::Config config_; | |
159 std::unique_ptr<AcmReceiver> receiver_; | |
160 rtc::ArrayView<const CodecInst> codecs_; | |
161 std::unique_ptr<AudioCodingModule> acm_; | |
162 WebRtcRTPHeader rtp_header_; | |
163 uint32_t timestamp_; | |
164 bool packet_sent_; // Set when SendData is called reset when inserting audio. | |
165 uint32_t last_packet_send_timestamp_; | |
166 FrameType last_frame_type_; | |
167 }; | |
168 | |
169 #if defined(WEBRTC_ANDROID) | |
170 #define MAYBE_AddCodecGetCodec DISABLED_AddCodecGetCodec | |
171 #else | |
172 #define MAYBE_AddCodecGetCodec AddCodecGetCodec | |
173 #endif | |
174 TEST_F(AcmReceiverTestOldApi, MAYBE_AddCodecGetCodec) { | |
175 // Add codec. | |
176 for (size_t n = 0; n < codecs_.size(); ++n) { | |
177 if (n & 0x1) { // Just add codecs with odd index. | |
178 EXPECT_EQ( | |
179 0, receiver_->AddCodec(n, codecs_[n].pltype, codecs_[n].channels, | |
180 codecs_[n].plfreq, NULL, codecs_[n].plname)); | |
181 } | |
182 } | |
183 // Get codec and compare. | |
184 for (size_t n = 0; n < codecs_.size(); ++n) { | |
185 CodecInst my_codec; | |
186 if (n & 0x1) { | |
187 // Codecs with odd index should match the reference. | |
188 EXPECT_EQ(0, receiver_->DecoderByPayloadType(codecs_[n].pltype, | |
189 &my_codec)); | |
190 EXPECT_TRUE(CodecsEqual(codecs_[n], my_codec)); | |
191 } else { | |
192 // Codecs with even index are not registered. | |
193 EXPECT_EQ(-1, receiver_->DecoderByPayloadType(codecs_[n].pltype, | |
194 &my_codec)); | |
195 } | |
196 } | |
197 } | |
198 | |
199 #if defined(WEBRTC_ANDROID) | |
200 #define MAYBE_AddCodecChangePayloadType DISABLED_AddCodecChangePayloadType | |
201 #else | |
202 #define MAYBE_AddCodecChangePayloadType AddCodecChangePayloadType | |
203 #endif | |
204 TEST_F(AcmReceiverTestOldApi, MAYBE_AddCodecChangePayloadType) { | |
205 const CodecIdInst codec1(RentACodec::CodecId::kPCMA); | |
206 CodecInst codec2 = codec1.inst; | |
207 ++codec2.pltype; | |
208 CodecInst test_codec; | |
209 | |
210 // Register the same codec with different payloads. | |
211 EXPECT_EQ(0, receiver_->AddCodec(codec1.id, codec1.inst.pltype, | |
212 codec1.inst.channels, codec1.inst.plfreq, | |
213 nullptr, codec1.inst.plname)); | |
214 EXPECT_EQ(0, receiver_->AddCodec(codec1.id, codec2.pltype, codec2.channels, | |
215 codec2.plfreq, NULL, codec2.plname)); | |
216 | |
217 // Both payload types should exist. | |
218 EXPECT_EQ(0, | |
219 receiver_->DecoderByPayloadType(codec1.inst.pltype, &test_codec)); | |
220 EXPECT_EQ(true, CodecsEqual(codec1.inst, test_codec)); | |
221 EXPECT_EQ(0, receiver_->DecoderByPayloadType(codec2.pltype, &test_codec)); | |
222 EXPECT_EQ(true, CodecsEqual(codec2, test_codec)); | |
223 } | |
224 | |
225 #if defined(WEBRTC_ANDROID) | |
226 #define MAYBE_AddCodecChangeCodecId DISABLED_AddCodecChangeCodecId | |
227 #else | |
228 #define MAYBE_AddCodecChangeCodecId AddCodecChangeCodecId | |
229 #endif | |
230 TEST_F(AcmReceiverTestOldApi, AddCodecChangeCodecId) { | |
231 const CodecIdInst codec1(RentACodec::CodecId::kPCMU); | |
232 CodecIdInst codec2(RentACodec::CodecId::kPCMA); | |
233 codec2.inst.pltype = codec1.inst.pltype; | |
234 CodecInst test_codec; | |
235 | |
236 // Register the same payload type with different codec ID. | |
237 EXPECT_EQ(0, receiver_->AddCodec(codec1.id, codec1.inst.pltype, | |
238 codec1.inst.channels, codec1.inst.plfreq, | |
239 nullptr, codec1.inst.plname)); | |
240 EXPECT_EQ(0, receiver_->AddCodec(codec2.id, codec2.inst.pltype, | |
241 codec2.inst.channels, codec2.inst.plfreq, | |
242 nullptr, codec2.inst.plname)); | |
243 | |
244 // Make sure that the last codec is used. | |
245 EXPECT_EQ(0, | |
246 receiver_->DecoderByPayloadType(codec2.inst.pltype, &test_codec)); | |
247 EXPECT_EQ(true, CodecsEqual(codec2.inst, test_codec)); | |
248 } | |
249 | |
250 #if defined(WEBRTC_ANDROID) | |
251 #define MAYBE_AddCodecRemoveCodec DISABLED_AddCodecRemoveCodec | |
252 #else | |
253 #define MAYBE_AddCodecRemoveCodec AddCodecRemoveCodec | |
254 #endif | |
255 TEST_F(AcmReceiverTestOldApi, MAYBE_AddCodecRemoveCodec) { | |
256 const CodecIdInst codec(RentACodec::CodecId::kPCMA); | |
257 const int payload_type = codec.inst.pltype; | |
258 EXPECT_EQ( | |
259 0, receiver_->AddCodec(codec.id, codec.inst.pltype, codec.inst.channels, | |
260 codec.inst.plfreq, nullptr, codec.inst.plname)); | |
261 | |
262 // Remove non-existing codec should not fail. ACM1 legacy. | |
263 EXPECT_EQ(0, receiver_->RemoveCodec(payload_type + 1)); | |
264 | |
265 // Remove an existing codec. | |
266 EXPECT_EQ(0, receiver_->RemoveCodec(payload_type)); | |
267 | |
268 // Ask for the removed codec, must fail. | |
269 CodecInst ci; | |
270 EXPECT_EQ(-1, receiver_->DecoderByPayloadType(payload_type, &ci)); | |
271 } | |
272 | |
273 #if defined(WEBRTC_ANDROID) | |
274 #define MAYBE_SampleRate DISABLED_SampleRate | |
275 #else | |
276 #define MAYBE_SampleRate SampleRate | |
277 #endif | |
278 TEST_F(AcmReceiverTestOldApi, MAYBE_SampleRate) { | |
279 const RentACodec::CodecId kCodecId[] = {RentACodec::CodecId::kISAC, | |
280 RentACodec::CodecId::kISACSWB}; | |
281 AddSetOfCodecs(kCodecId); | |
282 | |
283 AudioFrame frame; | |
284 const int kOutSampleRateHz = 8000; // Different than codec sample rate. | |
285 for (const auto codec_id : kCodecId) { | |
286 const CodecIdInst codec(codec_id); | |
287 const int num_10ms_frames = codec.inst.pacsize / (codec.inst.plfreq / 100); | |
288 InsertOnePacketOfSilence(codec.id); | |
289 for (int k = 0; k < num_10ms_frames; ++k) { | |
290 bool muted; | |
291 EXPECT_EQ(0, receiver_->GetAudio(kOutSampleRateHz, &frame, &muted)); | |
292 } | |
293 EXPECT_EQ(codec.inst.plfreq, receiver_->last_output_sample_rate_hz()); | |
294 } | |
295 } | |
296 | |
297 class AcmReceiverTestFaxModeOldApi : public AcmReceiverTestOldApi { | |
298 protected: | |
299 AcmReceiverTestFaxModeOldApi() { | |
300 config_.neteq_config.playout_mode = kPlayoutFax; | |
301 } | |
302 | |
303 void RunVerifyAudioFrame(RentACodec::CodecId codec_id) { | |
304 // Make sure "fax mode" is enabled. This will avoid delay changes unless the | |
305 // packet-loss concealment is made. We do this in order to make the | |
306 // timestamp increments predictable; in normal mode, NetEq may decide to do | |
307 // accelerate or pre-emptive expand operations after some time, offsetting | |
308 // the timestamp. | |
309 EXPECT_EQ(kPlayoutFax, config_.neteq_config.playout_mode); | |
310 | |
311 const RentACodec::CodecId kCodecId[] = {codec_id}; | |
312 AddSetOfCodecs(kCodecId); | |
313 | |
314 const CodecIdInst codec(codec_id); | |
315 const int output_sample_rate_hz = codec.inst.plfreq; | |
316 const size_t output_channels = codec.inst.channels; | |
317 const size_t samples_per_ms = rtc::checked_cast<size_t>( | |
318 rtc::CheckedDivExact(output_sample_rate_hz, 1000)); | |
319 const int num_10ms_frames = rtc::CheckedDivExact( | |
320 codec.inst.pacsize, rtc::checked_cast<int>(10 * samples_per_ms)); | |
321 const AudioFrame::VADActivity expected_vad_activity = | |
322 output_sample_rate_hz > 16000 ? AudioFrame::kVadActive | |
323 : AudioFrame::kVadPassive; | |
324 | |
325 // Expect the first output timestamp to be 5*fs/8000 samples before the | |
326 // first inserted timestamp (because of NetEq's look-ahead). (This value is | |
327 // defined in Expand::overlap_length_.) | |
328 uint32_t expected_output_ts = last_packet_send_timestamp_ - | |
329 rtc::CheckedDivExact(5 * output_sample_rate_hz, 8000); | |
330 | |
331 AudioFrame frame; | |
332 bool muted; | |
333 EXPECT_EQ(0, receiver_->GetAudio(output_sample_rate_hz, &frame, &muted)); | |
334 // Expect timestamp = 0 before first packet is inserted. | |
335 EXPECT_EQ(0u, frame.timestamp_); | |
336 for (int i = 0; i < 5; ++i) { | |
337 InsertOnePacketOfSilence(codec.id); | |
338 for (int k = 0; k < num_10ms_frames; ++k) { | |
339 EXPECT_EQ(0, | |
340 receiver_->GetAudio(output_sample_rate_hz, &frame, &muted)); | |
341 EXPECT_EQ(expected_output_ts, frame.timestamp_); | |
342 expected_output_ts += 10 * samples_per_ms; | |
343 EXPECT_EQ(10 * samples_per_ms, frame.samples_per_channel_); | |
344 EXPECT_EQ(output_sample_rate_hz, frame.sample_rate_hz_); | |
345 EXPECT_EQ(output_channels, frame.num_channels_); | |
346 EXPECT_EQ(AudioFrame::kNormalSpeech, frame.speech_type_); | |
347 EXPECT_EQ(expected_vad_activity, frame.vad_activity_); | |
348 EXPECT_FALSE(muted); | |
349 } | |
350 } | |
351 } | |
352 }; | |
353 | |
354 #if defined(WEBRTC_ANDROID) | |
355 #define MAYBE_VerifyAudioFramePCMU DISABLED_VerifyAudioFramePCMU | |
356 #else | |
357 #define MAYBE_VerifyAudioFramePCMU VerifyAudioFramePCMU | |
358 #endif | |
359 TEST_F(AcmReceiverTestFaxModeOldApi, MAYBE_VerifyAudioFramePCMU) { | |
360 RunVerifyAudioFrame(RentACodec::CodecId::kPCMU); | |
361 } | |
362 | |
363 #if defined(WEBRTC_ANDROID) | |
364 #define MAYBE_VerifyAudioFrameISAC DISABLED_VerifyAudioFrameISAC | |
365 #else | |
366 #define MAYBE_VerifyAudioFrameISAC VerifyAudioFrameISAC | |
367 #endif | |
368 TEST_F(AcmReceiverTestFaxModeOldApi, MAYBE_VerifyAudioFrameISAC) { | |
369 RunVerifyAudioFrame(RentACodec::CodecId::kISAC); | |
370 } | |
371 | |
372 #if defined(WEBRTC_ANDROID) | |
373 #define MAYBE_VerifyAudioFrameOpus DISABLED_VerifyAudioFrameOpus | |
374 #else | |
375 #define MAYBE_VerifyAudioFrameOpus VerifyAudioFrameOpus | |
376 #endif | |
377 TEST_F(AcmReceiverTestFaxModeOldApi, MAYBE_VerifyAudioFrameOpus) { | |
378 RunVerifyAudioFrame(RentACodec::CodecId::kOpus); | |
379 } | |
380 | |
381 #if defined(WEBRTC_ANDROID) | |
382 #define MAYBE_PostdecodingVad DISABLED_PostdecodingVad | |
383 #else | |
384 #define MAYBE_PostdecodingVad PostdecodingVad | |
385 #endif | |
386 TEST_F(AcmReceiverTestOldApi, MAYBE_PostdecodingVad) { | |
387 EXPECT_TRUE(config_.neteq_config.enable_post_decode_vad); | |
388 const CodecIdInst codec(RentACodec::CodecId::kPCM16Bwb); | |
389 ASSERT_EQ( | |
390 0, receiver_->AddCodec(codec.id, codec.inst.pltype, codec.inst.channels, | |
391 codec.inst.plfreq, nullptr, "")); | |
392 const int kNumPackets = 5; | |
393 const int num_10ms_frames = codec.inst.pacsize / (codec.inst.plfreq / 100); | |
394 AudioFrame frame; | |
395 for (int n = 0; n < kNumPackets; ++n) { | |
396 InsertOnePacketOfSilence(codec.id); | |
397 for (int k = 0; k < num_10ms_frames; ++k) { | |
398 bool muted; | |
399 ASSERT_EQ(0, receiver_->GetAudio(codec.inst.plfreq, &frame, &muted)); | |
400 } | |
401 } | |
402 EXPECT_EQ(AudioFrame::kVadPassive, frame.vad_activity_); | |
403 } | |
404 | |
405 class AcmReceiverTestPostDecodeVadPassiveOldApi : public AcmReceiverTestOldApi { | |
406 protected: | |
407 AcmReceiverTestPostDecodeVadPassiveOldApi() { | |
408 config_.neteq_config.enable_post_decode_vad = false; | |
409 } | |
410 }; | |
411 | |
412 #if defined(WEBRTC_ANDROID) | |
413 #define MAYBE_PostdecodingVad DISABLED_PostdecodingVad | |
414 #else | |
415 #define MAYBE_PostdecodingVad PostdecodingVad | |
416 #endif | |
417 TEST_F(AcmReceiverTestPostDecodeVadPassiveOldApi, MAYBE_PostdecodingVad) { | |
418 EXPECT_FALSE(config_.neteq_config.enable_post_decode_vad); | |
419 const CodecIdInst codec(RentACodec::CodecId::kPCM16Bwb); | |
420 ASSERT_EQ( | |
421 0, receiver_->AddCodec(codec.id, codec.inst.pltype, codec.inst.channels, | |
422 codec.inst.plfreq, nullptr, "")); | |
423 const int kNumPackets = 5; | |
424 const int num_10ms_frames = codec.inst.pacsize / (codec.inst.plfreq / 100); | |
425 AudioFrame frame; | |
426 for (int n = 0; n < kNumPackets; ++n) { | |
427 InsertOnePacketOfSilence(codec.id); | |
428 for (int k = 0; k < num_10ms_frames; ++k) { | |
429 bool muted; | |
430 ASSERT_EQ(0, receiver_->GetAudio(codec.inst.plfreq, &frame, &muted)); | |
431 } | |
432 } | |
433 EXPECT_EQ(AudioFrame::kVadUnknown, frame.vad_activity_); | |
434 } | |
435 | |
436 #if defined(WEBRTC_ANDROID) | |
437 #define MAYBE_LastAudioCodec DISABLED_LastAudioCodec | |
438 #else | |
439 #define MAYBE_LastAudioCodec LastAudioCodec | |
440 #endif | |
441 #if defined(WEBRTC_CODEC_ISAC) | |
442 TEST_F(AcmReceiverTestOldApi, MAYBE_LastAudioCodec) { | |
443 const RentACodec::CodecId kCodecId[] = { | |
444 RentACodec::CodecId::kISAC, RentACodec::CodecId::kPCMA, | |
445 RentACodec::CodecId::kISACSWB, RentACodec::CodecId::kPCM16Bswb32kHz}; | |
446 AddSetOfCodecs(kCodecId); | |
447 | |
448 const RentACodec::CodecId kCngId[] = { | |
449 // Not including full-band. | |
450 RentACodec::CodecId::kCNNB, RentACodec::CodecId::kCNWB, | |
451 RentACodec::CodecId::kCNSWB}; | |
452 AddSetOfCodecs(kCngId); | |
453 | |
454 // Register CNG at sender side. | |
455 for (auto id : kCngId) | |
456 ASSERT_EQ(0, acm_->RegisterSendCodec(CodecIdInst(id).inst)); | |
457 | |
458 CodecInst codec; | |
459 // No audio payload is received. | |
460 EXPECT_EQ(-1, receiver_->LastAudioCodec(&codec)); | |
461 | |
462 // Start with sending DTX. | |
463 ASSERT_EQ(0, acm_->SetVAD(true, true, VADVeryAggr)); | |
464 packet_sent_ = false; | |
465 InsertOnePacketOfSilence(CodecIdInst(kCodecId[0]).id); // Enough to test | |
466 // with one codec. | |
467 ASSERT_TRUE(packet_sent_); | |
468 EXPECT_EQ(kAudioFrameCN, last_frame_type_); | |
469 | |
470 // Has received, only, DTX. Last Audio codec is undefined. | |
471 EXPECT_EQ(-1, receiver_->LastAudioCodec(&codec)); | |
472 EXPECT_FALSE(receiver_->last_packet_sample_rate_hz()); | |
473 | |
474 for (auto id : kCodecId) { | |
475 const CodecIdInst c(id); | |
476 | |
477 // Set DTX off to send audio payload. | |
478 acm_->SetVAD(false, false, VADAggr); | |
479 packet_sent_ = false; | |
480 InsertOnePacketOfSilence(c.id); | |
481 | |
482 // Sanity check if Actually an audio payload received, and it should be | |
483 // of type "speech." | |
484 ASSERT_TRUE(packet_sent_); | |
485 ASSERT_EQ(kAudioFrameSpeech, last_frame_type_); | |
486 EXPECT_EQ(rtc::Optional<int>(c.inst.plfreq), | |
487 receiver_->last_packet_sample_rate_hz()); | |
488 | |
489 // Set VAD on to send DTX. Then check if the "Last Audio codec" returns | |
490 // the expected codec. | |
491 acm_->SetVAD(true, true, VADAggr); | |
492 | |
493 // Do as many encoding until a DTX is sent. | |
494 while (last_frame_type_ != kAudioFrameCN) { | |
495 packet_sent_ = false; | |
496 InsertOnePacketOfSilence(c.id); | |
497 ASSERT_TRUE(packet_sent_); | |
498 } | |
499 EXPECT_EQ(rtc::Optional<int>(c.inst.plfreq), | |
500 receiver_->last_packet_sample_rate_hz()); | |
501 EXPECT_EQ(0, receiver_->LastAudioCodec(&codec)); | |
502 EXPECT_TRUE(CodecsEqual(c.inst, codec)); | |
503 } | |
504 } | |
505 #endif | |
506 | |
507 } // namespace acm2 | |
508 | |
509 } // namespace webrtc | |
OLD | NEW |