diff --git a/third_party/libwebrtc/README.moz-ff-commit b/third_party/libwebrtc/README.moz-ff-commit index 18b48fc6a04a..cbcdd2f1e969 100644 --- a/third_party/libwebrtc/README.moz-ff-commit +++ b/third_party/libwebrtc/README.moz-ff-commit @@ -33966,3 +33966,6 @@ badfd6347e # MOZ_LIBWEBRTC_SRC=/Users/mfroman/no_tm_backup/elm/.moz-fast-forward/moz-libwebrtc MOZ_LIBWEBRTC_BRANCH=mozpatches bash dom/media/webrtc/third_party_build/fast-forward-libwebrtc.sh # base of lastest vendoring a5d71009ac +# MOZ_LIBWEBRTC_SRC=/Users/mfroman/no_tm_backup/elm/.moz-fast-forward/moz-libwebrtc MOZ_LIBWEBRTC_BRANCH=mozpatches bash dom/media/webrtc/third_party_build/fast-forward-libwebrtc.sh +# base of lastest vendoring +463ce639a6 diff --git a/third_party/libwebrtc/README.mozilla b/third_party/libwebrtc/README.mozilla index 3d1fdf34e29f..4c184b336c0d 100644 --- a/third_party/libwebrtc/README.mozilla +++ b/third_party/libwebrtc/README.mozilla @@ -22670,3 +22670,5 @@ libwebrtc updated from /Users/mfroman/no_tm_backup/elm/.moz-fast-forward/moz-lib libwebrtc updated from /Users/mfroman/no_tm_backup/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2024-12-05T22:18:19.097360+00:00. # ./mach python dom/media/webrtc/third_party_build/vendor-libwebrtc.py --from-local /Users/mfroman/no_tm_backup/elm/.moz-fast-forward/moz-libwebrtc --commit mozpatches libwebrtc libwebrtc updated from /Users/mfroman/no_tm_backup/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2024-12-05T22:19:55.432580+00:00. +# ./mach python dom/media/webrtc/third_party_build/vendor-libwebrtc.py --from-local /Users/mfroman/no_tm_backup/elm/.moz-fast-forward/moz-libwebrtc --commit mozpatches libwebrtc +libwebrtc updated from /Users/mfroman/no_tm_backup/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2024-12-05T22:21:31.486441+00:00. diff --git a/third_party/libwebrtc/modules/audio_coding/BUILD.gn b/third_party/libwebrtc/modules/audio_coding/BUILD.gn index 8a552ed9170a..e547f76cffca 100644 --- a/third_party/libwebrtc/modules/audio_coding/BUILD.gn +++ b/third_party/libwebrtc/modules/audio_coding/BUILD.gn @@ -1505,6 +1505,7 @@ if (rtc_include_tests) { "../../test:test_support", "codecs/opus/test", "codecs/opus/test:test_unittest", + "//testing/gmock", "//testing/gtest", "//third_party/abseil-cpp/absl/flags:flag", "//third_party/abseil-cpp/absl/memory", diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/opus/audio_decoder_opus_unittest.cc b/third_party/libwebrtc/modules/audio_coding/codecs/opus/audio_decoder_opus_unittest.cc index 71f0d38b255a..998b88a10530 100644 --- a/third_party/libwebrtc/modules/audio_coding/codecs/opus/audio_decoder_opus_unittest.cc +++ b/third_party/libwebrtc/modules/audio_coding/codecs/opus/audio_decoder_opus_unittest.cc @@ -28,6 +28,7 @@ #include "rtc_base/checks.h" #include "rtc_base/random.h" #include "test/explicit_key_value_config.h" +#include "test/gmock.h" #include "test/gtest.h" #include "test/testsupport/file_utils.h" @@ -35,6 +36,7 @@ namespace webrtc { namespace { using test::ExplicitKeyValueConfig; +using testing::SizeIs; using DecodeResult = ::webrtc::AudioDecoder::EncodedAudioFrame::DecodeResult; using ParseResult = ::webrtc::AudioDecoder::ParseResult; @@ -158,7 +160,6 @@ void EncodeDecodeNoiseUntilDecoderInDtxMode(AudioEncoderOpusImpl& encoder, std::vector decoded_frame(kEncoderFrameLength * decoder_num_channels); - bool dtx_packet_found = false; for (int i = 0; i < 50; ++i) { generator.GenerateNextFrame(input_frame); rtc::Buffer payload; @@ -170,8 +171,9 @@ void EncodeDecodeNoiseUntilDecoderInDtxMode(AudioEncoderOpusImpl& encoder, continue; } - // Decode `payload`. If not a DTX packet, decoding it may update the - // internal decoder parameters for comfort noise generation. + // Decode `payload`. If it encodes a DTX packet (i.e., 1 byte payload), the + // decoder will switch to DTX mode. Otherwise, it may update the internal + // decoder parameters for comfort noise generation. std::vector parse_results = decoder.ParsePayload(std::move(payload), timestamp++); RTC_CHECK_EQ(parse_results.size(), 1); @@ -179,14 +181,62 @@ void EncodeDecodeNoiseUntilDecoderInDtxMode(AudioEncoderOpusImpl& encoder, parse_results[0].frame->Decode(decoded_frame); RTC_CHECK(decode_results); RTC_CHECK_EQ(decode_results->num_decoded_samples, decoded_frame.size()); - if (parse_results[0].frame->IsDtxPacket()) { - // The decoder is now in DTX mode. - dtx_packet_found = true; + return; + } + } + RTC_CHECK_NOTREACHED(); +} + +// Generates packets by encoding speech frames and decodes them until a non-DTX +// packet is generated and, when that condition is met, returns the decoded +// audio samples. +std::vector EncodeDecodeSpeechUntilOneFrameIsDecoded( + AudioEncoderOpusImpl& encoder, + AudioDecoderOpusImpl& decoder, + uint32_t& rtp_timestamp, + uint32_t& timestamp) { + RTC_CHECK(encoder.NumChannels() == 1 || encoder.NumChannels() == 2); + const bool stereo_encoding = encoder.NumChannels() == 2; + const size_t decoder_num_channels = decoder.Channels(); + std::vector decoded_frame(kEncoderFrameLength * + decoder_num_channels); + + PCMFile pcm_file; + pcm_file.Open(test::ResourcePath( + stereo_encoding ? "near48_stereo" : "near48_mono", "pcm"), + kSampleRateHz, "rb"); + pcm_file.ReadStereo(stereo_encoding); + + AudioFrame audio_frame; + while (true) { + if (pcm_file.EndOfFile()) { break; } + pcm_file.Read10MsData(audio_frame); + rtc::Buffer payload; + encoder.Encode(rtp_timestamp++, audio_frame.data_view().data(), &payload); + + // Ignore empty payloads: the encoder needs more audio to produce a packet. + if (payload.size() == 0) { + continue; + } + + // Decode `payload`. + std::vector parse_results = + decoder.ParsePayload(std::move(payload), timestamp++); + RTC_CHECK_EQ(parse_results.size(), 1); + std::optional decode_results = + parse_results[0].frame->Decode(decoded_frame); + RTC_CHECK(decode_results); + + if (parse_results[0].frame->IsDtxPacket()) { + continue; + } + RTC_CHECK_EQ(decode_results->num_decoded_samples, decoded_frame.size()); + return decoded_frame; } - RTC_CHECK(dtx_packet_found); + RTC_CHECK_NOTREACHED(); } } // namespace @@ -239,6 +289,7 @@ TEST(AudioDecoderOpusTest, constexpr size_t kDecoderNumChannels = 2; AudioDecoderOpusImpl decoder(env.field_trials(), kDecoderNumChannels, kSampleRateHz); + std::vector decoded_frame; uint32_t rtp_timestamp = 0xFFFu; uint32_t timestamp = 0; @@ -250,7 +301,7 @@ TEST(AudioDecoderOpusTest, timestamp); // Decode an empty packet so that Opus generates comfort noise. - std::array decoded_frame; + decoded_frame.resize(kEncoderFrameLength * kDecoderNumChannels); AudioDecoder::SpeechType speech_type; const int num_decoded_samples = decoder.Decode(/*encoded=*/nullptr, /*encoded_len=*/0, kSampleRateHz, @@ -262,8 +313,14 @@ TEST(AudioDecoderOpusTest, num_decoded_samples); // Make sure that comfort noise is not a muted frame. ASSERT_FALSE(IsZeroedFrame(decoded_view)); - EXPECT_TRUE(IsTrivialStereo(decoded_view)); + + // Also check the first decoded audio frame after comfort noise. + decoded_frame = EncodeDecodeSpeechUntilOneFrameIsDecoded( + encoder, decoder, rtp_timestamp, timestamp); + ASSERT_THAT(decoded_frame, SizeIs(kDecoderNumChannels * kEncoderFrameLength)); + ASSERT_FALSE(IsZeroedFrame(decoded_frame)); + EXPECT_TRUE(IsTrivialStereo(decoded_frame)); } TEST(AudioDecoderOpusTest, MonoEncoderStereoDecoderOutputsTrivialStereoPlc) { @@ -296,8 +353,14 @@ TEST(AudioDecoderOpusTest, MonoEncoderStereoDecoderOutputsTrivialStereoPlc) { concealment_audio.size()); // Make sure that packet loss concealment is not a muted frame. ASSERT_FALSE(IsZeroedFrame(decoded_view)); - EXPECT_TRUE(IsTrivialStereo(decoded_view)); + + // Also check the first decoded audio frame after packet loss concealment. + std::vector decoded_frame = EncodeDecodeSpeechUntilOneFrameIsDecoded( + encoder, decoder, rtp_timestamp, timestamp); + ASSERT_THAT(decoded_frame, SizeIs(kDecoderNumChannels * kEncoderFrameLength)); + ASSERT_FALSE(IsZeroedFrame(decoded_frame)); + EXPECT_TRUE(IsTrivialStereo(decoded_frame)); } TEST(AudioDecoderOpusTest, diff --git a/third_party/libwebrtc/modules/audio_coding/codecs/opus/opus_interface.cc b/third_party/libwebrtc/modules/audio_coding/codecs/opus/opus_interface.cc index 565f803741a2..d18b517fe41b 100644 --- a/third_party/libwebrtc/modules/audio_coding/codecs/opus/opus_interface.cc +++ b/third_party/libwebrtc/modules/audio_coding/codecs/opus/opus_interface.cc @@ -547,22 +547,9 @@ int WebRtcOpus_Decode(OpusDecInst* inst, int16_t* decoded, int16_t* audio_type) { int decoded_samples_per_channel; - if (encoded_bytes == 0) { *audio_type = DetermineAudioType(inst, encoded_bytes); decoded_samples_per_channel = DecodePlc(inst, decoded); - - // TODO: https://issues.webrtc.org/376493209 - When fixed, remove block - // below. - if (inst->channels == 2 && inst->last_packet_num_channels == 1) { - // Stereo decoding is enabled and the last observed packet to decode - // encoded mono audio. In this case, Opus generates non-trivial stereo - // audio. Since this is unwanted, copy the left channel into the right - // one. - for (int i = 0; i < decoded_samples_per_channel << 1; i += 2) { - decoded[i + 1] = decoded[i]; - } - } } else { decoded_samples_per_channel = DecodeNative( inst, encoded, encoded_bytes, @@ -570,14 +557,25 @@ int WebRtcOpus_Decode(OpusDecInst* inst, // TODO: https://issues.webrtc.org/376493209 - When fixed, remove block // below. - const int num_channels = opus_packet_get_nb_channels(encoded); - RTC_DCHECK(num_channels == 1 || num_channels == 2); - inst->last_packet_num_channels = num_channels; + inst->last_packet_num_channels = opus_packet_get_nb_channels(encoded); + RTC_DCHECK(inst->last_packet_num_channels == 1 || + inst->last_packet_num_channels == 2); } if (decoded_samples_per_channel < 0) { return -1; } + // TODO: https://issues.webrtc.org/376493209 - When fixed, remove block below. + // When stereo decoding is enabled and the last observed non-empty packet + // encoded mono audio, the Opus decoder may generate non-trivial stereo audio. + // As that is undesired, in that case make sure that `decoded` contains + // trivial stereo audio by copying the left channel into the right one. + if (inst->channels == 2 && inst->last_packet_num_channels == 1) { + for (int i = 0; i < decoded_samples_per_channel << 1; i += 2) { + decoded[i + 1] = decoded[i]; + } + } + return decoded_samples_per_channel; } diff --git a/third_party/libwebrtc/moz-patch-stack/0030.patch b/third_party/libwebrtc/moz-patch-stack/0030.patch index cc92389c505a..7bb38b3d57d5 100644 --- a/third_party/libwebrtc/moz-patch-stack/0030.patch +++ b/third_party/libwebrtc/moz-patch-stack/0030.patch @@ -753,7 +753,7 @@ index e354db54a0..d2855cbfb0 100644 using webrtc::FrameDecryptorInterface; using webrtc::FrameEncryptorInterface; diff --git a/modules/audio_coding/BUILD.gn b/modules/audio_coding/BUILD.gn -index a2a1ca8328..05150752be 100644 +index 78bdccfefe..1df856e2e9 100644 --- a/modules/audio_coding/BUILD.gn +++ b/modules/audio_coding/BUILD.gn @@ -358,7 +358,7 @@ rtc_library("webrtc_opus_wrapper") { diff --git a/third_party/libwebrtc/moz-patch-stack/0124.patch b/third_party/libwebrtc/moz-patch-stack/0124.patch index 1b25178f84c1..fd53fb74d8bf 100644 --- a/third_party/libwebrtc/moz-patch-stack/0124.patch +++ b/third_party/libwebrtc/moz-patch-stack/0124.patch @@ -16,7 +16,7 @@ Mercurial Revision: https://hg.mozilla.org/mozilla-central/rev/bbec1b95ddb5e0096 5 files changed, 26 insertions(+), 6 deletions(-) diff --git a/modules/audio_coding/BUILD.gn b/modules/audio_coding/BUILD.gn -index 05150752be..8a552ed917 100644 +index 1df856e2e9..e547f76cff 100644 --- a/modules/audio_coding/BUILD.gn +++ b/modules/audio_coding/BUILD.gn @@ -358,7 +358,7 @@ rtc_library("webrtc_opus_wrapper") {