tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

commit 7ad5273dc2ef0a53975b50331ba3c7bbbcc1cf55
parent 8a2da2dd0f0d651e046d47e7e9d0c889c13e9f96
Author: Dan Baker <dbaker@mozilla.com>
Date:   Mon,  1 Dec 2025 18:30:55 -0700

Bug 2000941 - Vendor libwebrtc from 6afeb1ce2c

Upstream commit: https://webrtc.googlesource.com/src/+/6afeb1ce2c87539c82cc7f4900e1ae12934bb6f8
    Add is_repeat_frame flag to VideoFrame

    This flag indicates if a VideoFrame is a copy of a previous frame.
    It is set to true by the FrameCadenceAdapter when generating
    repeated frames in zero-hertz mode.

    Bug: webrtc:443906251
    Change-Id: I9447c08a5b09c8d758462284546f08e54bc1b748
    Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/408782
    Reviewed-by: Markus Handell <handellm@webrtc.org>
    Commit-Queue: Erik Språng <sprang@webrtc.org>
    Cr-Commit-Position: refs/heads/main@{#45604}

Diffstat:
Mthird_party/libwebrtc/README.mozilla.last-vendor | 4++--
Mthird_party/libwebrtc/api/video/video_frame.cc | 46+++++++++++-----------------------------------
Mthird_party/libwebrtc/api/video/video_frame.h | 28+++++++++++++++++++++++++++-
Mthird_party/libwebrtc/common_video/video_frame_unittest.cc | 28++++++++++++++++++++++++++++
Mthird_party/libwebrtc/video/frame_cadence_adapter.cc | 1+
Mthird_party/libwebrtc/video/frame_cadence_adapter_unittest.cc | 39+++++++++++++++++++++++++++++++++++++++
6 files changed, 108 insertions(+), 38 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-12-02T01:27:35.135605+00:00. +libwebrtc updated from /Users/danielbaker/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2025-12-02T01:30:37.866900+00:00. # base of lastest vendoring -9d4cf430f2 +6afeb1ce2c diff --git a/third_party/libwebrtc/api/video/video_frame.cc b/third_party/libwebrtc/api/video/video_frame.cc @@ -174,7 +174,7 @@ VideoFrame VideoFrame::Builder::build() { return VideoFrame(id_, video_frame_buffer_, timestamp_us_, presentation_timestamp_, reference_time_, timestamp_rtp_, ntp_time_ms_, rotation_, color_space_, render_parameters_, - update_rect_, packet_infos_); + update_rect_, packet_infos_, is_repeat_frame_); } VideoFrame::Builder& VideoFrame::Builder::set_video_frame_buffer( @@ -264,6 +264,12 @@ VideoFrame::Builder& VideoFrame::Builder::set_packet_infos( return *this; } +VideoFrame::Builder& VideoFrame::Builder::set_is_repeat_frame( + bool is_repeat_frame) { + is_repeat_frame_ = is_repeat_frame; + return *this; +} + VideoFrame::VideoFrame(const scoped_refptr<VideoFrameBuffer>& buffer, VideoRotation rotation, int64_t timestamp_us) @@ -271,7 +277,8 @@ VideoFrame::VideoFrame(const scoped_refptr<VideoFrameBuffer>& buffer, timestamp_rtp_(0), ntp_time_ms_(0), timestamp_us_(timestamp_us), - rotation_(rotation) {} + rotation_(rotation), + is_repeat_frame_(false) {} VideoFrame::VideoFrame(const scoped_refptr<VideoFrameBuffer>& buffer, uint32_t timestamp_rtp, @@ -281,40 +288,9 @@ VideoFrame::VideoFrame(const scoped_refptr<VideoFrameBuffer>& buffer, timestamp_rtp_(timestamp_rtp), ntp_time_ms_(0), timestamp_us_(render_time_ms * kNumMicrosecsPerMillisec), - rotation_(rotation) { - RTC_DCHECK(buffer); -} - -VideoFrame::VideoFrame(uint16_t id, - const scoped_refptr<VideoFrameBuffer>& buffer, - int64_t timestamp_us, - const std::optional<Timestamp>& presentation_timestamp, - const std::optional<Timestamp>& reference_time, - uint32_t timestamp_rtp, - int64_t ntp_time_ms, - VideoRotation rotation, - const std::optional<ColorSpace>& color_space, - const RenderParameters& render_parameters, - const std::optional<UpdateRect>& update_rect, - RtpPacketInfos packet_infos) - : id_(id), - video_frame_buffer_(buffer), - timestamp_rtp_(timestamp_rtp), - ntp_time_ms_(ntp_time_ms), - timestamp_us_(timestamp_us), - presentation_timestamp_(presentation_timestamp), - reference_time_(reference_time), rotation_(rotation), - color_space_(color_space), - render_parameters_(render_parameters), - update_rect_(update_rect), - packet_infos_(std::move(packet_infos)) { - if (update_rect_) { - RTC_DCHECK_GE(update_rect_->offset_x, 0); - RTC_DCHECK_GE(update_rect_->offset_y, 0); - RTC_DCHECK_LE(update_rect_->offset_x + update_rect_->width, width()); - RTC_DCHECK_LE(update_rect_->offset_y + update_rect_->height, height()); - } + is_repeat_frame_(false) { + RTC_DCHECK(buffer); } VideoFrame::~VideoFrame() = default; diff --git a/third_party/libwebrtc/api/video/video_frame.h b/third_party/libwebrtc/api/video/video_frame.h @@ -124,6 +124,7 @@ class RTC_EXPORT VideoFrame { Builder& set_id(uint16_t id); Builder& set_update_rect(const std::optional<UpdateRect>& update_rect); Builder& set_packet_infos(RtpPacketInfos packet_infos); + Builder& set_is_repeat_frame(bool is_repeat_frame); private: uint16_t id_ = kNotSetId; @@ -138,6 +139,7 @@ class RTC_EXPORT VideoFrame { RenderParameters render_parameters_; std::optional<UpdateRect> update_rect_; RtpPacketInfos packet_infos_; + bool is_repeat_frame_ = false; }; // To be deprecated. Migrate all use to Builder. @@ -283,6 +285,11 @@ class RTC_EXPORT VideoFrame { processing_time_ = processing_time; } + bool is_repeat_frame() const { return is_repeat_frame_; } + void set_is_repeat_frame(bool is_repeat_frame) { + is_repeat_frame_ = is_repeat_frame; + } + private: VideoFrame(uint16_t id, const scoped_refptr<VideoFrameBuffer>& buffer, @@ -295,7 +302,21 @@ class RTC_EXPORT VideoFrame { const std::optional<ColorSpace>& color_space, const RenderParameters& render_parameters, const std::optional<UpdateRect>& update_rect, - RtpPacketInfos packet_infos); + RtpPacketInfos packet_infos, + bool is_repeat_frame) + : id_(id), + video_frame_buffer_(buffer), + timestamp_rtp_(timestamp_rtp), + ntp_time_ms_(ntp_time_ms), + timestamp_us_(timestamp_us), + presentation_timestamp_(presentation_timestamp), + reference_time_(reference_time), + rotation_(rotation), + color_space_(color_space), + render_parameters_(render_parameters), + update_rect_(update_rect), + packet_infos_(std::move(packet_infos)), + is_repeat_frame_(is_repeat_frame) {} uint16_t id_; // An opaque reference counted handle that stores the pixel data. @@ -328,6 +349,11 @@ class RTC_EXPORT VideoFrame { // returned from the decoder. // Currently, not set for locally captured video frames. std::optional<ProcessingTime> processing_time_; + // Indicates if this is a "repeat frame" - i.e. a copy a previous frame, + // inserted in order to make a video codec converge towards a stable quality + // in cases where a capturer is using a variable frame rate and stops + // producing frames when nothing has changed. + bool is_repeat_frame_; }; } // namespace webrtc diff --git a/third_party/libwebrtc/common_video/video_frame_unittest.cc b/third_party/libwebrtc/common_video/video_frame_unittest.cc @@ -643,4 +643,32 @@ TEST(TestUpdateRectScale, CropAndScaleByHalf) { EXPECT_EQ(scaled, VideoFrame::UpdateRect({42, 22, 56, 106})); } +TEST(TestVideoFrame, IsRepeatFrame) { + // Defaults to false. + VideoFrame frame1 = VideoFrame::Builder() + .set_video_frame_buffer(I420Buffer::Create(10, 10)) + .set_rotation(kVideoRotation_0) + .set_timestamp_ms(123) + .build(); + EXPECT_FALSE(frame1.is_repeat_frame()); + + // Set to true. + VideoFrame frame2 = VideoFrame::Builder() + .set_video_frame_buffer(I420Buffer::Create(10, 10)) + .set_rotation(kVideoRotation_0) + .set_timestamp_ms(456) + .set_is_repeat_frame(true) + .build(); + EXPECT_TRUE(frame2.is_repeat_frame()); + + // Set to false. + VideoFrame frame3 = VideoFrame::Builder() + .set_video_frame_buffer(I420Buffer::Create(10, 10)) + .set_rotation(kVideoRotation_0) + .set_timestamp_ms(789) + .set_is_repeat_frame(false) + .build(); + EXPECT_FALSE(frame3.is_repeat_frame()); +} + } // namespace webrtc diff --git a/third_party/libwebrtc/video/frame_cadence_adapter.cc b/third_party/libwebrtc/video/frame_cadence_adapter.cc @@ -691,6 +691,7 @@ void ZeroHertzAdapterMode::ProcessRepeatedFrameOnDelayedCadence(int frame_id) { // Schedule another repeat before sending the frame off which could take time. ScheduleRepeat(frame_id, HasQualityConverged()); + frame.set_is_repeat_frame(true); SendFrameNow(std::nullopt, frame); } diff --git a/third_party/libwebrtc/video/frame_cadence_adapter_unittest.cc b/third_party/libwebrtc/video/frame_cadence_adapter_unittest.cc @@ -338,6 +338,45 @@ TEST(FrameCadenceAdapterTest, RepeatsFramesDelayed) { time_controller.AdvanceTime(TimeDelta::Seconds(1)); } +TEST(FrameCadenceAdapterTest, SetsIsRepeatFrameFlag) { + MockCallback callback; + GlobalSimulatedTimeController time_controller(Timestamp::Millis(47892223)); + FieldTrials no_field_trials = CreateTestFieldTrials(); + auto adapter = CreateAdapter(no_field_trials, time_controller.GetClock()); + adapter->Initialize(&callback); + adapter->SetZeroHertzModeEnabled( + FrameCadenceAdapterInterface::ZeroHertzModeParams{}); + adapter->OnConstraintsChanged( + VideoTrackSourceConstraints{.min_fps = 0, .max_fps = 1}); + + // Send one frame, expect is_repeat_frame to be false. + auto frame = CreateFrameWithTimestamps(&time_controller); + adapter->OnFrame(frame); + EXPECT_CALL(callback, OnFrame) + .WillOnce(Invoke([&](Timestamp, bool, const VideoFrame& frame) { + EXPECT_FALSE(frame.is_repeat_frame()); + })); + time_controller.AdvanceTime(TimeDelta::Seconds(1)); + Mock::VerifyAndClearExpectations(&callback); + + // Expect the repeated frame to have is_repeat_frame set to true. + EXPECT_CALL(callback, OnFrame) + .WillOnce(Invoke([&](Timestamp, bool, const VideoFrame& frame) { + EXPECT_TRUE(frame.is_repeat_frame()); + })); + time_controller.AdvanceTime(TimeDelta::Seconds(1)); + Mock::VerifyAndClearExpectations(&callback); + + // Send a new frame, expect is_repeat_frame to be false again. + auto new_frame = CreateFrameWithTimestamps(&time_controller); + adapter->OnFrame(new_frame); + EXPECT_CALL(callback, OnFrame) + .WillOnce(Invoke([&](Timestamp, bool, const VideoFrame& frame) { + EXPECT_FALSE(frame.is_repeat_frame()); + })); + time_controller.AdvanceTime(TimeDelta::Seconds(1)); +} + TEST(FrameCadenceAdapterTest, RepeatsFramesWithoutTimestampsWithUnsetTimestamps) { // Logic in the frame cadence adapter avoids modifying frame NTP and render