diff --git a/webrtc/modules/audio_coding/neteq/neteq_impl.cc b/webrtc/modules/audio_coding/neteq/neteq_impl.cc index c9c1f86926..00f854b8db 100644 --- a/webrtc/modules/audio_coding/neteq/neteq_impl.cc +++ b/webrtc/modules/audio_coding/neteq/neteq_impl.cc @@ -612,7 +612,8 @@ int NetEqImpl::InsertPacketInternal(const WebRtcRTPHeader& rtp_header, } // Insert packets in buffer. - size_t temp_bufsize = packet_buffer_->NumPacketsInBuffer(); + const size_t buffer_length_before_insert = + packet_buffer_->NumPacketsInBuffer(); ret = packet_buffer_->InsertPacketList( &packet_list, *decoder_database_, @@ -668,14 +669,18 @@ int NetEqImpl::InsertPacketInternal(const WebRtcRTPHeader& rtp_header, delay_manager_->LastDecoderType(dec_info->codec_type); if (delay_manager_->last_pack_cng_or_dtmf() == 0) { // Calculate the total speech length carried in each packet. - temp_bufsize = packet_buffer_->NumPacketsInBuffer() - temp_bufsize; - temp_bufsize *= decoder_frame_length_; + const size_t buffer_length_after_insert = + packet_buffer_->NumPacketsInBuffer(); - if ((temp_bufsize > 0) && - (temp_bufsize != decision_logic_->packet_length_samples())) { - decision_logic_->set_packet_length_samples(temp_bufsize); - delay_manager_->SetPacketAudioLength( - static_cast((1000 * temp_bufsize) / fs_hz_)); + if (buffer_length_after_insert > buffer_length_before_insert) { + const size_t packet_length_samples = + (buffer_length_after_insert - buffer_length_before_insert) * + decoder_frame_length_; + if (packet_length_samples != decision_logic_->packet_length_samples()) { + decision_logic_->set_packet_length_samples(packet_length_samples); + delay_manager_->SetPacketAudioLength( + rtc::checked_cast((1000 * packet_length_samples) / fs_hz_)); + } } // Update statistics. diff --git a/webrtc/modules/audio_coding/neteq/neteq_impl_unittest.cc b/webrtc/modules/audio_coding/neteq/neteq_impl_unittest.cc index ee04a6f255..4f68c66467 100644 --- a/webrtc/modules/audio_coding/neteq/neteq_impl_unittest.cc +++ b/webrtc/modules/audio_coding/neteq/neteq_impl_unittest.cc @@ -13,6 +13,7 @@ #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" +#include "webrtc/base/safe_conversions.h" #include "webrtc/modules/audio_coding/neteq/accelerate.h" #include "webrtc/modules/audio_coding/neteq/expand.h" #include "webrtc/modules/audio_coding/neteq/mock/mock_audio_decoder.h" @@ -902,4 +903,43 @@ TEST_F(NetEqImplTest, UnsupportedDecoder) { EXPECT_EQ(kChannels, num_channels); } +// This test inserts packets until the buffer is flushed. After that, it asks +// NetEq for the network statistics. The purpose of the test is to make sure +// that even though the buffer size increment is negative (which it becomes when +// the packet causing a flush is inserted), the packet length stored in the +// decision logic remains valid. +TEST_F(NetEqImplTest, FloodBufferAndGetNetworkStats) { + UseNoMocks(); + CreateInstance(); + + const size_t kPayloadLengthSamples = 80; + const size_t kPayloadLengthBytes = 2 * kPayloadLengthSamples; // PCM 16-bit. + const uint8_t kPayloadType = 17; // Just an arbitrary number. + const uint32_t kReceiveTime = 17; // Value doesn't matter for this test. + uint8_t payload[kPayloadLengthBytes] = {0}; + WebRtcRTPHeader rtp_header; + rtp_header.header.payloadType = kPayloadType; + rtp_header.header.sequenceNumber = 0x1234; + rtp_header.header.timestamp = 0x12345678; + rtp_header.header.ssrc = 0x87654321; + + EXPECT_EQ(NetEq::kOK, + neteq_->RegisterPayloadType(kDecoderPCM16B, kPayloadType)); + + // Insert packets until the buffer flushes. + for (size_t i = 0; i <= config_.max_packets_in_buffer; ++i) { + EXPECT_EQ(i, packet_buffer_->NumPacketsInBuffer()); + EXPECT_EQ(NetEq::kOK, + neteq_->InsertPacket(rtp_header, payload, kPayloadLengthBytes, + kReceiveTime)); + rtp_header.header.timestamp += + rtc::checked_cast(kPayloadLengthSamples); + ++rtp_header.header.sequenceNumber; + } + EXPECT_EQ(1u, packet_buffer_->NumPacketsInBuffer()); + + // Ask for network statistics. This should not crash. + NetEqNetworkStatistics stats; + EXPECT_EQ(NetEq::kOK, neteq_->NetworkStatistics(&stats)); +} } // namespace webrtc