Index: webrtc/modules/audio_coding/neteq/neteq_unittest.cc |
diff --git a/webrtc/modules/audio_coding/neteq/neteq_unittest.cc b/webrtc/modules/audio_coding/neteq/neteq_unittest.cc |
index 69c3876354776ce309bad9fd6fa8773a51f5ec8a..4a6f505fc639c4edb0b515f712a471ec0c9237cc 100644 |
--- a/webrtc/modules/audio_coding/neteq/neteq_unittest.cc |
+++ b/webrtc/modules/audio_coding/neteq/neteq_unittest.cc |
@@ -119,6 +119,49 @@ void AddMessage(FILE* file, rtc::MessageDigest* digest, |
#endif // WEBRTC_NETEQ_UNITTEST_BITEXACT |
+void LoadDecoders(webrtc::NetEq* neteq) { |
+ // Load PCMu. |
+ ASSERT_EQ(0, neteq->RegisterPayloadType(webrtc::NetEqDecoder::kDecoderPCMu, |
+ "pcmu", 0)); |
+ // Load PCMa. |
+ ASSERT_EQ(0, neteq->RegisterPayloadType(webrtc::NetEqDecoder::kDecoderPCMa, |
+ "pcma", 8)); |
+#ifdef WEBRTC_CODEC_ILBC |
+ // Load iLBC. |
+ ASSERT_EQ(0, neteq->RegisterPayloadType(webrtc::NetEqDecoder::kDecoderILBC, |
+ "ilbc", 102)); |
+#endif |
+#if defined(WEBRTC_CODEC_ISAC) || defined(WEBRTC_CODEC_ISACFX) |
+ // Load iSAC. |
+ ASSERT_EQ(0, neteq->RegisterPayloadType(webrtc::NetEqDecoder::kDecoderISAC, |
+ "isac", 103)); |
+#endif |
+#ifdef WEBRTC_CODEC_ISAC |
+ // Load iSAC SWB. |
+ ASSERT_EQ(0, neteq->RegisterPayloadType(webrtc::NetEqDecoder::kDecoderISACswb, |
+ "isac-swb", 104)); |
+#endif |
+#ifdef WEBRTC_CODEC_OPUS |
+ ASSERT_EQ(0, neteq->RegisterPayloadType(webrtc::NetEqDecoder::kDecoderOpus, |
+ "opus", 111)); |
+#endif |
+ // Load PCM16B nb. |
+ ASSERT_EQ(0, neteq->RegisterPayloadType(webrtc::NetEqDecoder::kDecoderPCM16B, |
+ "pcm16-nb", 93)); |
+ // Load PCM16B wb. |
+ ASSERT_EQ(0, neteq->RegisterPayloadType( |
+ webrtc::NetEqDecoder::kDecoderPCM16Bwb, "pcm16-wb", 94)); |
+ // Load PCM16B swb32. |
+ ASSERT_EQ( |
+ 0, neteq->RegisterPayloadType( |
+ webrtc::NetEqDecoder::kDecoderPCM16Bswb32kHz, "pcm16-swb32", 95)); |
+ // Load CNG 8 kHz. |
+ ASSERT_EQ(0, neteq->RegisterPayloadType(webrtc::NetEqDecoder::kDecoderCNGnb, |
+ "cng-nb", 13)); |
+ // Load CNG 16 kHz. |
+ ASSERT_EQ(0, neteq->RegisterPayloadType(webrtc::NetEqDecoder::kDecoderCNGwb, |
+ "cng-wb", 98)); |
+} |
} // namespace |
namespace webrtc { |
@@ -213,7 +256,6 @@ class NetEqDecodingTest : public ::testing::Test { |
virtual void SetUp(); |
virtual void TearDown(); |
void SelectDecoders(NetEqDecoder* used_codec); |
- void LoadDecoders(); |
void OpenInputFile(const std::string &rtp_file); |
void Process(); |
@@ -278,56 +320,13 @@ void NetEqDecodingTest::SetUp() { |
ASSERT_EQ(0, neteq_->NetworkStatistics(&stat)); |
algorithmic_delay_ms_ = stat.current_buffer_size_ms; |
ASSERT_TRUE(neteq_); |
- LoadDecoders(); |
+ LoadDecoders(neteq_); |
} |
void NetEqDecodingTest::TearDown() { |
delete neteq_; |
} |
-void NetEqDecodingTest::LoadDecoders() { |
- // Load PCMu. |
- ASSERT_EQ(0, |
- neteq_->RegisterPayloadType(NetEqDecoder::kDecoderPCMu, "pcmu", 0)); |
- // Load PCMa. |
- ASSERT_EQ(0, |
- neteq_->RegisterPayloadType(NetEqDecoder::kDecoderPCMa, "pcma", 8)); |
-#ifdef WEBRTC_CODEC_ILBC |
- // Load iLBC. |
- ASSERT_EQ( |
- 0, neteq_->RegisterPayloadType(NetEqDecoder::kDecoderILBC, "ilbc", 102)); |
-#endif |
-#if defined(WEBRTC_CODEC_ISAC) || defined(WEBRTC_CODEC_ISACFX) |
- // Load iSAC. |
- ASSERT_EQ( |
- 0, neteq_->RegisterPayloadType(NetEqDecoder::kDecoderISAC, "isac", 103)); |
-#endif |
-#ifdef WEBRTC_CODEC_ISAC |
- // Load iSAC SWB. |
- ASSERT_EQ(0, neteq_->RegisterPayloadType(NetEqDecoder::kDecoderISACswb, |
- "isac-swb", 104)); |
-#endif |
-#ifdef WEBRTC_CODEC_OPUS |
- ASSERT_EQ(0, neteq_->RegisterPayloadType(NetEqDecoder::kDecoderOpus, |
- "opus", 111)); |
-#endif |
- // Load PCM16B nb. |
- ASSERT_EQ(0, neteq_->RegisterPayloadType(NetEqDecoder::kDecoderPCM16B, |
- "pcm16-nb", 93)); |
- // Load PCM16B wb. |
- ASSERT_EQ(0, neteq_->RegisterPayloadType(NetEqDecoder::kDecoderPCM16Bwb, |
- "pcm16-wb", 94)); |
- // Load PCM16B swb32. |
- ASSERT_EQ(0, neteq_->RegisterPayloadType(NetEqDecoder::kDecoderPCM16Bswb32kHz, |
- "pcm16-swb32", 95)); |
- // Load CNG 8 kHz. |
- ASSERT_EQ(0, neteq_->RegisterPayloadType(NetEqDecoder::kDecoderCNGnb, |
- "cng-nb", 13)); |
- // Load CNG 16 kHz. |
- ASSERT_EQ(0, neteq_->RegisterPayloadType(NetEqDecoder::kDecoderCNGwb, |
- "cng-wb", 98)); |
-} |
- |
void NetEqDecodingTest::OpenInputFile(const std::string &rtp_file) { |
rtp_source_.reset(test::RtpFileSource::Create(rtp_file)); |
} |
@@ -354,7 +353,9 @@ void NetEqDecodingTest::Process() { |
} |
// Get audio from NetEq. |
- ASSERT_EQ(0, neteq_->GetAudio(&out_frame_)); |
+ bool muted; |
+ ASSERT_EQ(0, neteq_->GetAudio(&out_frame_, &muted)); |
+ ASSERT_FALSE(muted); |
ASSERT_TRUE((out_frame_.samples_per_channel_ == kBlockSize8kHz) || |
(out_frame_.samples_per_channel_ == kBlockSize16kHz) || |
(out_frame_.samples_per_channel_ == kBlockSize32kHz) || |
@@ -545,7 +546,8 @@ TEST_F(NetEqDecodingTestFaxMode, TestFrameWaitingTimeStatistics) { |
} |
// Pull out all data. |
for (size_t i = 0; i < num_frames; ++i) { |
- ASSERT_EQ(0, neteq_->GetAudio(&out_frame_)); |
+ bool muted; |
+ ASSERT_EQ(0, neteq_->GetAudio(&out_frame_, &muted)); |
ASSERT_EQ(kBlockSize16kHz, out_frame_.samples_per_channel_); |
} |
@@ -586,7 +588,8 @@ TEST_F(NetEqDecodingTest, TestAverageInterArrivalTimeNegative) { |
} |
// Pull out data once. |
- ASSERT_EQ(0, neteq_->GetAudio(&out_frame_)); |
+ bool muted; |
+ ASSERT_EQ(0, neteq_->GetAudio(&out_frame_, &muted)); |
ASSERT_EQ(kBlockSize16kHz, out_frame_.samples_per_channel_); |
} |
@@ -613,7 +616,8 @@ TEST_F(NetEqDecodingTest, TestAverageInterArrivalTimePositive) { |
} |
// Pull out data once. |
- ASSERT_EQ(0, neteq_->GetAudio(&out_frame_)); |
+ bool muted; |
+ ASSERT_EQ(0, neteq_->GetAudio(&out_frame_, &muted)); |
ASSERT_EQ(kBlockSize16kHz, out_frame_.samples_per_channel_); |
} |
@@ -634,6 +638,7 @@ void NetEqDecodingTest::LongCngWithClockDrift(double drift_factor, |
const size_t kPayloadBytes = kSamples * 2; |
double next_input_time_ms = 0.0; |
double t_ms; |
+ bool muted; |
// Insert speech for 5 seconds. |
const int kSpeechDurationMs = 5000; |
@@ -650,7 +655,7 @@ void NetEqDecodingTest::LongCngWithClockDrift(double drift_factor, |
next_input_time_ms += static_cast<double>(kFrameSizeMs) * drift_factor; |
} |
// Pull out data once. |
- ASSERT_EQ(0, neteq_->GetAudio(&out_frame_)); |
+ ASSERT_EQ(0, neteq_->GetAudio(&out_frame_, &muted)); |
ASSERT_EQ(kBlockSize16kHz, out_frame_.samples_per_channel_); |
} |
@@ -679,7 +684,7 @@ void NetEqDecodingTest::LongCngWithClockDrift(double drift_factor, |
next_input_time_ms += static_cast<double>(kCngPeriodMs) * drift_factor; |
} |
// Pull out data once. |
- ASSERT_EQ(0, neteq_->GetAudio(&out_frame_)); |
+ ASSERT_EQ(0, neteq_->GetAudio(&out_frame_, &muted)); |
ASSERT_EQ(kBlockSize16kHz, out_frame_.samples_per_channel_); |
} |
@@ -692,7 +697,7 @@ void NetEqDecodingTest::LongCngWithClockDrift(double drift_factor, |
const double loop_end_time = t_ms + network_freeze_ms; |
for (; t_ms < loop_end_time; t_ms += 10) { |
// Pull out data once. |
- ASSERT_EQ(0, neteq_->GetAudio(&out_frame_)); |
+ ASSERT_EQ(0, neteq_->GetAudio(&out_frame_, &muted)); |
ASSERT_EQ(kBlockSize16kHz, out_frame_.samples_per_channel_); |
EXPECT_EQ(AudioFrame::kCNG, out_frame_.speech_type_); |
} |
@@ -704,7 +709,7 @@ void NetEqDecodingTest::LongCngWithClockDrift(double drift_factor, |
if (pull_once && next_input_time_ms >= pull_time_ms) { |
pull_once = false; |
// Pull out data once. |
- ASSERT_EQ(0, neteq_->GetAudio(&out_frame_)); |
+ ASSERT_EQ(0, neteq_->GetAudio(&out_frame_, &muted)); |
ASSERT_EQ(kBlockSize16kHz, out_frame_.samples_per_channel_); |
EXPECT_EQ(AudioFrame::kCNG, out_frame_.speech_type_); |
t_ms += 10; |
@@ -738,7 +743,7 @@ void NetEqDecodingTest::LongCngWithClockDrift(double drift_factor, |
next_input_time_ms += kFrameSizeMs * drift_factor; |
} |
// Pull out data once. |
- ASSERT_EQ(0, neteq_->GetAudio(&out_frame_)); |
+ ASSERT_EQ(0, neteq_->GetAudio(&out_frame_, &muted)); |
ASSERT_EQ(kBlockSize16kHz, out_frame_.samples_per_channel_); |
// Increase clock. |
t_ms += 10; |
@@ -866,7 +871,9 @@ TEST_F(NetEqDecodingTest, MAYBE_DecoderError) { |
for (size_t i = 0; i < AudioFrame::kMaxDataSizeSamples; ++i) { |
out_frame_.data_[i] = 1; |
} |
- EXPECT_EQ(NetEq::kFail, neteq_->GetAudio(&out_frame_)); |
+ bool muted; |
+ EXPECT_EQ(NetEq::kFail, neteq_->GetAudio(&out_frame_, &muted)); |
+ ASSERT_FALSE(muted); |
// Verify that there is a decoder error to check. |
EXPECT_EQ(NetEq::kDecoderErrorCode, neteq_->LastError()); |
@@ -903,7 +910,9 @@ TEST_F(NetEqDecodingTest, GetAudioBeforeInsertPacket) { |
for (size_t i = 0; i < AudioFrame::kMaxDataSizeSamples; ++i) { |
out_frame_.data_[i] = 1; |
} |
- EXPECT_EQ(0, neteq_->GetAudio(&out_frame_)); |
+ bool muted; |
+ EXPECT_EQ(0, neteq_->GetAudio(&out_frame_, &muted)); |
+ ASSERT_FALSE(muted); |
// Verify that the first block of samples is set to 0. |
static const int kExpectedOutputLength = |
kInitSampleRateHz / 100; // 10 ms at initial sample rate. |
@@ -955,6 +964,7 @@ class NetEqBgnTest : public NetEqDecodingTest { |
rtp_info.header.payloadType = payload_type; |
uint32_t receive_timestamp = 0; |
+ bool muted; |
for (int n = 0; n < 10; ++n) { // Insert few packets and get audio. |
auto block = input.GetNextBlock(); |
ASSERT_EQ(expected_samples_per_channel, block.size()); |
@@ -966,7 +976,7 @@ class NetEqBgnTest : public NetEqDecodingTest { |
payload, enc_len_bytes), |
receive_timestamp)); |
output.Reset(); |
- ASSERT_EQ(0, neteq_->GetAudio(&output)); |
+ ASSERT_EQ(0, neteq_->GetAudio(&output, &muted)); |
ASSERT_EQ(1u, output.num_channels_); |
ASSERT_EQ(expected_samples_per_channel, output.samples_per_channel_); |
ASSERT_EQ(AudioFrame::kNormalSpeech, output.speech_type_); |
@@ -982,7 +992,7 @@ class NetEqBgnTest : public NetEqDecodingTest { |
// Get audio without inserting packets, expecting PLC and PLC-to-CNG. Pull |
// one frame without checking speech-type. This is the first frame pulled |
// without inserting any packet, and might not be labeled as PLC. |
- ASSERT_EQ(0, neteq_->GetAudio(&output)); |
+ ASSERT_EQ(0, neteq_->GetAudio(&output, &muted)); |
ASSERT_EQ(1u, output.num_channels_); |
ASSERT_EQ(expected_samples_per_channel, output.samples_per_channel_); |
@@ -997,7 +1007,8 @@ class NetEqBgnTest : public NetEqDecodingTest { |
for (int n = 0; n < kFadingThreshold + kNumPlcToCngTestFrames; ++n) { |
output.Reset(); |
memset(output.data_, 1, sizeof(output.data_)); // Set to non-zero. |
- ASSERT_EQ(0, neteq_->GetAudio(&output)); |
+ ASSERT_EQ(0, neteq_->GetAudio(&output, &muted)); |
+ ASSERT_FALSE(muted); |
ASSERT_EQ(1u, output.num_channels_); |
ASSERT_EQ(expected_samples_per_channel, output.samples_per_channel_); |
if (output.speech_type_ == AudioFrame::kPLCCNG) { |
@@ -1171,9 +1182,10 @@ TEST_F(NetEqDecodingTest, SyncPacketDecode) { |
// Insert some packets which decode to noise. We are not interested in |
// actual decoded values. |
uint32_t receive_timestamp = 0; |
+ bool muted; |
for (int n = 0; n < 100; ++n) { |
ASSERT_EQ(0, neteq_->InsertPacket(rtp_info, payload, receive_timestamp)); |
- ASSERT_EQ(0, neteq_->GetAudio(&output)); |
+ ASSERT_EQ(0, neteq_->GetAudio(&output, &muted)); |
ASSERT_EQ(kBlockSize16kHz, output.samples_per_channel_); |
ASSERT_EQ(1u, output.num_channels_); |
@@ -1189,7 +1201,8 @@ TEST_F(NetEqDecodingTest, SyncPacketDecode) { |
// Insert sync-packets, the decoded sequence should be all-zero. |
for (int n = 0; n < kNumSyncPackets; ++n) { |
ASSERT_EQ(0, neteq_->InsertSyncPacket(rtp_info, receive_timestamp)); |
- ASSERT_EQ(0, neteq_->GetAudio(&output)); |
+ ASSERT_EQ(0, neteq_->GetAudio(&output, &muted)); |
+ ASSERT_FALSE(muted); |
ASSERT_EQ(kBlockSize16kHz, output.samples_per_channel_); |
ASSERT_EQ(1u, output.num_channels_); |
if (n > algorithmic_frame_delay) { |
@@ -1205,7 +1218,8 @@ TEST_F(NetEqDecodingTest, SyncPacketDecode) { |
// network statistics would show some packet loss. |
for (int n = 0; n <= algorithmic_frame_delay + 10; ++n) { |
ASSERT_EQ(0, neteq_->InsertPacket(rtp_info, payload, receive_timestamp)); |
- ASSERT_EQ(0, neteq_->GetAudio(&output)); |
+ ASSERT_EQ(0, neteq_->GetAudio(&output, &muted)); |
+ ASSERT_FALSE(muted); |
if (n >= algorithmic_frame_delay + 1) { |
// Expect that this frame contain samples from regular RTP. |
EXPECT_TRUE(IsAllNonZero( |
@@ -1241,9 +1255,10 @@ TEST_F(NetEqDecodingTest, SyncPacketBufferSizeAndOverridenByNetworkPackets) { |
// actual decoded values. |
uint32_t receive_timestamp = 0; |
int algorithmic_frame_delay = algorithmic_delay_ms_ / 10 + 1; |
+ bool muted; |
for (int n = 0; n < algorithmic_frame_delay; ++n) { |
ASSERT_EQ(0, neteq_->InsertPacket(rtp_info, payload, receive_timestamp)); |
- ASSERT_EQ(0, neteq_->GetAudio(&output)); |
+ ASSERT_EQ(0, neteq_->GetAudio(&output, &muted)); |
ASSERT_EQ(kBlockSize16kHz, output.samples_per_channel_); |
ASSERT_EQ(1u, output.num_channels_); |
rtp_info.header.sequenceNumber++; |
@@ -1280,7 +1295,8 @@ TEST_F(NetEqDecodingTest, SyncPacketBufferSizeAndOverridenByNetworkPackets) { |
// Decode. |
for (int n = 0; n < kNumSyncPackets; ++n) { |
- ASSERT_EQ(0, neteq_->GetAudio(&output)); |
+ ASSERT_EQ(0, neteq_->GetAudio(&output, &muted)); |
+ ASSERT_FALSE(muted); |
ASSERT_EQ(kBlockSize16kHz, output.samples_per_channel_); |
ASSERT_EQ(1u, output.num_channels_); |
EXPECT_TRUE(IsAllNonZero( |
@@ -1347,7 +1363,8 @@ void NetEqDecodingTest::WrapTest(uint16_t start_seq_no, |
} |
// Pull out data once. |
AudioFrame output; |
- ASSERT_EQ(0, neteq_->GetAudio(&output)); |
+ bool muted; |
+ ASSERT_EQ(0, neteq_->GetAudio(&output, &muted)); |
ASSERT_EQ(kBlockSize16kHz, output.samples_per_channel_); |
ASSERT_EQ(1u, output.num_channels_); |
@@ -1403,6 +1420,7 @@ void NetEqDecodingTest::DuplicateCng() { |
// correct. |
uint8_t payload[kPayloadBytes] = {0}; |
WebRtcRTPHeader rtp_info; |
+ bool muted; |
for (int i = 0; i < 3; ++i) { |
PopulateRtpInfo(seq_no, timestamp, &rtp_info); |
ASSERT_EQ(0, neteq_->InsertPacket(rtp_info, payload, 0)); |
@@ -1410,7 +1428,7 @@ void NetEqDecodingTest::DuplicateCng() { |
timestamp += kSamples; |
// Pull audio once. |
- ASSERT_EQ(0, neteq_->GetAudio(&out_frame_)); |
+ ASSERT_EQ(0, neteq_->GetAudio(&out_frame_, &muted)); |
ASSERT_EQ(kBlockSize16kHz, out_frame_.samples_per_channel_); |
} |
// Verify speech output. |
@@ -1427,7 +1445,7 @@ void NetEqDecodingTest::DuplicateCng() { |
rtp_info, rtc::ArrayView<const uint8_t>(payload, payload_len), 0)); |
// Pull audio once and make sure CNG is played. |
- ASSERT_EQ(0, neteq_->GetAudio(&out_frame_)); |
+ ASSERT_EQ(0, neteq_->GetAudio(&out_frame_, &muted)); |
ASSERT_EQ(kBlockSize16kHz, out_frame_.samples_per_channel_); |
EXPECT_EQ(AudioFrame::kCNG, out_frame_.speech_type_); |
EXPECT_FALSE(PlayoutTimestamp()); // Returns empty value during CNG. |
@@ -1443,7 +1461,7 @@ void NetEqDecodingTest::DuplicateCng() { |
// Pull audio until we have played |kCngPeriodMs| of CNG. Start at 10 ms since |
// we have already pulled out CNG once. |
for (int cng_time_ms = 10; cng_time_ms < kCngPeriodMs; cng_time_ms += 10) { |
- ASSERT_EQ(0, neteq_->GetAudio(&out_frame_)); |
+ ASSERT_EQ(0, neteq_->GetAudio(&out_frame_, &muted)); |
ASSERT_EQ(kBlockSize16kHz, out_frame_.samples_per_channel_); |
EXPECT_EQ(AudioFrame::kCNG, out_frame_.speech_type_); |
EXPECT_FALSE(PlayoutTimestamp()); // Returns empty value during CNG. |
@@ -1458,7 +1476,7 @@ void NetEqDecodingTest::DuplicateCng() { |
ASSERT_EQ(0, neteq_->InsertPacket(rtp_info, payload, 0)); |
// Pull audio once and verify that the output is speech again. |
- ASSERT_EQ(0, neteq_->GetAudio(&out_frame_)); |
+ ASSERT_EQ(0, neteq_->GetAudio(&out_frame_, &muted)); |
ASSERT_EQ(kBlockSize16kHz, out_frame_.samples_per_channel_); |
EXPECT_EQ(AudioFrame::kNormalSpeech, out_frame_.speech_type_); |
rtc::Optional<uint32_t> playout_timestamp = PlayoutTimestamp(); |
@@ -1496,7 +1514,8 @@ TEST_F(NetEqDecodingTest, CngFirst) { |
timestamp += kCngPeriodSamples; |
// Pull audio once and make sure CNG is played. |
- ASSERT_EQ(0, neteq_->GetAudio(&out_frame_)); |
+ bool muted; |
+ ASSERT_EQ(0, neteq_->GetAudio(&out_frame_, &muted)); |
ASSERT_EQ(kBlockSize16kHz, out_frame_.samples_per_channel_); |
EXPECT_EQ(AudioFrame::kCNG, out_frame_.speech_type_); |
@@ -1508,10 +1527,252 @@ TEST_F(NetEqDecodingTest, CngFirst) { |
timestamp += kSamples; |
// Pull audio once. |
- ASSERT_EQ(0, neteq_->GetAudio(&out_frame_)); |
+ ASSERT_EQ(0, neteq_->GetAudio(&out_frame_, &muted)); |
ASSERT_EQ(kBlockSize16kHz, out_frame_.samples_per_channel_); |
} |
// Verify speech output. |
EXPECT_EQ(AudioFrame::kNormalSpeech, out_frame_.speech_type_); |
} |
+ |
+class NetEqDecodingTestWithMutedState : public NetEqDecodingTest { |
+ public: |
+ NetEqDecodingTestWithMutedState() : NetEqDecodingTest() { |
+ config_.enable_muted_state = true; |
+ } |
+ |
+ protected: |
+ static constexpr size_t kSamples = 10 * 16; |
+ static constexpr size_t kPayloadBytes = kSamples * 2; |
+ |
+ void InsertPacket(uint32_t rtp_timestamp) { |
+ uint8_t payload[kPayloadBytes] = {0}; |
+ WebRtcRTPHeader rtp_info; |
+ PopulateRtpInfo(0, rtp_timestamp, &rtp_info); |
+ EXPECT_EQ(0, neteq_->InsertPacket(rtp_info, payload, 0)); |
+ } |
+ |
+ bool GetAudioReturnMuted() { |
+ bool muted; |
+ EXPECT_EQ(0, neteq_->GetAudio(&out_frame_, &muted)); |
+ return muted; |
+ } |
+ |
+ void GetAudioUntilMuted() { |
+ while (!GetAudioReturnMuted()) { |
+ ASSERT_LT(counter_++, 1000) << "Test timed out"; |
+ } |
+ } |
+ |
+ void GetAudioUntilNormal() { |
+ bool muted = false; |
+ while (out_frame_.speech_type_ != AudioFrame::kNormalSpeech) { |
+ EXPECT_EQ(0, neteq_->GetAudio(&out_frame_, &muted)); |
+ ASSERT_LT(counter_++, 1000) << "Test timed out"; |
+ } |
+ EXPECT_FALSE(muted); |
+ } |
+ |
+ int counter_ = 0; |
+}; |
+ |
+// Verifies that NetEq goes in and out of muted state as expected. |
+TEST_F(NetEqDecodingTestWithMutedState, MutedState) { |
+ // Insert one speech packet. |
+ InsertPacket(0); |
+ // Pull out audio once and expect it not to be muted. |
+ EXPECT_FALSE(GetAudioReturnMuted()); |
+ // Pull data until faded out. |
+ GetAudioUntilMuted(); |
+ |
+ // Verify that output audio is not written during muted mode. Other parameters |
+ // should be correct, though. |
+ AudioFrame new_frame; |
+ for (auto& d : new_frame.data_) { |
+ d = 17; |
+ } |
+ bool muted; |
+ EXPECT_EQ(0, neteq_->GetAudio(&new_frame, &muted)); |
+ EXPECT_TRUE(muted); |
+ for (auto d : new_frame.data_) { |
+ EXPECT_EQ(17, d); |
+ } |
+ EXPECT_EQ(out_frame_.timestamp_ + out_frame_.samples_per_channel_, |
+ new_frame.timestamp_); |
+ EXPECT_EQ(out_frame_.samples_per_channel_, new_frame.samples_per_channel_); |
+ EXPECT_EQ(out_frame_.sample_rate_hz_, new_frame.sample_rate_hz_); |
+ EXPECT_EQ(out_frame_.num_channels_, new_frame.num_channels_); |
+ EXPECT_EQ(out_frame_.speech_type_, new_frame.speech_type_); |
+ EXPECT_EQ(out_frame_.vad_activity_, new_frame.vad_activity_); |
+ |
+ // Insert new data. Timestamp is corrected for the time elapsed since the last |
+ // packet. Verify that normal operation resumes. |
+ InsertPacket(kSamples * counter_); |
+ GetAudioUntilNormal(); |
+} |
+ |
+// Verifies that NetEq goes out of muted state when given a delayed packet. |
+TEST_F(NetEqDecodingTestWithMutedState, MutedStateDelayedPacket) { |
+ // Insert one speech packet. |
+ InsertPacket(0); |
+ // Pull out audio once and expect it not to be muted. |
+ EXPECT_FALSE(GetAudioReturnMuted()); |
+ // Pull data until faded out. |
+ GetAudioUntilMuted(); |
+ // Insert new data. Timestamp is only corrected for the half of the time |
+ // elapsed since the last packet. That is, the new packet is delayed. Verify |
+ // that normal operation resumes. |
+ InsertPacket(kSamples * counter_ / 2); |
+ GetAudioUntilNormal(); |
+} |
+ |
+// Verifies that NetEq goes out of muted state when given a future packet. |
+TEST_F(NetEqDecodingTestWithMutedState, MutedStateFuturePacket) { |
+ // Insert one speech packet. |
+ InsertPacket(0); |
+ // Pull out audio once and expect it not to be muted. |
+ EXPECT_FALSE(GetAudioReturnMuted()); |
+ // Pull data until faded out. |
+ GetAudioUntilMuted(); |
+ // Insert new data. Timestamp is over-corrected for the time elapsed since the |
+ // last packet. That is, the new packet is too early. Verify that normal |
+ // operation resumes. |
+ InsertPacket(kSamples * counter_ * 2); |
+ GetAudioUntilNormal(); |
+} |
+ |
+// Verifies that NetEq goes out of muted state when given an old packet. |
+TEST_F(NetEqDecodingTestWithMutedState, MutedStateOldPacket) { |
+ // Insert one speech packet. |
+ InsertPacket(0); |
+ // Pull out audio once and expect it not to be muted. |
+ EXPECT_FALSE(GetAudioReturnMuted()); |
+ // Pull data until faded out. |
+ GetAudioUntilMuted(); |
+ |
+ EXPECT_NE(AudioFrame::kNormalSpeech, out_frame_.speech_type_); |
+ // Insert packet which is older than the first packet. |
+ InsertPacket(kSamples * (counter_ - 1000)); |
+ EXPECT_FALSE(GetAudioReturnMuted()); |
+ EXPECT_EQ(AudioFrame::kNormalSpeech, out_frame_.speech_type_); |
+} |
+ |
+class NetEqDecodingTestTwoInstances : public NetEqDecodingTest { |
+ public: |
+ NetEqDecodingTestTwoInstances() : NetEqDecodingTest() {} |
+ |
+ void SetUp() override { |
+ NetEqDecodingTest::SetUp(); |
+ config2_ = config_; |
+ } |
+ |
+ void CreateSecondInstance() { |
+ neteq2_.reset(NetEq::Create(config2_)); |
+ ASSERT_TRUE(neteq2_); |
+ LoadDecoders(neteq2_.get()); |
+ } |
+ |
+ protected: |
+ std::unique_ptr<NetEq> neteq2_; |
+ NetEq::Config config2_; |
+}; |
+ |
+namespace { |
+::testing::AssertionResult AudioFramesEqualExceptData(const AudioFrame& a, |
+ const AudioFrame& b) { |
+ if (a.timestamp_ != b.timestamp_) |
+ return ::testing::AssertionFailure() << "timestamp_ diff (" << a.timestamp_ |
+ << " != " << b.timestamp_ << ")"; |
+ if (a.sample_rate_hz_ != b.sample_rate_hz_) |
+ return ::testing::AssertionFailure() << "sample_rate_hz_ diff (" |
+ << a.sample_rate_hz_ |
+ << " != " << b.sample_rate_hz_ << ")"; |
+ if (a.samples_per_channel_ != b.samples_per_channel_) |
+ return ::testing::AssertionFailure() |
+ << "samples_per_channel_ diff (" << a.samples_per_channel_ |
+ << " != " << b.samples_per_channel_ << ")"; |
+ if (a.num_channels_ != b.num_channels_) |
+ return ::testing::AssertionFailure() << "num_channels_ diff (" |
+ << a.num_channels_ |
+ << " != " << b.num_channels_ << ")"; |
+ if (a.speech_type_ != b.speech_type_) |
+ return ::testing::AssertionFailure() << "speech_type_ diff (" |
+ << a.speech_type_ |
+ << " != " << b.speech_type_ << ")"; |
+ if (a.vad_activity_ != b.vad_activity_) |
+ return ::testing::AssertionFailure() << "vad_activity_ diff (" |
+ << a.vad_activity_ |
+ << " != " << b.vad_activity_ << ")"; |
+ return ::testing::AssertionSuccess(); |
+} |
+ |
+::testing::AssertionResult AudioFramesEqual(const AudioFrame& a, |
+ const AudioFrame& b) { |
+ ::testing::AssertionResult res = AudioFramesEqualExceptData(a, b); |
+ if (!res) |
+ return res; |
+ if (memcmp( |
+ a.data_, b.data_, |
+ a.samples_per_channel_ * a.num_channels_ * sizeof(a.data_[0])) != 0) { |
+ return ::testing::AssertionFailure() << "data_ diff"; |
+ } |
+ return ::testing::AssertionSuccess(); |
+} |
+ |
+} // namespace |
+ |
+TEST_F(NetEqDecodingTestTwoInstances, CompareMutedStateOnOff) { |
+ ASSERT_FALSE(config_.enable_muted_state); |
+ config2_.enable_muted_state = true; |
+ CreateSecondInstance(); |
+ |
+ // Insert one speech packet into both NetEqs. |
+ const size_t kSamples = 10 * 16; |
+ const size_t kPayloadBytes = kSamples * 2; |
+ uint8_t payload[kPayloadBytes] = {0}; |
+ WebRtcRTPHeader rtp_info; |
+ PopulateRtpInfo(0, 0, &rtp_info); |
+ EXPECT_EQ(0, neteq_->InsertPacket(rtp_info, payload, 0)); |
+ EXPECT_EQ(0, neteq2_->InsertPacket(rtp_info, payload, 0)); |
+ |
+ AudioFrame out_frame1, out_frame2; |
+ bool muted; |
+ for (int i = 0; i < 1000; ++i) { |
+ std::ostringstream ss; |
+ ss << "i = " << i; |
+ SCOPED_TRACE(ss.str()); // Print out the loop iterator on failure. |
+ EXPECT_EQ(0, neteq_->GetAudio(&out_frame1, &muted)); |
+ EXPECT_FALSE(muted); |
+ EXPECT_EQ(0, neteq2_->GetAudio(&out_frame2, &muted)); |
+ if (muted) { |
+ EXPECT_TRUE(AudioFramesEqualExceptData(out_frame1, out_frame2)); |
+ } else { |
+ EXPECT_TRUE(AudioFramesEqual(out_frame1, out_frame2)); |
+ } |
+ } |
+ EXPECT_TRUE(muted); |
+ |
+ // Insert new data. Timestamp is corrected for the time elapsed since the last |
+ // packet. |
+ PopulateRtpInfo(0, kSamples * 1000, &rtp_info); |
+ EXPECT_EQ(0, neteq_->InsertPacket(rtp_info, payload, 0)); |
+ EXPECT_EQ(0, neteq2_->InsertPacket(rtp_info, payload, 0)); |
+ |
+ int counter = 0; |
+ while (out_frame1.speech_type_ != AudioFrame::kNormalSpeech) { |
+ ASSERT_LT(counter++, 1000) << "Test timed out"; |
+ std::ostringstream ss; |
+ ss << "counter = " << counter; |
+ SCOPED_TRACE(ss.str()); // Print out the loop iterator on failure. |
+ EXPECT_EQ(0, neteq_->GetAudio(&out_frame1, &muted)); |
+ EXPECT_FALSE(muted); |
+ EXPECT_EQ(0, neteq2_->GetAudio(&out_frame2, &muted)); |
+ if (muted) { |
+ EXPECT_TRUE(AudioFramesEqualExceptData(out_frame1, out_frame2)); |
+ } else { |
+ EXPECT_TRUE(AudioFramesEqual(out_frame1, out_frame2)); |
+ } |
+ } |
+ EXPECT_FALSE(muted); |
+} |
+ |
} // namespace webrtc |