Skip to content

Commit

Permalink
Bug 1934695 - Vendor libwebrtc from 463ce639a6
Browse files Browse the repository at this point in the history
Upstream commit: https://webrtc.googlesource.com/src/+/463ce639a6175abb69dff6650e213cfd2ed89955
    With stereo decoding and mono packets produce mono after CN/PLC

    The workaround in https://webrtc-review.googlesource.com/c/src/+/367740
    is incomplete because it does not fix the issue for the first decoded
    mono packet after CN/PLC. This CL extends the workaround to such a case
    and adds a unit test for it.

    Note: it was verified that the 2nd packet after CN/PLC is trivial
    stereo.

    Credits: [email protected] for raising the concern

    (cherry picked from commit ebb11c4c87e4c0288d1ac18f38b4efa4254b3c6a)

    Bug: chromium:378896415
    Change-Id: Ide27e411781693f14629cf9db8b6c0c0fc762a17
    Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/368160
    Reviewed-by: Jakob Ivarsson‎ <[email protected]>
    Commit-Queue: Alessio Bazzica <[email protected]>
    Cr-Original-Commit-Position: refs/heads/main@{#43393}
    Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/368560
    Reviewed-by: Henrik Lundin <[email protected]>
    Cr-Commit-Position: refs/branch-heads/6834@{#1}
    Cr-Branched-From: a5d71009ac1dce7da23813dc9413c03073cfa8ca-refs/heads/main@{#43387}
  • Loading branch information
mfromanmoz committed Dec 5, 2024
1 parent ae05481 commit 3caed04
Show file tree
Hide file tree
Showing 7 changed files with 95 additions and 28 deletions.
3 changes: 3 additions & 0 deletions third_party/libwebrtc/README.moz-ff-commit
Original file line number Diff line number Diff line change
Expand Up @@ -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
2 changes: 2 additions & 0 deletions third_party/libwebrtc/README.mozilla
Original file line number Diff line number Diff line change
Expand Up @@ -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.
1 change: 1 addition & 0 deletions third_party/libwebrtc/modules/audio_coding/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,15 @@
#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"

namespace webrtc {
namespace {

using test::ExplicitKeyValueConfig;
using testing::SizeIs;

using DecodeResult = ::webrtc::AudioDecoder::EncodedAudioFrame::DecodeResult;
using ParseResult = ::webrtc::AudioDecoder::ParseResult;
Expand Down Expand Up @@ -158,7 +160,6 @@ void EncodeDecodeNoiseUntilDecoderInDtxMode(AudioEncoderOpusImpl& encoder,
std::vector<int16_t> 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;
Expand All @@ -170,23 +171,72 @@ 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<ParseResult> parse_results =
decoder.ParsePayload(std::move(payload), timestamp++);
RTC_CHECK_EQ(parse_results.size(), 1);
std::optional<DecodeResult> decode_results =
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<int16_t> 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<int16_t> 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<ParseResult> parse_results =
decoder.ParsePayload(std::move(payload), timestamp++);
RTC_CHECK_EQ(parse_results.size(), 1);
std::optional<DecodeResult> 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
Expand Down Expand Up @@ -239,6 +289,7 @@ TEST(AudioDecoderOpusTest,
constexpr size_t kDecoderNumChannels = 2;
AudioDecoderOpusImpl decoder(env.field_trials(), kDecoderNumChannels,
kSampleRateHz);
std::vector<int16_t> decoded_frame;

uint32_t rtp_timestamp = 0xFFFu;
uint32_t timestamp = 0;
Expand All @@ -250,7 +301,7 @@ TEST(AudioDecoderOpusTest,
timestamp);

// Decode an empty packet so that Opus generates comfort noise.
std::array<int16_t, kEncoderFrameLength * kDecoderNumChannels> decoded_frame;
decoded_frame.resize(kEncoderFrameLength * kDecoderNumChannels);
AudioDecoder::SpeechType speech_type;
const int num_decoded_samples =
decoder.Decode(/*encoded=*/nullptr, /*encoded_len=*/0, kSampleRateHz,
Expand All @@ -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) {
Expand Down Expand Up @@ -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<int16_t> 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,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -547,37 +547,35 @@ 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,
MaxFrameSizePerChannel(inst->sample_rate_hz), decoded, audio_type, 0);

// 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;
}

Expand Down
2 changes: 1 addition & 1 deletion third_party/libwebrtc/moz-patch-stack/0030.patch
Original file line number Diff line number Diff line change
Expand Up @@ -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") {
Expand Down
2 changes: 1 addition & 1 deletion third_party/libwebrtc/moz-patch-stack/0124.patch
Original file line number Diff line number Diff line change
Expand Up @@ -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") {
Expand Down

0 comments on commit 3caed04

Please sign in to comment.