commit d787ba63db653392275f3fb1477c08b6a223f5d3 parent 8d5ec70a721b81d1b3c72c7869edf2b325043676 Author: Dan Baker <dbaker@mozilla.com> Date: Wed, 22 Oct 2025 13:45:03 -0600 Bug 1995393 - Vendor libwebrtc from 7cf44a4cc3 Upstream commit: https://webrtc.googlesource.com/src/+/7cf44a4cc3e1a20b54398c4b9eadc255016344a7 Implement L4S send stats described in https://github.com/w3c/webrtc-stats/pull/792 with a location change from https://github.com/w3c/webrtc-stats/pull/808 Bug: webrtc:42225697 Change-Id: I2660a17928ed6ecfb75ca597759c960678f17eaf Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/390866 Reviewed-by: Harald Alvestrand <hta@webrtc.org> Reviewed-by: Per Kjellander <perkj@webrtc.org> Commit-Queue: Philipp Hancke <phancke@meta.com> Cr-Commit-Position: refs/heads/main@{#45283} Diffstat:
20 files changed, 75 insertions(+), 17 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 /Users/danielbaker/elm/.moz-fast-forward/moz-libwebrtc --commit mozpatches libwebrtc -libwebrtc updated from /Users/danielbaker/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2025-10-22T19:42:03.164825+00:00. +libwebrtc updated from /Users/danielbaker/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2025-10-22T19:44:53.145515+00:00. # base of lastest vendoring -77e84253e0 +7cf44a4cc3 diff --git a/third_party/libwebrtc/api/stats/rtcstats_objects.h b/third_party/libwebrtc/api/stats/rtcstats_objects.h @@ -369,6 +369,9 @@ class RTC_EXPORT RTCOutboundRtpStreamStats final // RTX ssrc. Only present if RTX is negotiated. std::optional<uint32_t> rtx_ssrc; + + // https://w3c.github.io/webrtc-stats/#dom-rtcoutboundrtpstreamstats-packetssentwithect1 + std::optional<uint64_t> packets_sent_with_ect1; }; // https://w3c.github.io/webrtc-stats/#remoteinboundrtpstats-dict* diff --git a/third_party/libwebrtc/audio/audio_send_stream.cc b/third_party/libwebrtc/audio/audio_send_stream.cc @@ -443,6 +443,7 @@ webrtc::AudioSendStream::Stats AudioSendStream::GetStats( call_stats.header_and_padding_bytes_sent; stats.retransmitted_bytes_sent = call_stats.retransmitted_bytes_sent; stats.packets_sent = call_stats.packetsSent; + stats.packets_sent_with_ect1 = call_stats.packets_sent_with_ect1; stats.total_packet_send_delay = call_stats.total_packet_send_delay; stats.retransmitted_packets_sent = call_stats.retransmitted_packets_sent; // RTT isn't known until a RTCP report is received. Until then, VoiceEngine diff --git a/third_party/libwebrtc/audio/channel_send.cc b/third_party/libwebrtc/audio/channel_send.cc @@ -839,6 +839,8 @@ CallSendStatistics ChannelSend::GetRTCPStatistics() const { stats.retransmitted_bytes_sent = rtp_stats.retransmitted.payload_bytes; stats.packetsSent = rtp_stats.transmitted.packets + rtx_stats.transmitted.packets; + stats.packets_sent_with_ect1 = rtp_stats.transmitted.packets_with_ect1 + + rtx_stats.transmitted.packets_with_ect1; stats.total_packet_send_delay = rtp_stats.transmitted.total_packet_delay; stats.retransmitted_packets_sent = rtp_stats.retransmitted.packets; stats.report_block_datas = rtp_rtcp_->GetLatestReportBlockData(); diff --git a/third_party/libwebrtc/audio/channel_send.h b/third_party/libwebrtc/audio/channel_send.h @@ -46,6 +46,8 @@ struct CallSendStatistics { // https://w3c.github.io/webrtc-stats/#dom-rtcoutboundrtpstreamstats-retransmittedbytessent uint64_t retransmitted_bytes_sent; int packetsSent; + // https://w3c.github.io/webrtc-stats/#dom-rtcoutboundrtpstreamstats-packetssentwithect1 + int packets_sent_with_ect1; // https://w3c.github.io/webrtc-stats/#dom-rtcoutboundrtpstreamstats-totalpacketsenddelay TimeDelta total_packet_send_delay = TimeDelta::Zero(); // https://w3c.github.io/webrtc-stats/#dom-rtcoutboundrtpstreamstats-retransmittedpacketssent diff --git a/third_party/libwebrtc/call/audio_send_stream.h b/third_party/libwebrtc/call/audio_send_stream.h @@ -49,6 +49,8 @@ class AudioSendStream : public AudioSender { // https://w3c.github.io/webrtc-stats/#dom-rtcoutboundrtpstreamstats-retransmittedbytessent uint64_t retransmitted_bytes_sent = 0; int32_t packets_sent = 0; + // https://w3c.github.io/webrtc-stats/#dom-rtcoutboundrtpstreamstats-packetssentwithect1 + int32_t packets_sent_with_ect1 = 0; // https://w3c.github.io/webrtc-stats/#dom-rtcoutboundrtpstreamstats-totalpacketsenddelay TimeDelta total_packet_send_delay = TimeDelta::Zero(); // https://w3c.github.io/webrtc-stats/#dom-rtcoutboundrtpstreamstats-retransmittedpacketssent diff --git a/third_party/libwebrtc/media/base/media_channel.h b/third_party/libwebrtc/media/base/media_channel.h @@ -363,6 +363,8 @@ struct MediaSenderInfo { // https://w3c.github.io/webrtc-stats/#dom-rtcoutboundrtpstreamstats-retransmittedbytessent uint64_t retransmitted_bytes_sent = 0; int packets_sent = 0; + // https://w3c.github.io/webrtc-stats/#dom-rtcoutboundrtpstreamstats-packetssentwithect1 + int packets_sent_with_ect1 = 0; // https://w3c.github.io/webrtc-stats/#dom-rtcoutboundrtpstreamstats-retransmittedpacketssent uint64_t retransmitted_packets_sent = 0; // https://w3c.github.io/webrtc-stats/#dom-rtcoutboundrtpstreamstats-nackcount diff --git a/third_party/libwebrtc/media/engine/webrtc_video_engine.cc b/third_party/libwebrtc/media/engine/webrtc_video_engine.cc @@ -2514,6 +2514,8 @@ WebRtcVideoSendChannel::WebRtcVideoSendStream::GetPerLayerVideoSenderInfos( stream_stats.rtp_stats.transmitted.header_bytes + stream_stats.rtp_stats.transmitted.padding_bytes; info.packets_sent = stream_stats.rtp_stats.transmitted.packets; + info.packets_sent_with_ect1 = + stream_stats.rtp_stats.transmitted.packets_with_ect1; info.total_packet_send_delay += stream_stats.rtp_stats.transmitted.total_packet_delay; info.send_frame_width = stream_stats.width; diff --git a/third_party/libwebrtc/media/engine/webrtc_voice_engine.cc b/third_party/libwebrtc/media/engine/webrtc_voice_engine.cc @@ -1800,6 +1800,7 @@ bool WebRtcVoiceSendChannel::GetStats(VoiceMediaSendInfo* info) { sinfo.header_and_padding_bytes_sent = stats.header_and_padding_bytes_sent; sinfo.retransmitted_bytes_sent = stats.retransmitted_bytes_sent; sinfo.packets_sent = stats.packets_sent; + sinfo.packets_sent_with_ect1 = stats.packets_sent_with_ect1; sinfo.total_packet_send_delay = stats.total_packet_send_delay; sinfo.retransmitted_packets_sent = stats.retransmitted_packets_sent; sinfo.packets_lost = stats.packets_lost; diff --git a/third_party/libwebrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.cc b/third_party/libwebrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.cc @@ -51,12 +51,16 @@ RtpPacketCounter::RtpPacketCounter(const RtpPacket& packet) : header_bytes(packet.headers_size()), payload_bytes(packet.payload_size()), padding_bytes(packet.padding_size()), - packets(1) {} + packets(1), + packets_with_ect1(0) {} RtpPacketCounter::RtpPacketCounter(const RtpPacketToSend& packet_to_send) : RtpPacketCounter(static_cast<const RtpPacket&>(packet_to_send)) { total_packet_delay = packet_to_send.time_in_send_queue().value_or(TimeDelta::Zero()); + if (packet_to_send.send_as_ect1()) { + ++packets_with_ect1; + } } void RtpPacketCounter::AddPacket(const RtpPacket& packet) { @@ -70,6 +74,9 @@ void RtpPacketCounter::AddPacket(const RtpPacketToSend& packet_to_send) { AddPacket(static_cast<const RtpPacket&>(packet_to_send)); total_packet_delay += packet_to_send.time_in_send_queue().value_or(TimeDelta::Zero()); + if (packet_to_send.send_as_ect1()) { + ++packets_with_ect1; + } } } // namespace webrtc diff --git a/third_party/libwebrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h b/third_party/libwebrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h @@ -276,7 +276,11 @@ class RtcpRttStats { struct RtpPacketCounter { RtpPacketCounter() - : header_bytes(0), payload_bytes(0), padding_bytes(0), packets(0) {} + : header_bytes(0), + payload_bytes(0), + padding_bytes(0), + packets(0), + packets_with_ect1(0) {} explicit RtpPacketCounter(const RtpPacket& packet); explicit RtpPacketCounter(const RtpPacketToSend& packet_to_send); @@ -286,6 +290,7 @@ struct RtpPacketCounter { payload_bytes += other.payload_bytes; padding_bytes += other.padding_bytes; packets += other.packets; + packets_with_ect1 += other.packets_with_ect1; total_packet_delay += other.total_packet_delay; } @@ -293,6 +298,7 @@ struct RtpPacketCounter { return header_bytes == other.header_bytes && payload_bytes == other.payload_bytes && padding_bytes == other.padding_bytes && packets == other.packets && + packets_with_ect1 == other.packets_with_ect1 && total_packet_delay == other.total_packet_delay; } @@ -308,6 +314,7 @@ struct RtpPacketCounter { size_t payload_bytes; // Payload bytes, excluding RTP headers and padding. size_t padding_bytes; // Number of padding bytes. size_t packets; // Number of packets. + size_t packets_with_ect1; // Number of packets with ECT1 flag set to true. // The total delay of all `packets`. For RtpPacketToSend packets, this is // `time_in_send_queue()`. For receive packets, this is zero. TimeDelta total_packet_delay = TimeDelta::Zero(); diff --git a/third_party/libwebrtc/moz-patch-stack/s0027.patch b/third_party/libwebrtc/moz-patch-stack/s0027.patch @@ -491,7 +491,7 @@ index 01b4bcf984..ff746af7d4 100644 "../api:transport_api", "../api/adaptation:resource_adaptation_api", diff --git a/call/audio_send_stream.h b/call/audio_send_stream.h -index 2cc5397e31..021a2976dd 100644 +index 851c7aed30..2ae1020161 100644 --- a/call/audio_send_stream.h +++ b/call/audio_send_stream.h @@ -27,7 +27,7 @@ @@ -689,7 +689,7 @@ index 98a675a7c9..6cfbf1b9f3 100644 rtc_library("rtc_audio_video") { diff --git a/media/base/media_channel.h b/media/base/media_channel.h -index 6a3463937c..9247d6837b 100644 +index 17ad9ad5b6..c844dfd798 100644 --- a/media/base/media_channel.h +++ b/media/base/media_channel.h @@ -67,9 +67,6 @@ namespace webrtc { diff --git a/third_party/libwebrtc/moz-patch-stack/s0029.patch b/third_party/libwebrtc/moz-patch-stack/s0029.patch @@ -15,7 +15,7 @@ Mercurial Revision: https://hg.mozilla.org/mozilla-central/rev/d380a43d59f4f7cbc 4 files changed, 35 insertions(+) diff --git a/audio/audio_send_stream.cc b/audio/audio_send_stream.cc -index 5c7fa93ba5..e2668b8df7 100644 +index 5b6c070d02..bd3b7ca994 100644 --- a/audio/audio_send_stream.cc +++ b/audio/audio_send_stream.cc @@ -437,6 +437,7 @@ webrtc::AudioSendStream::Stats AudioSendStream::GetStats( @@ -27,7 +27,7 @@ index 5c7fa93ba5..e2668b8df7 100644 stats.header_and_padding_bytes_sent = call_stats.header_and_padding_bytes_sent; diff --git a/audio/channel_send.cc b/audio/channel_send.cc -index 06ebdd2346..885b0c01ff 100644 +index b0759406c8..7a262bcea3 100644 --- a/audio/channel_send.cc +++ b/audio/channel_send.cc @@ -81,6 +81,31 @@ constexpr TimeDelta kMinRetransmissionWindow = TimeDelta::Millis(30); @@ -97,10 +97,10 @@ index 06ebdd2346..885b0c01ff 100644 StreamDataCounters rtp_stats; StreamDataCounters rtx_stats; diff --git a/audio/channel_send.h b/audio/channel_send.h -index 0ed544afed..7047248c1f 100644 +index 1706406e4f..232748f33c 100644 --- a/audio/channel_send.h +++ b/audio/channel_send.h -@@ -50,6 +50,7 @@ struct CallSendStatistics { +@@ -52,6 +52,7 @@ struct CallSendStatistics { TimeDelta total_packet_send_delay = TimeDelta::Zero(); // https://w3c.github.io/webrtc-stats/#dom-rtcoutboundrtpstreamstats-retransmittedpacketssent uint64_t retransmitted_packets_sent; @@ -109,7 +109,7 @@ index 0ed544afed..7047248c1f 100644 // Within this list, the sender-source SSRC pair is unique and per-pair the // ReportBlockData represents the latest Report Block that was received for diff --git a/call/audio_send_stream.h b/call/audio_send_stream.h -index 021a2976dd..d2ff41b0f4 100644 +index 2ae1020161..88e8a7f18b 100644 --- a/call/audio_send_stream.h +++ b/call/audio_send_stream.h @@ -32,6 +32,7 @@ @@ -120,7 +120,7 @@ index 021a2976dd..d2ff41b0f4 100644 namespace webrtc { -@@ -66,6 +67,7 @@ class AudioSendStream : public AudioSender { +@@ -68,6 +69,7 @@ class AudioSendStream : public AudioSender { ANAStats ana_statistics; AudioProcessingStats apm_statistics; diff --git a/third_party/libwebrtc/moz-patch-stack/s0035.patch b/third_party/libwebrtc/moz-patch-stack/s0035.patch @@ -168,7 +168,7 @@ index c69ec1a674..b07f08eddf 100644 // Transport for outgoing packets (RTCP). diff --git a/modules/rtp_rtcp/include/rtp_rtcp_defines.h b/modules/rtp_rtcp/include/rtp_rtcp_defines.h -index a888e4f3d8..4783206052 100644 +index 2552792e10..aa6a7a3005 100644 --- a/modules/rtp_rtcp/include/rtp_rtcp_defines.h +++ b/modules/rtp_rtcp/include/rtp_rtcp_defines.h @@ -180,6 +180,14 @@ class NetworkLinkRtcpObserver { diff --git a/third_party/libwebrtc/moz-patch-stack/s0070.patch b/third_party/libwebrtc/moz-patch-stack/s0070.patch @@ -12,7 +12,7 @@ Mercurial Revision: https://hg.mozilla.org/mozilla-central/rev/6ac6592a04a839a61 1 file changed, 2 deletions(-) diff --git a/audio/channel_send.cc b/audio/channel_send.cc -index 885b0c01ff..8ac2891c7c 100644 +index 7a262bcea3..f275cc60d8 100644 --- a/audio/channel_send.cc +++ b/audio/channel_send.cc @@ -571,8 +571,6 @@ ChannelSend::ChannelSend( diff --git a/third_party/libwebrtc/pc/rtc_stats_collector.cc b/third_party/libwebrtc/pc/rtc_stats_collector.cc @@ -730,6 +730,8 @@ void SetOutboundRTPStreamStatsFromMediaSenderInfo( if (media_sender_info.active.has_value()) { outbound_stats->active = *media_sender_info.active; } + outbound_stats->packets_sent_with_ect1 = + media_sender_info.packets_sent_with_ect1; } std::unique_ptr<RTCOutboundRtpStreamStats> diff --git a/third_party/libwebrtc/pc/rtc_stats_collector_unittest.cc b/third_party/libwebrtc/pc/rtc_stats_collector_unittest.cc @@ -2523,6 +2523,7 @@ TEST_F(RTCStatsCollectorTest, CollectRTCOutboundRtpStreamStats_Audio) { voice_media_info.senders[0].local_stats.push_back(SsrcSenderInfo()); voice_media_info.senders[0].local_stats[0].ssrc = 1; voice_media_info.senders[0].packets_sent = 2; + voice_media_info.senders[0].packets_sent_with_ect1 = 2; voice_media_info.senders[0].total_packet_send_delay = TimeDelta::Seconds(1); voice_media_info.senders[0].retransmitted_packets_sent = 20; voice_media_info.senders[0].payload_bytes_sent = 3; @@ -2558,6 +2559,7 @@ TEST_F(RTCStatsCollectorTest, CollectRTCOutboundRtpStreamStats_Audio) { expected_audio.transport_id = "TTransportName1"; expected_audio.codec_id = "COTTransportName1_42"; expected_audio.packets_sent = 2; + expected_audio.packets_sent_with_ect1 = 2; expected_audio.total_packet_send_delay = 1; expected_audio.retransmitted_packets_sent = 20; expected_audio.bytes_sent = 3; @@ -2592,6 +2594,7 @@ TEST_F(RTCStatsCollectorTest, CollectRTCOutboundRtpStreamStats_Video) { video_media_info.senders[0].plis_received = 3; video_media_info.senders[0].nacks_received = 4; video_media_info.senders[0].packets_sent = 5; + video_media_info.senders[0].packets_sent_with_ect1 = 3; video_media_info.senders[0].retransmitted_packets_sent = 50; video_media_info.senders[0].payload_bytes_sent = 6; video_media_info.senders[0].header_and_padding_bytes_sent = 12; @@ -2669,6 +2672,7 @@ TEST_F(RTCStatsCollectorTest, CollectRTCOutboundRtpStreamStats_Video) { expected_video.pli_count = 3; expected_video.nack_count = 4; expected_video.packets_sent = 5; + expected_video.packets_sent_with_ect1 = 3; expected_video.retransmitted_packets_sent = 50; expected_video.bytes_sent = 6; expected_video.header_bytes_sent = 12; @@ -2971,6 +2975,7 @@ TEST_F(RTCStatsCollectorTest, CollectNoStreamRTCOutboundRtpStreamStats_Audio) { voice_media_info.senders[0].local_stats.push_back(SsrcSenderInfo()); voice_media_info.senders[0].local_stats[0].ssrc = 1; voice_media_info.senders[0].packets_sent = 2; + voice_media_info.senders[0].packets_sent_with_ect1 = 0; voice_media_info.senders[0].total_packet_send_delay = TimeDelta::Seconds(0.5); voice_media_info.senders[0].retransmitted_packets_sent = 20; voice_media_info.senders[0].payload_bytes_sent = 3; @@ -3005,6 +3010,7 @@ TEST_F(RTCStatsCollectorTest, CollectNoStreamRTCOutboundRtpStreamStats_Audio) { expected_audio.transport_id = "TTransportName1"; expected_audio.codec_id = "COTTransportName1_42"; expected_audio.packets_sent = 2; + expected_audio.packets_sent_with_ect1 = 0; expected_audio.total_packet_send_delay = 0.5; expected_audio.retransmitted_packets_sent = 20; expected_audio.bytes_sent = 3; diff --git a/third_party/libwebrtc/pc/rtc_stats_integrationtest.cc b/third_party/libwebrtc/pc/rtc_stats_integrationtest.cc @@ -799,6 +799,8 @@ class RTCStatsReportVerifier { verifier.TestAttributeIsNonNegative<uint64_t>( outbound_stream.retransmitted_bytes_sent); verifier.TestAttributeIsNonNegative<double>(outbound_stream.target_bitrate); + verifier.TestAttributeIsNonNegative<uint64_t>( + outbound_stream.packets_sent_with_ect1); if (outbound_stream.kind.has_value() && *outbound_stream.kind == "video") { verifier.TestAttributeIsDefined(outbound_stream.frames_encoded); verifier.TestAttributeIsDefined(outbound_stream.key_frames_encoded); diff --git a/third_party/libwebrtc/stats/rtcstats_objects.cc b/third_party/libwebrtc/stats/rtcstats_objects.cc @@ -324,7 +324,8 @@ WEBRTC_RTCSTATS_IMPL( AttributeInit("active", &active), AttributeInit("powerEfficientEncoder", &power_efficient_encoder), AttributeInit("scalabilityMode", &scalability_mode), - AttributeInit("rtxSsrc", &rtx_ssrc)) + AttributeInit("rtxSsrc", &rtx_ssrc), + AttributeInit("packetsSentWithEct1", &packets_sent_with_ect1)) // clang-format on RTCOutboundRtpStreamStats::RTCOutboundRtpStreamStats(std::string id, diff --git a/third_party/libwebrtc/test/peer_scenario/tests/l4s_test.cc b/third_party/libwebrtc/test/peer_scenario/tests/l4s_test.cc @@ -9,6 +9,8 @@ */ #include <atomic> +#include <cstdint> +#include <optional> #include <string> #include "absl/strings/str_cat.h" @@ -121,6 +123,15 @@ DataRate GetAvailableSendBitrate( return DataRate::BitsPerSec(*stats[0]->available_outgoing_bitrate); } +std::optional<uint64_t> GetPacketsSentWithEct1( + const scoped_refptr<const RTCStatsReport>& report) { + auto stats = report->GetStatsOfType<RTCOutboundRtpStreamStats>(); + if (stats.empty()) { + return std::nullopt; + } + return stats[0]->packets_sent_with_ect1; +} + TEST(L4STest, NegotiateAndUseCcfbIfEnabled) { PeerScenario s(*test_info_); @@ -303,11 +314,11 @@ TEST(L4STest, SendsEct1UntilFirstFeedback) { feedback_counter.Count(packet); if (feedback_counter.ect1() > 0) { seen_ect1_feedback = true; - RTC_LOG(LS_INFO) << " ect 1" << feedback_counter.ect1(); + RTC_LOG(LS_INFO) << " ect 1: " << feedback_counter.ect1(); } if (feedback_counter.not_ect() > 0) { seen_not_ect_feedback = true; - RTC_LOG(LS_INFO) << " not ect" << feedback_counter.not_ect(); + RTC_LOG(LS_INFO) << " not ect: " << feedback_counter.not_ect(); } }); @@ -331,6 +342,9 @@ TEST(L4STest, SendsEct1UntilFirstFeedback) { EXPECT_TRUE(s.WaitAndProcess(&seen_ect1_feedback, TimeDelta::Seconds(1))); EXPECT_FALSE(seen_not_ect_feedback); EXPECT_TRUE(s.WaitAndProcess(&seen_not_ect_feedback, TimeDelta::Seconds(1))); + auto packets_sent_with_ect1_stats = + GetPacketsSentWithEct1(GetStatsAndProcess(s, caller)); + EXPECT_EQ(packets_sent_with_ect1_stats, feedback_counter.ect1()); } TEST(L4STest, SendsEct1AfterRouteChange) { @@ -416,6 +430,10 @@ TEST(L4STest, SendsEct1AfterRouteChange) { s.net()->DisableEndpoint(callee->endpoint(0)); EXPECT_TRUE( s.WaitAndProcess(&seen_ect1_on_cellular_feedback, TimeDelta::Seconds(5))); + auto packets_sent_with_ect1_stats = + GetPacketsSentWithEct1(GetStatsAndProcess(s, caller)); + EXPECT_EQ(packets_sent_with_ect1_stats, + wifi_feedback_counter.ect1() + cellular_feedback_counter.ect1()); } } // namespace