From 82e5f91a2bdf955aa870142008fbdc9ac12f6acd Mon Sep 17 00:00:00 2001 From: Philipp Hancke Date: Tue, 8 Aug 2023 14:29:22 +0200 Subject: [PATCH] audio: fix handling of RED packets where the primary encoding is too large by falling back to the primary encoding. This can happen with opus stereo packets at the maximum bitrate which results in 1276 encoded bytes. BUG=chromium:1470261 Change-Id: I3fd9bb30773963a519bbb5da44fe71db5dec2bd7 Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/315141 Commit-Queue: Henrik Lundin Commit-Queue: Philipp Hancke Reviewed-by: Henrik Lundin Reviewed-by: Harald Alvestrand Cr-Commit-Position: refs/heads/main@{#40524} --- .../codecs/red/audio_encoder_copy_red.cc | 9 ++++++++- .../red/audio_encoder_copy_red_unittest.cc | 17 +++++++++++++++++ 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/modules/audio_coding/codecs/red/audio_encoder_copy_red.cc b/modules/audio_coding/codecs/red/audio_encoder_copy_red.cc index 724bba52d6..634f14d370 100644 --- a/modules/audio_coding/codecs/red/audio_encoder_copy_red.cc +++ b/modules/audio_coding/codecs/red/audio_encoder_copy_red.cc @@ -104,7 +104,14 @@ AudioEncoder::EncodedInfo AudioEncoderCopyRed::EncodeImpl( RTC_CHECK(info.redundant.empty()) << "Cannot use nested redundant encoders."; RTC_DCHECK_EQ(primary_encoded_.size(), info.encoded_bytes); - if (info.encoded_bytes == 0 || info.encoded_bytes >= kRedMaxPacketSize) { + if (info.encoded_bytes == 0) { + return info; + } + if (info.encoded_bytes >= kRedMaxPacketSize) { + // Fallback to the primary encoding if the encoded size is more than + // what RED can encode as redundancy (1024 bytes). This can happen with + // Opus stereo at the highest bitrate which consumes up to 1276 bytes. + encoded->AppendData(primary_encoded_); return info; } RTC_DCHECK_GT(max_packet_length_, info.encoded_bytes); diff --git a/modules/audio_coding/codecs/red/audio_encoder_copy_red_unittest.cc b/modules/audio_coding/codecs/red/audio_encoder_copy_red_unittest.cc index 8161931a7a..20d85a1d15 100644 --- a/modules/audio_coding/codecs/red/audio_encoder_copy_red_unittest.cc +++ b/modules/audio_coding/codecs/red/audio_encoder_copy_red_unittest.cc @@ -315,6 +315,23 @@ TEST_F(AudioEncoderCopyRedTest, CheckPayloadSizes3) { } } +// Checks that packets encoded larger than REDs 1024 maximum are returned as-is. +TEST_F(AudioEncoderCopyRedTest, VeryLargePacket) { + AudioEncoder::EncodedInfo info; + info.payload_type = 63; + info.encoded_bytes = + 1111; // Must be > 1024 which is the maximum size encodable by RED. + info.encoded_timestamp = timestamp_; + + EXPECT_CALL(*mock_encoder_, EncodeImpl(_, _, _)) + .WillOnce(Invoke(MockAudioEncoder::FakeEncoding(info))); + + Encode(); + ASSERT_EQ(0u, encoded_info_.redundant.size()); + ASSERT_EQ(info.encoded_bytes, encoded_info_.encoded_bytes); + ASSERT_EQ(info.payload_type, encoded_info_.payload_type); +} + // Checks that the correct timestamps are returned. TEST_F(AudioEncoderCopyRedTest, CheckTimestamps) { uint32_t primary_timestamp = timestamp_;