Index: webrtc/modules/audio_coding/neteq/neteq_impl_unittest.cc |
diff --git a/webrtc/modules/audio_coding/neteq/neteq_impl_unittest.cc b/webrtc/modules/audio_coding/neteq/neteq_impl_unittest.cc |
index 77622bc4573a75174d764362b807d25f1840c213..8b47adb9c549376b47abcf229ac70db17e33b524 100644 |
--- a/webrtc/modules/audio_coding/neteq/neteq_impl_unittest.cc |
+++ b/webrtc/modules/audio_coding/neteq/neteq_impl_unittest.cc |
@@ -763,7 +763,7 @@ TEST_F(NetEqImplTest, CodecInternalCng) { |
TEST_F(NetEqImplTest, UnsupportedDecoder) { |
UseNoMocks(); |
CreateInstance(); |
- static const size_t kNetEqMaxFrameSize = 2880; // 60 ms @ 48 kHz. |
+ static const size_t kNetEqMaxFrameSize = 5760; // 120 ms @ 48 kHz. |
static const size_t kChannels = 2; |
const uint8_t kPayloadType = 17; // Just an arbitrary number. |
@@ -773,7 +773,7 @@ TEST_F(NetEqImplTest, UnsupportedDecoder) { |
const size_t kPayloadLengthSamples = |
static_cast<size_t>(10 * kSampleRateHz / 1000); // 10 ms. |
const size_t kPayloadLengthBytes = 1; |
- uint8_t payload[kPayloadLengthBytes]= {0}; |
+ uint8_t payload[kPayloadLengthBytes] = {0}; |
int16_t dummy_output[kPayloadLengthSamples * kChannels] = {0}; |
WebRtcRTPHeader rtp_header; |
rtp_header.header.payloadType = kPayloadType; |
@@ -1189,4 +1189,214 @@ TEST_F(NetEqImplTest, TickTimerIncrement) { |
EXPECT_EQ(1u, tick_timer_->ticks()); |
} |
+class Decoder120ms : public AudioDecoder { |
+ public: |
+ Decoder120ms(SpeechType speech_type) |
+ : next_value_(1), |
+ speech_type_(speech_type) {} |
+ |
+ int DecodeInternal(const uint8_t* encoded, |
+ size_t encoded_len, |
+ int sample_rate_hz, |
+ int16_t* decoded, |
+ SpeechType* speech_type) override { |
+ size_t decoded_len = |
+ rtc::CheckedDivExact(sample_rate_hz, 1000) * 120 * Channels(); |
+ for (size_t i = 0; i < decoded_len; ++i) { |
+ decoded[i] = next_value_++; |
+ } |
+ *speech_type = speech_type_; |
+ return decoded_len; |
+ } |
+ |
+ void Reset() override { next_value_ = 1; } |
+ size_t Channels() const override { return 2; } |
+ |
+ private: |
+ int16_t next_value_; |
+ SpeechType speech_type_; |
+}; |
+ |
+class NetEqImplTest120ms : public NetEqImplTest { |
+ protected: |
+ NetEqImplTest120ms() : NetEqImplTest() {} |
+ virtual ~NetEqImplTest120ms() {} |
+ |
+ void CreateInstanceNoMocks() { |
+ UseNoMocks(); |
+ CreateInstance(); |
+ } |
+ |
+ void CreateInstanceWithDelayManagerMock() { |
+ UseNoMocks(); |
+ use_mock_delay_manager_ = true; |
+ CreateInstance(); |
+ } |
+ |
+ uint32_t timestamp_diff_between_packets() const { |
+ return rtc::CheckedDivExact(kSamplingFreq_, 1000u) * 120; |
+ } |
+ |
+ uint32_t first_timestamp() const { return 10u; } |
+ |
+ void GetFirstPacket() { |
+ for (int i = 0; i < 12; i++) { |
+ EXPECT_EQ(NetEq::kOK, neteq_->GetAudio(&output_)); |
+ } |
+ } |
+ |
+ void InsertPacket(uint32_t timestamp) { |
+ WebRtcRTPHeader rtp_header; |
+ rtp_header.header.payloadType = kPayloadType; |
+ rtp_header.header.sequenceNumber = sequence_number_; |
+ rtp_header.header.timestamp = timestamp; |
+ rtp_header.header.ssrc = 15; |
+ const size_t kPayloadLengthBytes = 1; // This can be arbitrary. |
+ uint8_t payload[kPayloadLengthBytes] = {0}; |
+ EXPECT_EQ(NetEq::kOK, neteq_->InsertPacket(rtp_header, payload, 10)); |
+ sequence_number_++; |
+ } |
+ |
+ void Register120msCodec(AudioDecoder::SpeechType speech_type) { |
+ decoder_.reset(new Decoder120ms(speech_type)); |
+ ASSERT_EQ(2u, decoder_->Channels()); |
+ EXPECT_EQ(NetEq::kOK, neteq_->RegisterExternalDecoder( |
+ decoder_.get(), NetEqDecoder::kDecoderOpus_2ch, |
+ "120ms codec", kPayloadType, kSamplingFreq_)); |
+ } |
+ |
+ std::unique_ptr<Decoder120ms> decoder_; |
+ AudioFrame output_; |
+ const uint32_t kPayloadType = 17; |
+ const uint32_t kSamplingFreq_ = 48000; |
+ uint16_t sequence_number_ = 1; |
+}; |
+ |
+TEST_F(NetEqImplTest120ms, AudioRepetition) { |
+ config_.playout_mode = kPlayoutFax; |
+ CreateInstanceNoMocks(); |
+ Register120msCodec(AudioDecoder::kSpeech); |
+ |
+ InsertPacket(first_timestamp()); |
+ GetFirstPacket(); |
+ |
+ EXPECT_EQ(NetEq::kOK, neteq_->GetAudio(&output_)); |
+ EXPECT_EQ(kAudioRepetition, neteq_->last_operation_for_test()); |
+} |
+ |
+TEST_F(NetEqImplTest120ms, AlternativePlc) { |
+ config_.playout_mode = kPlayoutOff; |
+ CreateInstanceNoMocks(); |
+ Register120msCodec(AudioDecoder::kSpeech); |
+ |
+ InsertPacket(first_timestamp()); |
+ GetFirstPacket(); |
+ |
+ EXPECT_EQ(NetEq::kOK, neteq_->GetAudio(&output_)); |
+ EXPECT_EQ(kAlternativePlc, neteq_->last_operation_for_test()); |
+} |
+ |
+TEST_F(NetEqImplTest120ms, CodecInternalCng) { |
+ CreateInstanceNoMocks(); |
+ Register120msCodec(AudioDecoder::kComfortNoise); |
+ |
+ InsertPacket(first_timestamp()); |
+ GetFirstPacket(); |
+ |
+ EXPECT_EQ(NetEq::kOK, neteq_->GetAudio(&output_)); |
+ EXPECT_EQ(kCodecInternalCng, neteq_->last_operation_for_test()); |
+} |
+ |
+TEST_F(NetEqImplTest120ms, Normal) { |
+ CreateInstanceNoMocks(); |
+ Register120msCodec(AudioDecoder::kSpeech); |
+ |
+ InsertPacket(first_timestamp()); |
+ GetFirstPacket(); |
+ |
+ EXPECT_EQ(kNormal, neteq_->last_operation_for_test()); |
+} |
+ |
+TEST_F(NetEqImplTest120ms, Merge) { |
+ CreateInstanceWithDelayManagerMock(); |
+ |
+ Register120msCodec(AudioDecoder::kSpeech); |
+ InsertPacket(first_timestamp()); |
+ |
+ GetFirstPacket(); |
+ EXPECT_EQ(NetEq::kOK, neteq_->GetAudio(&output_)); |
+ |
+ InsertPacket(first_timestamp() + 2 * timestamp_diff_between_packets()); |
+ |
+ // Delay manager reports a target level which should cause a Merge. |
+ EXPECT_CALL(*mock_delay_manager_, TargetLevel()).WillOnce(Return(-10)); |
+ |
+ EXPECT_EQ(NetEq::kOK, neteq_->GetAudio(&output_)); |
+ EXPECT_EQ(kMerge, neteq_->last_operation_for_test()); |
+} |
+ |
+TEST_F(NetEqImplTest120ms, Expand) { |
+ CreateInstanceNoMocks(); |
+ Register120msCodec(AudioDecoder::kSpeech); |
+ |
+ InsertPacket(first_timestamp()); |
+ GetFirstPacket(); |
+ |
+ EXPECT_EQ(NetEq::kOK, neteq_->GetAudio(&output_)); |
+ EXPECT_EQ(kExpand, neteq_->last_operation_for_test()); |
+} |
+ |
+TEST_F(NetEqImplTest120ms, FastAccelerate) { |
+ CreateInstanceWithDelayManagerMock(); |
+ Register120msCodec(AudioDecoder::kSpeech); |
+ |
+ InsertPacket(first_timestamp()); |
+ GetFirstPacket(); |
+ InsertPacket(first_timestamp() + timestamp_diff_between_packets()); |
+ |
+ // Delay manager report buffer limit which should cause a FastAccelerate. |
+ EXPECT_CALL(*mock_delay_manager_, BufferLimits(_, _)) |
+ .Times(1) |
+ .WillOnce(DoAll(SetArgPointee<0>(0), SetArgPointee<1>(0))); |
+ |
+ EXPECT_EQ(NetEq::kOK, neteq_->GetAudio(&output_)); |
+ EXPECT_EQ(kFastAccelerate, neteq_->last_operation_for_test()); |
+} |
+ |
+TEST_F(NetEqImplTest120ms, PreemptiveExpand) { |
+ CreateInstanceWithDelayManagerMock(); |
+ Register120msCodec(AudioDecoder::kSpeech); |
+ |
+ InsertPacket(first_timestamp()); |
+ GetFirstPacket(); |
+ |
+ InsertPacket(first_timestamp() + timestamp_diff_between_packets()); |
+ |
+ // Delay manager report buffer limit which should cause a PreemptiveExpand. |
+ EXPECT_CALL(*mock_delay_manager_, BufferLimits(_, _)) |
+ .Times(1) |
+ .WillOnce(DoAll(SetArgPointee<0>(100), SetArgPointee<1>(100))); |
+ |
+ EXPECT_EQ(NetEq::kOK, neteq_->GetAudio(&output_)); |
+ EXPECT_EQ(kPreemptiveExpand, neteq_->last_operation_for_test()); |
+} |
+ |
+TEST_F(NetEqImplTest120ms, Accelerate) { |
+ CreateInstanceWithDelayManagerMock(); |
+ Register120msCodec(AudioDecoder::kSpeech); |
+ |
+ InsertPacket(first_timestamp()); |
+ GetFirstPacket(); |
+ |
+ InsertPacket(first_timestamp() + timestamp_diff_between_packets()); |
+ |
+ // Delay manager report buffer limit which should cause a Accelerate. |
+ EXPECT_CALL(*mock_delay_manager_, BufferLimits(_, _)) |
+ .Times(1) |
+ .WillOnce(DoAll(SetArgPointee<0>(1), SetArgPointee<1>(2))); |
+ |
+ EXPECT_EQ(NetEq::kOK, neteq_->GetAudio(&output_)); |
+ EXPECT_EQ(kAccelerate, neteq_->last_operation_for_test()); |
+} |
+ |
}// namespace webrtc |