commit 3bcc5255de660e64a87dec1a9f2903fea940c94e
parent 1e42a77af648871483f4aa7c66b966c994faa7cc
Author: Michael Froman <mfroman@mozilla.com>
Date: Thu, 9 Oct 2025 14:50:01 -0500
Bug 1993083 - Vendor libwebrtc from e30dd59e03
Upstream commit: https://webrtc.googlesource.com/src/+/e30dd59e0362ef7c5cd62294daed5e24e7e552c9
Change SetLocalContent_w to update header extensions on answer.
The functions were skipping over updating the sender and receiver when
the list of header extensions was changed in offer/answer.
The revised version ensures that caller's sender always have the
extension list from the last applied prAnswer / answer. Adding all
the fixes generated surprising results, so this tries for the
minimum change.
Bug: webrtc:383078466
Change-Id: I78d4087970d388d81a9b84cc86aa1929d354d827
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/399760
Auto-Submit: Harald Alvestrand <hta@webrtc.org>
Commit-Queue: Harald Alvestrand <hta@webrtc.org>
Reviewed-by: Philip Eliasson <philipel@webrtc.org>
Cr-Commit-Position: refs/heads/main@{#45161}
Diffstat:
7 files changed, 97 insertions(+), 22 deletions(-)
diff --git a/third_party/libwebrtc/README.mozilla.last-vendor b/third_party/libwebrtc/README.mozilla.last-vendor
@@ -1,4 +1,4 @@
# ./mach python dom/media/webrtc/third_party_build/vendor-libwebrtc.py --from-local /home/mfroman/mozilla/elm/.moz-fast-forward/moz-libwebrtc --commit mozpatches libwebrtc
-libwebrtc updated from /home/mfroman/mozilla/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2025-10-09T19:48:49.094960+00:00.
+libwebrtc updated from /home/mfroman/mozilla/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2025-10-09T19:49:52.179522+00:00.
# base of lastest vendoring
-31417145ed
+e30dd59e03
diff --git a/third_party/libwebrtc/api/jsep.h b/third_party/libwebrtc/api/jsep.h
@@ -198,6 +198,11 @@ enum class SdpType {
// SessionDescriptionInterface.
RTC_EXPORT const char* SdpTypeToString(SdpType type);
+template <typename Sink>
+void AbslStringify(Sink& sink, SdpType sdp_type) {
+ sink.Append(SdpTypeToString(sdp_type));
+}
+
// Returns the SdpType from its string form. The string form can be one of the
// constants defined in SessionDescriptionInterface. Passing in any other string
// results in nullopt.
diff --git a/third_party/libwebrtc/media/base/codec.h b/third_party/libwebrtc/media/base/codec.h
@@ -192,6 +192,9 @@ struct RTC_EXPORT Codec {
sink.Append("video/");
}
absl::Format(&sink, "%s/%d/%d", c.name, c.clockrate, c.channels);
+ if (c.packetization) {
+ absl::Format(&sink, ",packetization=%s", *c.packetization);
+ }
for (auto param : c.params) {
sink.Append(";");
sink.Append(param.first);
diff --git a/third_party/libwebrtc/pc/channel.cc b/third_party/libwebrtc/pc/channel.cc
@@ -1035,6 +1035,7 @@ bool VideoChannel::SetLocalContent_w(const MediaContentDescription* content,
RtpHeaderExtensions header_extensions =
GetDeduplicatedRtpHeaderExtensions(content->rtp_header_extensions());
bool update_header_extensions = true;
+ // TODO: issues.webrtc.org/396640 - remove if pushdown on answer is enough.
media_send_channel()->SetExtmapAllowMixed(content->extmap_allow_mixed());
VideoReceiverParameters recv_params = last_recv_params_;
@@ -1044,13 +1045,13 @@ bool VideoChannel::SetLocalContent_w(const MediaContentDescription* content,
RtpTransceiverDirectionHasRecv(content->direction()), &recv_params);
VideoSenderParameters send_params = last_send_params_;
+ send_params.extmap_allow_mixed = content->extmap_allow_mixed();
// Ensure that there is a matching packetization for each send codec. If the
// other peer offered to exclusively send non-standard packetization but we
// only accept to receive standard packetization we effectively amend their
// offer by ignoring the packetiztion and fall back to standard packetization
// instead.
- bool needs_send_params_update = false;
if (type == SdpType::kAnswer || type == SdpType::kPrAnswer) {
flat_set<const Codec*> matched_codecs;
for (Codec& send_codec : send_params.codecs) {
@@ -1080,7 +1081,6 @@ bool VideoChannel::SetLocalContent_w(const MediaContentDescription* content,
if (may_ignore_packetization) {
send_codec.packetization = std::nullopt;
- needs_send_params_update = true;
} else if (!has_matching_packetization) {
error_desc = StringFormat(
"Failed to set local answer due to incompatible codec "
@@ -1113,7 +1113,7 @@ bool VideoChannel::SetLocalContent_w(const MediaContentDescription* content,
last_recv_params_ = recv_params;
- if (needs_send_params_update) {
+ if (type == SdpType::kAnswer || type == SdpType::kPrAnswer) {
if (!media_send_channel()->SetSenderParameters(send_params)) {
error_desc = StringFormat(
"Failed to set send parameters for m-section with mid='%s'.",
diff --git a/third_party/libwebrtc/pc/channel_unittest.cc b/third_party/libwebrtc/pc/channel_unittest.cc
@@ -2387,18 +2387,22 @@ TEST_F(VideoChannelSingleThreadTest,
EXPECT_THAT(
media_receive_channel1_impl()->recv_codecs(),
- ElementsAre(AllOf(Field(&webrtc::Codec::id, 96),
- Field(&webrtc::Codec::packetization, "foo")),
- AllOf(Field(&webrtc::Codec::id, 98),
- Field(&webrtc::Codec::packetization, std::nullopt))));
+ ElementsAre(
+ AllOf(Field("id", &webrtc::Codec::id, 96),
+ Field("packetization", &webrtc::Codec::packetization, "foo")),
+ AllOf(Field("id", &webrtc::Codec::id, 98),
+ Field("packetization", &webrtc::Codec::packetization,
+ std::nullopt))));
EXPECT_THAT(
media_send_channel1_impl()->send_codecs(),
- ElementsAre(AllOf(Field(&webrtc::Codec::id, 96),
- Field(&webrtc::Codec::packetization, "foo")),
- AllOf(Field(&webrtc::Codec::id, 97),
- Field(&webrtc::Codec::packetization, "bar")),
- AllOf(Field(&webrtc::Codec::id, 99),
- Field(&webrtc::Codec::packetization, std::nullopt))));
+ ElementsAre(
+ AllOf(Field("id", &webrtc::Codec::id, 96),
+ Field("packetization", &webrtc::Codec::packetization, "foo")),
+ AllOf(Field("id", &webrtc::Codec::id, 97),
+ Field("packetization", &webrtc::Codec::packetization, "bar")),
+ AllOf(Field("id", &webrtc::Codec::id, 99),
+ Field("packetization", &webrtc::Codec::packetization,
+ std::nullopt))));
}
TEST_F(VideoChannelSingleThreadTest,
diff --git a/third_party/libwebrtc/pc/congestion_control_integrationtest.cc b/third_party/libwebrtc/pc/congestion_control_integrationtest.cc
@@ -13,10 +13,14 @@
#include <memory>
#include <string>
+#include <vector>
#include "absl/strings/str_cat.h"
#include "api/jsep.h"
+#include "api/media_types.h"
#include "api/peer_connection_interface.h"
+#include "api/rtp_parameters.h"
+#include "api/rtp_transceiver_direction.h"
#include "api/test/rtc_error_matchers.h"
#include "pc/test/integration_test_helpers.h"
#include "test/gmock.h"
@@ -25,11 +29,12 @@
namespace webrtc {
-using testing::Eq;
+using ::testing::Eq;
+using ::testing::Field;
using ::testing::Gt;
-using testing::HasSubstr;
+using ::testing::HasSubstr;
using ::testing::IsTrue;
-using testing::Not;
+using ::testing::Not;
class PeerConnectionCongestionControlTest
: public PeerConnectionIntegrationBaseTest {
@@ -80,6 +85,57 @@ TEST_F(PeerConnectionCongestionControlTest, ReceiveOfferSetsCcfbFlag) {
EXPECT_THAT(answer_str, Not(HasSubstr("transport-cc")));
}
+TEST_F(PeerConnectionCongestionControlTest, NegotiatingCcfbRemovesTsn) {
+ SetFieldTrials("WebRTC-RFC8888CongestionControlFeedback/Enabled/");
+ ASSERT_TRUE(CreatePeerConnectionWrappers());
+ ConnectFakeSignalingForSdpOnly();
+ callee()->AddVideoTrack();
+ // Add transceivers to caller in order to accomodate reception
+ caller()->pc()->AddTransceiver(MediaType::VIDEO);
+ auto parameters = caller()->pc()->GetSenders()[0]->GetParameters();
+ caller()->CreateAndSetAndSignalOffer();
+ ASSERT_THAT(WaitUntil([&] { return SignalingStateStable(); }, IsTrue()),
+ IsRtcOk());
+
+ std::vector<RtpHeaderExtensionCapability> negotiated_header_extensions =
+ caller()->pc()->GetTransceivers()[0]->GetNegotiatedHeaderExtensions();
+ EXPECT_THAT(
+ negotiated_header_extensions,
+ Not(Contains(
+ AllOf(Field("uri", &RtpHeaderExtensionCapability::uri,
+ RtpExtension::kTransportSequenceNumberUri),
+ Not(Field("direction", &RtpHeaderExtensionCapability::direction,
+ RtpTransceiverDirection::kStopped))))))
+ << " in caller negotiated header extensions";
+
+ parameters = caller()->pc()->GetSenders()[0]->GetParameters();
+ EXPECT_THAT(parameters.header_extensions,
+ Not(Contains(Field("uri", &RtpExtension::uri,
+ RtpExtension::kTransportSequenceNumberUri))))
+ << " in caller sender parameters";
+ /* Caller receivers are not fixed yet.
+ TODO: issues.webrtc.org/383078466 - enable
+ parameters = caller()->pc()->GetReceivers()[0]->GetParameters();
+ EXPECT_THAT(parameters.header_extensions,
+ Not(Contains(Field("uri", &RtpExtension::uri,
+ RtpExtension::kTransportSequenceNumberUri))))
+ << " in caller receiver parameters";
+ */
+ /* Callee senders are not fixed yet.
+ TODO: issues.webrtc.org/383078466 - enable
+ parameters = callee()->pc()->GetSenders()[0]->GetParameters();
+ EXPECT_THAT(parameters.header_extensions,
+ Not(Contains(Field("uri", &RtpExtension::uri,
+ RtpExtension::kTransportSequenceNumberUri))))
+ << " in callee sender parameters";
+ */
+ parameters = callee()->pc()->GetReceivers()[0]->GetParameters();
+ EXPECT_THAT(parameters.header_extensions,
+ Not(Contains(Field("uri", &RtpExtension::uri,
+ RtpExtension::kTransportSequenceNumberUri))))
+ << " in callee receiver parameters";
+}
+
TEST_F(PeerConnectionCongestionControlTest, CcfbGetsUsed) {
SetFieldTrials("WebRTC-RFC8888CongestionControlFeedback/Enabled/");
ASSERT_TRUE(CreatePeerConnectionWrappers());
diff --git a/third_party/libwebrtc/pc/peer_connection_integrationtest.cc b/third_party/libwebrtc/pc/peer_connection_integrationtest.cc
@@ -4488,12 +4488,19 @@ TEST_F(PeerConnectionIntegrationTestUnifiedPlan,
caller()->CreateAndSetAndSignalOffer();
ASSERT_THAT(WaitUntil([&] { return SignalingStateStable(); }, IsTrue()),
IsRtcOk());
- ASSERT_THAT(WaitUntil([&] { return caller()->GetReceivedFrameCount(); },
+ std::vector<RtpHeaderExtensionCapability> negotiated_extensions =
+ caller()->pc()->GetTransceivers()[0]->GetNegotiatedHeaderExtensions();
+ ASSERT_THAT(negotiated_extensions,
+ Contains(Field("uri", &RtpHeaderExtensionCapability::uri,
+ RtpExtension::kCorruptionDetectionUri)));
+ ASSERT_THAT(WaitUntil([&] { return caller()->GetCorruptionScoreCount(); },
Eq(3), {.timeout = kMaxWaitForStats}),
- IsRtcOk());
- ASSERT_THAT(WaitUntil([&] { return callee()->GetReceivedFrameCount(); },
+ IsRtcOk())
+ << "Waiting for caller corruption score count > 0";
+ ASSERT_THAT(WaitUntil([&] { return callee()->GetCorruptionScoreCount(); },
Eq(3), {.timeout = kMaxWaitForStats}),
- IsRtcOk());
+ IsRtcOk())
+ << "Waiting for callee corruption score count > 0";
for (const auto& pair : {caller(), callee()}) {
scoped_refptr<const RTCStatsReport> report = pair->NewGetStats();