summaryrefslogtreecommitdiffstats
path: root/third_party/libwebrtc/video
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/libwebrtc/video')
-rw-r--r--third_party/libwebrtc/video/BUILD.gn3
-rw-r--r--third_party/libwebrtc/video/adaptation/video_adaptation_gn/moz.build5
-rw-r--r--third_party/libwebrtc/video/config/encoder_config_gn/moz.build5
-rw-r--r--third_party/libwebrtc/video/config/streams_config_gn/moz.build5
-rw-r--r--third_party/libwebrtc/video/decode_synchronizer_gn/moz.build5
-rw-r--r--third_party/libwebrtc/video/end_to_end_tests/multi_stream_tester.cc18
-rw-r--r--third_party/libwebrtc/video/end_to_end_tests/network_state_tests.cc2
-rw-r--r--third_party/libwebrtc/video/end_to_end_tests/stats_tests.cc8
-rw-r--r--third_party/libwebrtc/video/frame_cadence_adapter.cc154
-rw-r--r--third_party/libwebrtc/video/frame_cadence_adapter.h17
-rw-r--r--third_party/libwebrtc/video/frame_cadence_adapter_gn/moz.build5
-rw-r--r--third_party/libwebrtc/video/frame_cadence_adapter_unittest.cc145
-rw-r--r--third_party/libwebrtc/video/frame_decode_scheduler_gn/moz.build7
-rw-r--r--third_party/libwebrtc/video/frame_decode_timing_gn/moz.build5
-rw-r--r--third_party/libwebrtc/video/frame_dumping_decoder_gn/moz.build5
-rw-r--r--third_party/libwebrtc/video/frame_dumping_encoder_gn/moz.build5
-rw-r--r--third_party/libwebrtc/video/render/incoming_video_stream_gn/moz.build5
-rw-r--r--third_party/libwebrtc/video/render/video_render_frames_gn/moz.build5
-rw-r--r--third_party/libwebrtc/video/send_statistics_proxy.cc7
-rw-r--r--third_party/libwebrtc/video/task_queue_frame_decode_scheduler_gn/moz.build5
-rw-r--r--third_party/libwebrtc/video/unique_timestamp_counter_gn/moz.build5
-rw-r--r--third_party/libwebrtc/video/video_gn/moz.build5
-rw-r--r--third_party/libwebrtc/video/video_quality_test.cc51
-rw-r--r--third_party/libwebrtc/video/video_receive_stream2.cc21
-rw-r--r--third_party/libwebrtc/video/video_receive_stream_timeout_tracker_gn/moz.build5
-rw-r--r--third_party/libwebrtc/video/video_stream_buffer_controller_gn/moz.build5
-rw-r--r--third_party/libwebrtc/video/video_stream_encoder.cc115
-rw-r--r--third_party/libwebrtc/video/video_stream_encoder.h69
-rw-r--r--third_party/libwebrtc/video/video_stream_encoder_impl_gn/moz.build5
-rw-r--r--third_party/libwebrtc/video/video_stream_encoder_interface_gn/moz.build7
-rw-r--r--third_party/libwebrtc/video/video_stream_encoder_observer.h1
-rw-r--r--third_party/libwebrtc/video/video_stream_encoder_unittest.cc64
32 files changed, 463 insertions, 306 deletions
diff --git a/third_party/libwebrtc/video/BUILD.gn b/third_party/libwebrtc/video/BUILD.gn
index e84b73a352..0a930053c0 100644
--- a/third_party/libwebrtc/video/BUILD.gn
+++ b/third_party/libwebrtc/video/BUILD.gn
@@ -836,6 +836,8 @@ if (rtc_include_tests) {
"../api:transport_api",
"../api/adaptation:resource_adaptation_api",
"../api/crypto:options",
+ "../api/environment",
+ "../api/environment:environment_factory",
"../api/metronome/test:fake_metronome",
"../api/rtc_event_log",
"../api/task_queue",
@@ -843,7 +845,6 @@ if (rtc_include_tests) {
"../api/test/metrics:global_metrics_logger_and_exporter",
"../api/test/metrics:metric",
"../api/test/video:function_video_factory",
- "../api/transport:field_trial_based_config",
"../api/units:data_rate",
"../api/units:frequency",
"../api/units:time_delta",
diff --git a/third_party/libwebrtc/video/adaptation/video_adaptation_gn/moz.build b/third_party/libwebrtc/video/adaptation/video_adaptation_gn/moz.build
index 2d1fd69ed0..18d29da556 100644
--- a/third_party/libwebrtc/video/adaptation/video_adaptation_gn/moz.build
+++ b/third_party/libwebrtc/video/adaptation/video_adaptation_gn/moz.build
@@ -209,7 +209,6 @@ if CONFIG["MOZ_X11"] == "1" and CONFIG["OS_TARGET"] == "Linux":
if CONFIG["OS_TARGET"] == "Android" and CONFIG["TARGET_CPU"] == "arm":
OS_LIBS += [
- "android_support",
"unwind"
]
@@ -219,10 +218,6 @@ if CONFIG["OS_TARGET"] == "Android" and CONFIG["TARGET_CPU"] == "x86":
"-msse2"
]
- OS_LIBS += [
- "android_support"
- ]
-
if CONFIG["OS_TARGET"] == "Linux" and CONFIG["TARGET_CPU"] == "aarch64":
DEFINES["_GNU_SOURCE"] = True
diff --git a/third_party/libwebrtc/video/config/encoder_config_gn/moz.build b/third_party/libwebrtc/video/config/encoder_config_gn/moz.build
index 1c2c9ef835..4dbe7bf32c 100644
--- a/third_party/libwebrtc/video/config/encoder_config_gn/moz.build
+++ b/third_party/libwebrtc/video/config/encoder_config_gn/moz.build
@@ -195,7 +195,6 @@ if CONFIG["MOZ_X11"] == "1" and CONFIG["OS_TARGET"] == "Linux":
if CONFIG["OS_TARGET"] == "Android" and CONFIG["TARGET_CPU"] == "arm":
OS_LIBS += [
- "android_support",
"unwind"
]
@@ -205,10 +204,6 @@ if CONFIG["OS_TARGET"] == "Android" and CONFIG["TARGET_CPU"] == "x86":
"-msse2"
]
- OS_LIBS += [
- "android_support"
- ]
-
if CONFIG["OS_TARGET"] == "Linux" and CONFIG["TARGET_CPU"] == "aarch64":
DEFINES["_GNU_SOURCE"] = True
diff --git a/third_party/libwebrtc/video/config/streams_config_gn/moz.build b/third_party/libwebrtc/video/config/streams_config_gn/moz.build
index e2d2f9963d..c34883fb37 100644
--- a/third_party/libwebrtc/video/config/streams_config_gn/moz.build
+++ b/third_party/libwebrtc/video/config/streams_config_gn/moz.build
@@ -201,7 +201,6 @@ if CONFIG["MOZ_X11"] == "1" and CONFIG["OS_TARGET"] == "Linux":
if CONFIG["OS_TARGET"] == "Android" and CONFIG["TARGET_CPU"] == "arm":
OS_LIBS += [
- "android_support",
"unwind"
]
@@ -211,10 +210,6 @@ if CONFIG["OS_TARGET"] == "Android" and CONFIG["TARGET_CPU"] == "x86":
"-msse2"
]
- OS_LIBS += [
- "android_support"
- ]
-
if CONFIG["OS_TARGET"] == "Linux" and CONFIG["TARGET_CPU"] == "aarch64":
DEFINES["_GNU_SOURCE"] = True
diff --git a/third_party/libwebrtc/video/decode_synchronizer_gn/moz.build b/third_party/libwebrtc/video/decode_synchronizer_gn/moz.build
index d0e4adeda2..0aff4a854c 100644
--- a/third_party/libwebrtc/video/decode_synchronizer_gn/moz.build
+++ b/third_party/libwebrtc/video/decode_synchronizer_gn/moz.build
@@ -199,7 +199,6 @@ if CONFIG["MOZ_X11"] == "1" and CONFIG["OS_TARGET"] == "Linux":
if CONFIG["OS_TARGET"] == "Android" and CONFIG["TARGET_CPU"] == "arm":
OS_LIBS += [
- "android_support",
"unwind"
]
@@ -209,10 +208,6 @@ if CONFIG["OS_TARGET"] == "Android" and CONFIG["TARGET_CPU"] == "x86":
"-msse2"
]
- OS_LIBS += [
- "android_support"
- ]
-
if CONFIG["OS_TARGET"] == "Linux" and CONFIG["TARGET_CPU"] == "aarch64":
DEFINES["_GNU_SOURCE"] = True
diff --git a/third_party/libwebrtc/video/end_to_end_tests/multi_stream_tester.cc b/third_party/libwebrtc/video/end_to_end_tests/multi_stream_tester.cc
index 1eb388cc76..759b75ccf9 100644
--- a/third_party/libwebrtc/video/end_to_end_tests/multi_stream_tester.cc
+++ b/third_party/libwebrtc/video/end_to_end_tests/multi_stream_tester.cc
@@ -14,8 +14,8 @@
#include <utility>
#include <vector>
-#include "api/rtc_event_log/rtc_event_log.h"
-#include "api/task_queue/default_task_queue_factory.h"
+#include "api/environment/environment.h"
+#include "api/environment/environment_factory.h"
#include "api/task_queue/task_queue_base.h"
#include "api/test/create_frame_generator.h"
#include "api/test/simulated_network.h"
@@ -42,17 +42,13 @@ MultiStreamTester::MultiStreamTester() {
MultiStreamTester::~MultiStreamTester() = default;
void MultiStreamTester::RunTest() {
- webrtc::RtcEventLogNull event_log;
- auto task_queue_factory = CreateDefaultTaskQueueFactory();
+ Environment env = CreateEnvironment();
// Use high prioirity since this task_queue used for fake network delivering
// at correct time. Those test tasks should be prefered over code under test
// to make test more stable.
- auto task_queue = task_queue_factory->CreateTaskQueue(
+ auto task_queue = env.task_queue_factory().CreateTaskQueue(
"TaskQueue", TaskQueueFactory::Priority::HIGH);
- CallConfig config(&event_log);
- test::ScopedKeyValueConfig field_trials;
- config.trials = &field_trials;
- config.task_queue_factory = task_queue_factory.get();
+ CallConfig config(env);
std::unique_ptr<Call> sender_call;
std::unique_ptr<Call> receiver_call;
std::unique_ptr<test::DirectTransport> sender_transport;
@@ -115,10 +111,10 @@ void MultiStreamTester::RunTest() {
receive_streams[i]->Start();
auto* frame_generator = new test::FrameGeneratorCapturer(
- Clock::GetRealTimeClock(),
+ &env.clock(),
test::CreateSquareFrameGenerator(width, height, absl::nullopt,
absl::nullopt),
- 30, *task_queue_factory);
+ 30, env.task_queue_factory());
frame_generators[i] = frame_generator;
send_streams[i]->SetSource(frame_generator,
DegradationPreference::MAINTAIN_FRAMERATE);
diff --git a/third_party/libwebrtc/video/end_to_end_tests/network_state_tests.cc b/third_party/libwebrtc/video/end_to_end_tests/network_state_tests.cc
index 7bc9f1493e..7e9c86362a 100644
--- a/third_party/libwebrtc/video/end_to_end_tests/network_state_tests.cc
+++ b/third_party/libwebrtc/video/end_to_end_tests/network_state_tests.cc
@@ -94,7 +94,7 @@ void NetworkStateEndToEndTest::VerifyNewVideoSendStreamsRespectNetworkState(
SendTask(task_queue(), [this, network_to_bring_up, &encoder_factory,
transport]() {
- CreateSenderCall(CallConfig(send_event_log_.get()));
+ CreateSenderCall();
sender_call_->SignalChannelNetworkState(network_to_bring_up, kNetworkUp);
CreateSendConfig(1, 0, 0, transport);
diff --git a/third_party/libwebrtc/video/end_to_end_tests/stats_tests.cc b/third_party/libwebrtc/video/end_to_end_tests/stats_tests.cc
index cc0b328b2b..d6820eeac2 100644
--- a/third_party/libwebrtc/video/end_to_end_tests/stats_tests.cc
+++ b/third_party/libwebrtc/video/end_to_end_tests/stats_tests.cc
@@ -518,9 +518,9 @@ TEST_F(StatsEndToEndTest, MAYBE_ContentTypeSwitches) {
metrics::Reset();
- CallConfig send_config(send_event_log_.get());
+ CallConfig send_config = SendCallConfig();
test.ModifySenderBitrateConfig(&send_config.bitrate_config);
- CallConfig recv_config(recv_event_log_.get());
+ CallConfig recv_config = RecvCallConfig();
test.ModifyReceiverBitrateConfig(&recv_config.bitrate_config);
VideoEncoderConfig encoder_config_with_screenshare;
@@ -732,13 +732,13 @@ TEST_F(StatsEndToEndTest, CallReportsRttForSender) {
Start();
});
- int64_t start_time_ms = clock_->TimeInMilliseconds();
+ int64_t start_time_ms = env().clock().TimeInMilliseconds();
while (true) {
Call::Stats stats;
SendTask(task_queue(),
[this, &stats]() { stats = sender_call_->GetStats(); });
ASSERT_GE(start_time_ms + test::VideoTestConstants::kDefaultTimeout.ms(),
- clock_->TimeInMilliseconds())
+ env().clock().TimeInMilliseconds())
<< "No RTT stats before timeout!";
if (stats.rtt_ms != -1) {
// To avoid failures caused by rounding or minor ntp clock adjustments,
diff --git a/third_party/libwebrtc/video/frame_cadence_adapter.cc b/third_party/libwebrtc/video/frame_cadence_adapter.cc
index b09986847b..2c4acdd6c2 100644
--- a/third_party/libwebrtc/video/frame_cadence_adapter.cc
+++ b/third_party/libwebrtc/video/frame_cadence_adapter.cc
@@ -50,7 +50,7 @@ class AdapterMode {
// Called on the worker thread for every frame that enters.
virtual void OnFrame(Timestamp post_time,
- int frames_scheduled_for_processing,
+ bool queue_overload,
const VideoFrame& frame) = 0;
// Returns the currently estimated input framerate.
@@ -71,10 +71,10 @@ class PassthroughAdapterMode : public AdapterMode {
// Adapter overrides.
void OnFrame(Timestamp post_time,
- int frames_scheduled_for_processing,
+ bool queue_overload,
const VideoFrame& frame) override {
RTC_DCHECK_RUN_ON(&sequence_checker_);
- callback_->OnFrame(post_time, frames_scheduled_for_processing, frame);
+ callback_->OnFrame(post_time, queue_overload, frame);
}
absl::optional<uint32_t> GetInputFrameRateFps() override {
@@ -119,7 +119,7 @@ class ZeroHertzAdapterMode : public AdapterMode {
// Adapter overrides.
void OnFrame(Timestamp post_time,
- int frames_scheduled_for_processing,
+ bool queue_overload,
const VideoFrame& frame) override;
absl::optional<uint32_t> GetInputFrameRateFps() override;
void UpdateFrameRate() override {}
@@ -131,6 +131,10 @@ class ZeroHertzAdapterMode : public AdapterMode {
// Callback::RequestRefreshFrame.
void ProcessKeyFrameRequest();
+ // Updates the restrictions of max frame rate for the video source.
+ // Always called during construction using latest `restricted_frame_delay_`.
+ void UpdateVideoSourceRestrictions(absl::optional<double> max_frame_rate);
+
private:
// The tracking state of each spatial layer. Used for determining when to
// stop repeating frames.
@@ -171,20 +175,22 @@ class ZeroHertzAdapterMode : public AdapterMode {
// after this call.
void ResetQualityConvergenceInfo() RTC_RUN_ON(sequence_checker_);
// Processes incoming frames on a delayed cadence.
- void ProcessOnDelayedCadence() RTC_RUN_ON(sequence_checker_);
- // Schedules a later repeat with delay depending on state of layer trackers.
+ void ProcessOnDelayedCadence(Timestamp post_time)
+ RTC_RUN_ON(sequence_checker_);
+ // Schedules a later repeat with delay depending on state of layer trackers
+ // and if UpdateVideoSourceRestrictions has been called or not.
// If true is passed in `idle_repeat`, the repeat is going to be
- // kZeroHertzIdleRepeatRatePeriod. Otherwise it'll be the value of
- // `frame_delay`.
+ // kZeroHertzIdleRepeatRatePeriod. Otherwise it'll be the maximum value of
+ // `frame_delay` or `restricted_frame_delay_` if it has been set.
void ScheduleRepeat(int frame_id, bool idle_repeat)
RTC_RUN_ON(sequence_checker_);
- // Repeats a frame in the abscence of incoming frames. Slows down when quality
+ // Repeats a frame in the absence of incoming frames. Slows down when quality
// convergence is attained, and stops the cadence terminally when new frames
// have arrived.
void ProcessRepeatedFrameOnDelayedCadence(int frame_id)
RTC_RUN_ON(sequence_checker_);
// Sends a frame, updating the timestamp to the current time.
- void SendFrameNow(const VideoFrame& frame) const
+ void SendFrameNow(Timestamp post_time, const VideoFrame& frame) const
RTC_RUN_ON(sequence_checker_);
// Returns the repeat duration depending on if it's an idle repeat or not.
TimeDelta RepeatDuration(bool idle_repeat) const
@@ -220,6 +226,10 @@ class ZeroHertzAdapterMode : public AdapterMode {
// they can be dropped in various places in the capture pipeline.
RepeatingTaskHandle refresh_frame_requester_
RTC_GUARDED_BY(sequence_checker_);
+ // Can be set by UpdateVideoSourceRestrictions when the video source restricts
+ // the max frame rate.
+ absl::optional<TimeDelta> restricted_frame_delay_
+ RTC_GUARDED_BY(sequence_checker_);
ScopedTaskSafety safety_;
};
@@ -240,6 +250,8 @@ class FrameCadenceAdapterImpl : public FrameCadenceAdapterInterface {
void UpdateLayerQualityConvergence(size_t spatial_index,
bool quality_converged) override;
void UpdateLayerStatus(size_t spatial_index, bool enabled) override;
+ void UpdateVideoSourceRestrictions(
+ absl::optional<double> max_frame_rate) override;
void ProcessKeyFrameRequest() override;
// VideoFrameSink overrides.
@@ -249,9 +261,9 @@ class FrameCadenceAdapterImpl : public FrameCadenceAdapterInterface {
const VideoTrackSourceConstraints& constraints) override;
private:
- // Called from OnFrame in zero-hertz mode.
+ // Called from OnFrame in both pass-through and zero-hertz mode.
void OnFrameOnMainQueue(Timestamp post_time,
- int frames_scheduled_for_processing,
+ bool queue_overload,
const VideoFrame& frame) RTC_RUN_ON(queue_);
// Returns true under all of the following conditions:
@@ -276,6 +288,7 @@ class FrameCadenceAdapterImpl : public FrameCadenceAdapterInterface {
absl::optional<ZeroHertzAdapterMode> zero_hertz_adapter_;
// If set, zero-hertz mode has been enabled.
absl::optional<ZeroHertzModeParams> zero_hertz_params_;
+ std::atomic<bool> zero_hertz_adapter_is_active_{false};
// Cache for the current adapter mode.
AdapterMode* current_adapter_mode_ = nullptr;
@@ -290,10 +303,14 @@ class FrameCadenceAdapterImpl : public FrameCadenceAdapterInterface {
absl::optional<VideoTrackSourceConstraints> source_constraints_
RTC_GUARDED_BY(queue_);
+ // Stores the latest restriction in max frame rate set by
+ // UpdateVideoSourceRestrictions. Ensures that a previously set restriction
+ // can be maintained during reconstructions of the adapter.
+ absl::optional<double> restricted_max_frame_rate_ RTC_GUARDED_BY(queue_);
+
// Race checker for incoming frames. This is the network thread in chromium,
// but may vary from test contexts.
rtc::RaceChecker incoming_frame_race_checker_;
- bool has_reported_screenshare_frame_rate_umas_ RTC_GUARDED_BY(queue_) = false;
// Number of frames that are currently scheduled for processing on the
// `queue_`.
@@ -355,7 +372,7 @@ void ZeroHertzAdapterMode::UpdateLayerStatus(size_t spatial_index,
}
void ZeroHertzAdapterMode::OnFrame(Timestamp post_time,
- int frames_scheduled_for_processing,
+ bool queue_overload,
const VideoFrame& frame) {
RTC_DCHECK_RUN_ON(&sequence_checker_);
TRACE_EVENT0("webrtc", "ZeroHertzAdapterMode::OnFrame");
@@ -382,7 +399,7 @@ void ZeroHertzAdapterMode::OnFrame(Timestamp post_time,
frame_id);
queue_->PostDelayedHighPrecisionTask(
SafeTask(safety_.flag(),
- [this, frame_id, frame] {
+ [this, post_time, frame_id, frame] {
RTC_UNUSED(frame_id);
RTC_DCHECK_RUN_ON(&sequence_checker_);
TRACE_EVENT_ASYNC_END0(TRACE_DISABLED_BY_DEFAULT("webrtc"),
@@ -390,7 +407,7 @@ void ZeroHertzAdapterMode::OnFrame(Timestamp post_time,
TRACE_EVENT_ASYNC_END0(TRACE_DISABLED_BY_DEFAULT("webrtc"),
"OnFrameToEncode",
frame.video_frame_buffer().get());
- ProcessOnDelayedCadence();
+ ProcessOnDelayedCadence(post_time);
}),
std::max(frame_delay_ - time_spent_since_post, TimeDelta::Zero()));
}
@@ -411,6 +428,20 @@ absl::optional<uint32_t> ZeroHertzAdapterMode::GetInputFrameRateFps() {
return max_fps_;
}
+void ZeroHertzAdapterMode::UpdateVideoSourceRestrictions(
+ absl::optional<double> max_frame_rate) {
+ RTC_DCHECK_RUN_ON(&sequence_checker_);
+ TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("webrtc"), __func__,
+ "max_frame_rate", max_frame_rate.value_or(-1));
+ if (max_frame_rate.value_or(0) > 0) {
+ // Set new, validated (> 0) and restricted frame rate.
+ restricted_frame_delay_ = TimeDelta::Seconds(1) / *max_frame_rate;
+ } else {
+ // Source reports that the frame rate is now unrestricted.
+ restricted_frame_delay_ = absl::nullopt;
+ }
+}
+
void ZeroHertzAdapterMode::ProcessKeyFrameRequest() {
RTC_DCHECK_RUN_ON(&sequence_checker_);
TRACE_EVENT_INSTANT0("webrtc", __func__);
@@ -475,13 +506,13 @@ void ZeroHertzAdapterMode::ResetQualityConvergenceInfo() {
}
}
-void ZeroHertzAdapterMode::ProcessOnDelayedCadence() {
+void ZeroHertzAdapterMode::ProcessOnDelayedCadence(Timestamp post_time) {
RTC_DCHECK_RUN_ON(&sequence_checker_);
RTC_DCHECK(!queued_frames_.empty());
TRACE_EVENT0("webrtc", __func__);
// Avoid sending the front frame for encoding (which could take a long time)
- // until we schedule a repeate.
+ // until we schedule a repeat.
VideoFrame front_frame = queued_frames_.front();
// If there were two or more frames stored, we do not have to schedule repeats
@@ -494,7 +525,7 @@ void ZeroHertzAdapterMode::ProcessOnDelayedCadence() {
// arrive.
ScheduleRepeat(current_frame_id_, HasQualityConverged());
}
- SendFrameNow(front_frame);
+ SendFrameNow(post_time, front_frame);
}
void ZeroHertzAdapterMode::ScheduleRepeat(int frame_id, bool idle_repeat) {
@@ -551,23 +582,36 @@ void ZeroHertzAdapterMode::ProcessRepeatedFrameOnDelayedCadence(int frame_id) {
// Schedule another repeat before sending the frame off which could take time.
ScheduleRepeat(frame_id, HasQualityConverged());
- SendFrameNow(frame);
+ // Mark `post_time` with 0 to signal that this is a repeated frame.
+ SendFrameNow(Timestamp::Zero(), frame);
}
-void ZeroHertzAdapterMode::SendFrameNow(const VideoFrame& frame) const {
+void ZeroHertzAdapterMode::SendFrameNow(Timestamp post_time,
+ const VideoFrame& frame) const {
RTC_DCHECK_RUN_ON(&sequence_checker_);
TRACE_EVENT0("webrtc", __func__);
- // TODO(crbug.com/1255737): figure out if frames_scheduled_for_processing
- // makes sense to compute in this implementation.
- callback_->OnFrame(/*post_time=*/clock_->CurrentTime(),
- /*frames_scheduled_for_processing=*/1, frame);
+ Timestamp now = clock_->CurrentTime();
+ // Exclude repeated frames which are marked with zero as post time.
+ if (post_time != Timestamp::Zero()) {
+ TimeDelta delay = (now - post_time);
+ RTC_HISTOGRAM_COUNTS_10000("WebRTC.Screenshare.ZeroHz.DelayMs", delay.ms());
+ }
+ // TODO(crbug.com/1255737): ensure queue_overload is computed from current
+ // conditions on the encoder queue.
+ callback_->OnFrame(/*post_time=*/now,
+ /*queue_overload=*/false, frame);
}
TimeDelta ZeroHertzAdapterMode::RepeatDuration(bool idle_repeat) const {
RTC_DCHECK_RUN_ON(&sequence_checker_);
+ // By default use `frame_delay_` in non-idle repeat mode but use the
+ // restricted frame delay instead if it is set in
+ // UpdateVideoSourceRestrictions.
+ TimeDelta frame_delay =
+ std::max(frame_delay_, restricted_frame_delay_.value_or(frame_delay_));
return idle_repeat
? FrameCadenceAdapterInterface::kZeroHertzIdleRepeatRatePeriod
- : frame_delay_;
+ : frame_delay;
}
void ZeroHertzAdapterMode::MaybeStartRefreshFrameRequester() {
@@ -609,8 +653,6 @@ void FrameCadenceAdapterImpl::SetZeroHertzModeEnabled(
absl::optional<ZeroHertzModeParams> params) {
RTC_DCHECK_RUN_ON(queue_);
bool was_zero_hertz_enabled = zero_hertz_params_.has_value();
- if (params.has_value() && !was_zero_hertz_enabled)
- has_reported_screenshare_frame_rate_umas_ = false;
zero_hertz_params_ = params;
MaybeReconfigureAdapters(was_zero_hertz_enabled);
}
@@ -642,6 +684,17 @@ void FrameCadenceAdapterImpl::UpdateLayerStatus(size_t spatial_index,
zero_hertz_adapter_->UpdateLayerStatus(spatial_index, enabled);
}
+void FrameCadenceAdapterImpl::UpdateVideoSourceRestrictions(
+ absl::optional<double> max_frame_rate) {
+ RTC_DCHECK_RUN_ON(queue_);
+ // Store the restriction to ensure that it can be reapplied in possible
+ // future adapter creations on configuration changes.
+ restricted_max_frame_rate_ = max_frame_rate;
+ if (zero_hertz_adapter_) {
+ zero_hertz_adapter_->UpdateVideoSourceRestrictions(max_frame_rate);
+ }
+}
+
void FrameCadenceAdapterImpl::ProcessKeyFrameRequest() {
RTC_DCHECK_RUN_ON(queue_);
if (zero_hertz_adapter_)
@@ -657,14 +710,21 @@ void FrameCadenceAdapterImpl::OnFrame(const VideoFrame& frame) {
// Local time in webrtc time base.
Timestamp post_time = clock_->CurrentTime();
frames_scheduled_for_processing_.fetch_add(1, std::memory_order_relaxed);
- TRACE_EVENT_ASYNC_BEGIN0(TRACE_DISABLED_BY_DEFAULT("webrtc"),
- "OnFrameToEncode", frame.video_frame_buffer().get());
- TRACE_EVENT_ASYNC_BEGIN0(TRACE_DISABLED_BY_DEFAULT("webrtc"),
- "OnFrameToQueue", frame.video_frame_buffer().get());
+ if (zero_hertz_adapter_is_active_.load(std::memory_order_relaxed)) {
+ TRACE_EVENT_ASYNC_BEGIN0(TRACE_DISABLED_BY_DEFAULT("webrtc"),
+ "OnFrameToEncode",
+ frame.video_frame_buffer().get());
+ TRACE_EVENT_ASYNC_BEGIN0(TRACE_DISABLED_BY_DEFAULT("webrtc"),
+ "OnFrameToQueue",
+ frame.video_frame_buffer().get());
+ }
queue_->PostTask(SafeTask(safety_.flag(), [this, post_time, frame] {
RTC_DCHECK_RUN_ON(queue_);
- TRACE_EVENT_ASYNC_END0(TRACE_DISABLED_BY_DEFAULT("webrtc"),
- "OnFrameToQueue", frame.video_frame_buffer().get());
+ if (zero_hertz_adapter_is_active_.load(std::memory_order_relaxed)) {
+ TRACE_EVENT_ASYNC_END0(TRACE_DISABLED_BY_DEFAULT("webrtc"),
+ "OnFrameToQueue",
+ frame.video_frame_buffer().get());
+ }
if (zero_hertz_adapter_created_timestamp_.has_value()) {
TimeDelta time_until_first_frame =
clock_->CurrentTime() - *zero_hertz_adapter_created_timestamp_;
@@ -677,7 +737,7 @@ void FrameCadenceAdapterImpl::OnFrame(const VideoFrame& frame) {
const int frames_scheduled_for_processing =
frames_scheduled_for_processing_.fetch_sub(1,
std::memory_order_relaxed);
- OnFrameOnMainQueue(post_time, frames_scheduled_for_processing,
+ OnFrameOnMainQueue(post_time, frames_scheduled_for_processing > 1,
std::move(frame));
}));
}
@@ -705,13 +765,11 @@ void FrameCadenceAdapterImpl::OnConstraintsChanged(
}));
}
-void FrameCadenceAdapterImpl::OnFrameOnMainQueue(
- Timestamp post_time,
- int frames_scheduled_for_processing,
- const VideoFrame& frame) {
+void FrameCadenceAdapterImpl::OnFrameOnMainQueue(Timestamp post_time,
+ bool queue_overload,
+ const VideoFrame& frame) {
RTC_DCHECK_RUN_ON(queue_);
- current_adapter_mode_->OnFrame(post_time, frames_scheduled_for_processing,
- frame);
+ current_adapter_mode_->OnFrame(post_time, queue_overload, frame);
}
bool FrameCadenceAdapterImpl::IsZeroHertzScreenshareEnabled() const {
@@ -727,17 +785,25 @@ void FrameCadenceAdapterImpl::MaybeReconfigureAdapters(
RTC_DCHECK_RUN_ON(queue_);
bool is_zero_hertz_enabled = IsZeroHertzScreenshareEnabled();
if (is_zero_hertz_enabled) {
- if (!was_zero_hertz_enabled) {
+ bool max_fps_has_changed = GetInputFrameRateFps().value_or(-1) !=
+ source_constraints_->max_fps.value_or(-1);
+ if (!was_zero_hertz_enabled || max_fps_has_changed) {
+ RTC_LOG(LS_INFO) << "Zero hertz mode enabled (max_fps="
+ << source_constraints_->max_fps.value() << ")";
zero_hertz_adapter_.emplace(queue_, clock_, callback_,
source_constraints_->max_fps.value());
- RTC_LOG(LS_INFO) << "Zero hertz mode activated.";
+ zero_hertz_adapter_->UpdateVideoSourceRestrictions(
+ restricted_max_frame_rate_);
zero_hertz_adapter_created_timestamp_ = clock_->CurrentTime();
}
zero_hertz_adapter_->ReconfigureParameters(zero_hertz_params_.value());
current_adapter_mode_ = &zero_hertz_adapter_.value();
} else {
- if (was_zero_hertz_enabled)
+ if (was_zero_hertz_enabled) {
zero_hertz_adapter_ = absl::nullopt;
+ zero_hertz_adapter_is_active_.store(false, std::memory_order_relaxed);
+ RTC_LOG(LS_INFO) << "Zero hertz mode disabled.";
+ }
current_adapter_mode_ = &passthrough_adapter_.value();
}
}
diff --git a/third_party/libwebrtc/video/frame_cadence_adapter.h b/third_party/libwebrtc/video/frame_cadence_adapter.h
index d0eab7e770..2b62bb26cd 100644
--- a/third_party/libwebrtc/video/frame_cadence_adapter.h
+++ b/third_party/libwebrtc/video/frame_cadence_adapter.h
@@ -60,14 +60,11 @@ class FrameCadenceAdapterInterface
// The |post_time| parameter indicates the current time sampled when
// FrameCadenceAdapterInterface::OnFrame was called.
//
- // |frames_scheduled_for_processing| indicates how many frames that have
- // been scheduled for processing. During sequential conditions where
- // FrameCadenceAdapterInterface::OnFrame is invoked and subsequently ending
- // up in this callback, this value will read 1. Otherwise if the
- // |queue| gets stalled for some reason, the value will increase
- // beyond 1.
+ // |queue_overload| is true if the frame cadence adapter notices it's
+ // not able to deliver the incoming |frame| to the |queue| in the expected
+ // time.
virtual void OnFrame(Timestamp post_time,
- int frames_scheduled_for_processing,
+ bool queue_overload,
const VideoFrame& frame) = 0;
// Called when the source has discarded a frame.
@@ -112,6 +109,12 @@ class FrameCadenceAdapterInterface
// Updates spatial layer enabled status.
virtual void UpdateLayerStatus(size_t spatial_index, bool enabled) = 0;
+ // Updates the restrictions of max frame rate for the video source.
+ // The new `max_frame_rate` will only affect the cadence of Callback::OnFrame
+ // for non-idle (non converged) repeated frames.
+ virtual void UpdateVideoSourceRestrictions(
+ absl::optional<double> max_frame_rate) = 0;
+
// Conditionally requests a refresh frame via
// Callback::RequestRefreshFrame.
virtual void ProcessKeyFrameRequest() = 0;
diff --git a/third_party/libwebrtc/video/frame_cadence_adapter_gn/moz.build b/third_party/libwebrtc/video/frame_cadence_adapter_gn/moz.build
index 51ec86b2cf..a860d550ad 100644
--- a/third_party/libwebrtc/video/frame_cadence_adapter_gn/moz.build
+++ b/third_party/libwebrtc/video/frame_cadence_adapter_gn/moz.build
@@ -199,7 +199,6 @@ if CONFIG["MOZ_X11"] == "1" and CONFIG["OS_TARGET"] == "Linux":
if CONFIG["OS_TARGET"] == "Android" and CONFIG["TARGET_CPU"] == "arm":
OS_LIBS += [
- "android_support",
"unwind"
]
@@ -209,10 +208,6 @@ if CONFIG["OS_TARGET"] == "Android" and CONFIG["TARGET_CPU"] == "x86":
"-msse2"
]
- OS_LIBS += [
- "android_support"
- ]
-
if CONFIG["OS_TARGET"] == "Linux" and CONFIG["TARGET_CPU"] == "aarch64":
DEFINES["_GNU_SOURCE"] = True
diff --git a/third_party/libwebrtc/video/frame_cadence_adapter_unittest.cc b/third_party/libwebrtc/video/frame_cadence_adapter_unittest.cc
index 052b0a6c61..0fef2400f0 100644
--- a/third_party/libwebrtc/video/frame_cadence_adapter_unittest.cc
+++ b/third_party/libwebrtc/video/frame_cadence_adapter_unittest.cc
@@ -70,7 +70,7 @@ std::unique_ptr<FrameCadenceAdapterInterface> CreateAdapter(
class MockCallback : public FrameCadenceAdapterInterface::Callback {
public:
- MOCK_METHOD(void, OnFrame, (Timestamp, int, const VideoFrame&), (override));
+ MOCK_METHOD(void, OnFrame, (Timestamp, bool, const VideoFrame&), (override));
MOCK_METHOD(void, OnDiscardedFrame, (), (override));
MOCK_METHOD(void, RequestRefreshFrame, (), (override));
};
@@ -115,13 +115,13 @@ TEST(FrameCadenceAdapterTest, CountsOutstandingFramesToProcess) {
MockCallback callback;
auto adapter = CreateAdapter(no_field_trials, time_controller.GetClock());
adapter->Initialize(&callback);
- EXPECT_CALL(callback, OnFrame(_, 2, _)).Times(1);
- EXPECT_CALL(callback, OnFrame(_, 1, _)).Times(1);
+ EXPECT_CALL(callback, OnFrame(_, true, _)).Times(1);
+ EXPECT_CALL(callback, OnFrame(_, false, _)).Times(1);
auto frame = CreateFrame();
adapter->OnFrame(frame);
adapter->OnFrame(frame);
time_controller.AdvanceTime(TimeDelta::Zero());
- EXPECT_CALL(callback, OnFrame(_, 1, _)).Times(1);
+ EXPECT_CALL(callback, OnFrame(_, false, _)).Times(1);
adapter->OnFrame(frame);
time_controller.AdvanceTime(TimeDelta::Zero());
}
@@ -184,6 +184,29 @@ TEST(FrameCadenceAdapterTest, FrameRateFollowsMaxFpsWhenZeroHertzActivated) {
}
}
+TEST(FrameCadenceAdapterTest, ZeroHertzAdapterSupportsMaxFpsChange) {
+ ZeroHertzFieldTrialEnabler enabler;
+ GlobalSimulatedTimeController time_controller(Timestamp::Zero());
+ auto adapter = CreateAdapter(enabler, time_controller.GetClock());
+ MockCallback callback;
+ adapter->Initialize(&callback);
+ adapter->SetZeroHertzModeEnabled(
+ FrameCadenceAdapterInterface::ZeroHertzModeParams{});
+ adapter->OnConstraintsChanged(VideoTrackSourceConstraints{0, 1});
+ time_controller.AdvanceTime(TimeDelta::Zero());
+ EXPECT_EQ(adapter->GetInputFrameRateFps(), 1u);
+ adapter->OnFrame(CreateFrame());
+ time_controller.AdvanceTime(TimeDelta::Seconds(1));
+ adapter->OnConstraintsChanged(VideoTrackSourceConstraints{0, 2});
+ time_controller.AdvanceTime(TimeDelta::Zero());
+ EXPECT_EQ(adapter->GetInputFrameRateFps(), 2u);
+ adapter->OnFrame(CreateFrame());
+ // Ensure that the max_fps has been changed from 1 to 2 fps even if it was
+ // changed while zero hertz was already active.
+ EXPECT_CALL(callback, OnFrame);
+ time_controller.AdvanceTime(TimeDelta::Millis(500));
+}
+
TEST(FrameCadenceAdapterTest,
FrameRateFollowsRateStatisticsAfterZeroHertzDeactivated) {
ZeroHertzFieldTrialEnabler enabler;
@@ -230,7 +253,7 @@ TEST(FrameCadenceAdapterTest, ForwardsFramesDelayed) {
EXPECT_CALL(callback, OnFrame).Times(0);
adapter->OnFrame(frame);
EXPECT_CALL(callback, OnFrame)
- .WillOnce(Invoke([&](Timestamp post_time, int,
+ .WillOnce(Invoke([&](Timestamp post_time, bool,
const VideoFrame& frame) {
EXPECT_EQ(post_time, time_controller.GetClock()->CurrentTime());
EXPECT_EQ(frame.timestamp_us(),
@@ -309,7 +332,7 @@ TEST(FrameCadenceAdapterTest, RepeatsFramesDelayed) {
adapter->OnFrame(frame);
EXPECT_CALL(callback, OnFrame)
- .WillOnce(Invoke([&](Timestamp post_time, int, const VideoFrame& frame) {
+ .WillOnce(Invoke([&](Timestamp post_time, bool, const VideoFrame& frame) {
EXPECT_EQ(post_time, time_controller.GetClock()->CurrentTime());
EXPECT_EQ(frame.timestamp_us(), original_timestamp_us);
EXPECT_EQ(frame.ntp_time_ms(), original_ntp_time.ToMs());
@@ -318,7 +341,7 @@ TEST(FrameCadenceAdapterTest, RepeatsFramesDelayed) {
Mock::VerifyAndClearExpectations(&callback);
EXPECT_CALL(callback, OnFrame)
- .WillOnce(Invoke([&](Timestamp post_time, int, const VideoFrame& frame) {
+ .WillOnce(Invoke([&](Timestamp post_time, bool, const VideoFrame& frame) {
EXPECT_EQ(post_time, time_controller.GetClock()->CurrentTime());
EXPECT_EQ(frame.timestamp_us(),
original_timestamp_us + rtc::kNumMicrosecsPerSec);
@@ -329,7 +352,7 @@ TEST(FrameCadenceAdapterTest, RepeatsFramesDelayed) {
Mock::VerifyAndClearExpectations(&callback);
EXPECT_CALL(callback, OnFrame)
- .WillOnce(Invoke([&](Timestamp post_time, int, const VideoFrame& frame) {
+ .WillOnce(Invoke([&](Timestamp post_time, bool, const VideoFrame& frame) {
EXPECT_EQ(post_time, time_controller.GetClock()->CurrentTime());
EXPECT_EQ(frame.timestamp_us(),
original_timestamp_us + 2 * rtc::kNumMicrosecsPerSec);
@@ -359,7 +382,7 @@ TEST(FrameCadenceAdapterTest,
// Send one frame, expect a repeat.
adapter->OnFrame(CreateFrame());
EXPECT_CALL(callback, OnFrame)
- .WillOnce(Invoke([&](Timestamp post_time, int, const VideoFrame& frame) {
+ .WillOnce(Invoke([&](Timestamp post_time, bool, const VideoFrame& frame) {
EXPECT_EQ(post_time, time_controller.GetClock()->CurrentTime());
EXPECT_EQ(frame.timestamp_us(), 0);
EXPECT_EQ(frame.ntp_time_ms(), 0);
@@ -367,7 +390,7 @@ TEST(FrameCadenceAdapterTest,
time_controller.AdvanceTime(TimeDelta::Seconds(1));
Mock::VerifyAndClearExpectations(&callback);
EXPECT_CALL(callback, OnFrame)
- .WillOnce(Invoke([&](Timestamp post_time, int, const VideoFrame& frame) {
+ .WillOnce(Invoke([&](Timestamp post_time, bool, const VideoFrame& frame) {
EXPECT_EQ(post_time, time_controller.GetClock()->CurrentTime());
EXPECT_EQ(frame.timestamp_us(), 0);
EXPECT_EQ(frame.ntp_time_ms(), 0);
@@ -399,7 +422,7 @@ TEST(FrameCadenceAdapterTest, StopsRepeatingFramesDelayed) {
// Send the new frame at 2.5s, which should appear after 3.5s.
adapter->OnFrame(CreateFrameWithTimestamps(&time_controller));
EXPECT_CALL(callback, OnFrame)
- .WillOnce(Invoke([&](Timestamp, int, const VideoFrame& frame) {
+ .WillOnce(Invoke([&](Timestamp, bool, const VideoFrame& frame) {
EXPECT_EQ(frame.timestamp_us(), 5 * rtc::kNumMicrosecsPerSec / 2);
EXPECT_EQ(frame.ntp_time_ms(),
original_ntp_time.ToMs() + 5u * rtc::kNumMillisecsPerSec / 2);
@@ -708,6 +731,8 @@ class ZeroHertzLayerQualityConvergenceTest : public ::testing::Test {
static constexpr TimeDelta kMinFrameDelay = TimeDelta::Millis(100);
static constexpr TimeDelta kIdleFrameDelay =
FrameCadenceAdapterInterface::kZeroHertzIdleRepeatRatePeriod;
+ // Restricts non-idle repeat rate to 5 fps (default is 10 fps);
+ static constexpr int kRestrictedMaxFps = 5;
ZeroHertzLayerQualityConvergenceTest() {
adapter_->Initialize(&callback_);
@@ -725,7 +750,7 @@ class ZeroHertzLayerQualityConvergenceTest : public ::testing::Test {
std::initializer_list<TimeDelta> list) {
Timestamp origin = time_controller_.GetClock()->CurrentTime();
for (auto delay : list) {
- EXPECT_CALL(callback_, OnFrame(origin + delay, _, _));
+ EXPECT_CALL(callback_, OnFrame(origin + delay, false, _));
time_controller_.AdvanceTime(origin + delay -
time_controller_.GetClock()->CurrentTime());
}
@@ -810,6 +835,100 @@ TEST_F(ZeroHertzLayerQualityConvergenceTest,
});
}
+TEST_F(ZeroHertzLayerQualityConvergenceTest,
+ UnconvergedRepeatRateAdaptsDownWhenRestricted) {
+ PassFrame();
+ ScheduleDelayed(1.5 * kMinFrameDelay, [&] {
+ adapter_->UpdateVideoSourceRestrictions(kRestrictedMaxFps);
+ });
+ ExpectFrameEntriesAtDelaysFromNow({
+ 1 * kMinFrameDelay, // Original frame emitted at non-restricted rate.
+
+ // 1.5 * kMinFrameDelay: restricts max fps to 5 fps which should result
+ // in a new non-idle repeat delay of 2 * kMinFrameDelay.
+ 2 * kMinFrameDelay, // Unconverged repeat at non-restricted rate.
+ 4 * kMinFrameDelay, // Unconverged repeats at restricted rate. This
+ // happens 2 * kMinFrameDelay after the last frame.
+ 6 * kMinFrameDelay, // ...
+ });
+}
+
+TEST_F(ZeroHertzLayerQualityConvergenceTest,
+ UnconvergedRepeatRateAdaptsUpWhenGoingFromRestrictedToUnrestricted) {
+ PassFrame();
+ ScheduleDelayed(1.5 * kMinFrameDelay, [&] {
+ adapter_->UpdateVideoSourceRestrictions(kRestrictedMaxFps);
+ });
+ ScheduleDelayed(5.5 * kMinFrameDelay, [&] {
+ adapter_->UpdateVideoSourceRestrictions(absl::nullopt);
+ });
+ ExpectFrameEntriesAtDelaysFromNow({
+ 1 * kMinFrameDelay, // Original frame emitted at non-restricted rate.
+
+ // 1.5 * kMinFrameDelay: restricts max fps to 5 fps which should result
+ // in a new non-idle repeat delay of 2 * kMinFrameDelay.
+ 2 * kMinFrameDelay, // Unconverged repeat at non-restricted rate.
+ 4 * kMinFrameDelay, // Unconverged repeat at restricted rate.
+
+ // 5.5 * kMinFrameDelay: removes frame-rate restriction and we should
+ // then go back to 10 fps as unconverged repeat rate.
+ 6 * kMinFrameDelay, // Last unconverged repeat at restricted rate.
+ 7 * kMinFrameDelay, // Back to unconverged repeat at non-restricted rate.
+ 8 * kMinFrameDelay, // We are now unrestricted.
+ 9 * kMinFrameDelay, // ...
+ });
+}
+
+TEST_F(ZeroHertzLayerQualityConvergenceTest,
+ UnconvergedRepeatRateMaintainsRestrictionOnReconfigureToHigherMaxFps) {
+ PassFrame();
+ ScheduleDelayed(1.5 * kMinFrameDelay, [&] {
+ adapter_->UpdateVideoSourceRestrictions(kRestrictedMaxFps);
+ });
+ ScheduleDelayed(2.5 * kMinFrameDelay, [&] {
+ adapter_->OnConstraintsChanged(VideoTrackSourceConstraints{
+ /*min_fps=*/0, /*max_fps=*/2 * TimeDelta::Seconds(1) / kMinFrameDelay});
+ });
+ ScheduleDelayed(3 * kMinFrameDelay, [&] { PassFrame(); });
+ ScheduleDelayed(8 * kMinFrameDelay, [&] {
+ adapter_->OnConstraintsChanged(VideoTrackSourceConstraints{
+ /*min_fps=*/0,
+ /*max_fps=*/0.2 * TimeDelta::Seconds(1) / kMinFrameDelay});
+ });
+ ScheduleDelayed(9 * kMinFrameDelay, [&] { PassFrame(); });
+ ExpectFrameEntriesAtDelaysFromNow({
+ 1 * kMinFrameDelay, // Original frame emitted at non-restricted rate.
+
+ // 1.5 * kMinFrameDelay: restricts max fps to 5 fps which should result
+ // in a new non-idle repeat delay of 2 * kMinFrameDelay.
+ 2 * kMinFrameDelay, // Unconverged repeat at non-restricted rate.
+
+ // 2.5 * kMinFrameDelay: new constraint asks for max rate of 20 fps.
+ // The 0Hz adapter is reconstructed for 20 fps but inherits the current
+ // restriction for rate of non-converged frames of 5 fps.
+
+ // A new frame is passed at 3 * kMinFrameDelay. The previous repeat
+ // cadence was stopped by the change in constraints.
+ 3.5 * kMinFrameDelay, // Original frame emitted at non-restricted 20 fps.
+ // The delay is 0.5 * kMinFrameDelay.
+ 5.5 * kMinFrameDelay, // Unconverged repeat at restricted rate.
+ // The delay is 2 * kMinFrameDelay when restricted.
+ 7.5 * kMinFrameDelay, // ...
+
+ // 8 * kMinFrameDelay: new constraint asks for max rate of 2 fps.
+ // The 0Hz adapter is reconstructed for 2 fps and will therefore not obey
+ // the current restriction for rate of non-converged frames of 5 fps
+ // since the new max rate is lower.
+
+ // A new frame is passed at 9 * kMinFrameDelay. The previous repeat
+ // cadence was stopped by the change in constraints.
+ 14 * kMinFrameDelay, // Original frame emitted at non-restricted 2 fps.
+ // The delay is 5 * kMinFrameDelay.
+ 19 * kMinFrameDelay, // Unconverged repeat at non-restricted rate.
+ 24 * kMinFrameDelay, // ...
+ });
+}
+
class FrameCadenceAdapterMetricsTest : public ::testing::Test {
public:
FrameCadenceAdapterMetricsTest() : time_controller_(Timestamp::Millis(1)) {
@@ -869,7 +988,7 @@ TEST(FrameCadenceAdapterRealTimeTest, TimestampsDoNotDrift) {
constexpr int kSleepMs = rtc::kNumMillisecsPerSec / 2;
EXPECT_CALL(callback, OnFrame)
.WillRepeatedly(
- Invoke([&](Timestamp, int, const VideoFrame& incoming_frame) {
+ Invoke([&](Timestamp, bool, const VideoFrame& incoming_frame) {
++frame_counter;
// Avoid the first OnFrame and sleep on the second.
if (frame_counter == 2) {
diff --git a/third_party/libwebrtc/video/frame_decode_scheduler_gn/moz.build b/third_party/libwebrtc/video/frame_decode_scheduler_gn/moz.build
index a53fde81f2..d3fb5a4710 100644
--- a/third_party/libwebrtc/video/frame_decode_scheduler_gn/moz.build
+++ b/third_party/libwebrtc/video/frame_decode_scheduler_gn/moz.build
@@ -191,16 +191,9 @@ if CONFIG["MOZ_X11"] == "1" and CONFIG["OS_TARGET"] == "Linux":
if CONFIG["OS_TARGET"] == "Android" and CONFIG["TARGET_CPU"] == "arm":
OS_LIBS += [
- "android_support",
"unwind"
]
-if CONFIG["OS_TARGET"] == "Android" and CONFIG["TARGET_CPU"] == "x86":
-
- OS_LIBS += [
- "android_support"
- ]
-
if CONFIG["OS_TARGET"] == "Linux" and CONFIG["TARGET_CPU"] == "aarch64":
DEFINES["_GNU_SOURCE"] = True
diff --git a/third_party/libwebrtc/video/frame_decode_timing_gn/moz.build b/third_party/libwebrtc/video/frame_decode_timing_gn/moz.build
index ca09fac23b..9161f27d71 100644
--- a/third_party/libwebrtc/video/frame_decode_timing_gn/moz.build
+++ b/third_party/libwebrtc/video/frame_decode_timing_gn/moz.build
@@ -199,7 +199,6 @@ if CONFIG["MOZ_X11"] == "1" and CONFIG["OS_TARGET"] == "Linux":
if CONFIG["OS_TARGET"] == "Android" and CONFIG["TARGET_CPU"] == "arm":
OS_LIBS += [
- "android_support",
"unwind"
]
@@ -209,10 +208,6 @@ if CONFIG["OS_TARGET"] == "Android" and CONFIG["TARGET_CPU"] == "x86":
"-msse2"
]
- OS_LIBS += [
- "android_support"
- ]
-
if CONFIG["OS_TARGET"] == "Linux" and CONFIG["TARGET_CPU"] == "aarch64":
DEFINES["_GNU_SOURCE"] = True
diff --git a/third_party/libwebrtc/video/frame_dumping_decoder_gn/moz.build b/third_party/libwebrtc/video/frame_dumping_decoder_gn/moz.build
index 39e9878bd2..309c0b159e 100644
--- a/third_party/libwebrtc/video/frame_dumping_decoder_gn/moz.build
+++ b/third_party/libwebrtc/video/frame_dumping_decoder_gn/moz.build
@@ -200,7 +200,6 @@ if CONFIG["MOZ_X11"] == "1" and CONFIG["OS_TARGET"] == "Linux":
if CONFIG["OS_TARGET"] == "Android" and CONFIG["TARGET_CPU"] == "arm":
OS_LIBS += [
- "android_support",
"unwind"
]
@@ -210,10 +209,6 @@ if CONFIG["OS_TARGET"] == "Android" and CONFIG["TARGET_CPU"] == "x86":
"-msse2"
]
- OS_LIBS += [
- "android_support"
- ]
-
if CONFIG["OS_TARGET"] == "Linux" and CONFIG["TARGET_CPU"] == "aarch64":
DEFINES["_GNU_SOURCE"] = True
diff --git a/third_party/libwebrtc/video/frame_dumping_encoder_gn/moz.build b/third_party/libwebrtc/video/frame_dumping_encoder_gn/moz.build
index 615033eb1d..6719245825 100644
--- a/third_party/libwebrtc/video/frame_dumping_encoder_gn/moz.build
+++ b/third_party/libwebrtc/video/frame_dumping_encoder_gn/moz.build
@@ -200,7 +200,6 @@ if CONFIG["MOZ_X11"] == "1" and CONFIG["OS_TARGET"] == "Linux":
if CONFIG["OS_TARGET"] == "Android" and CONFIG["TARGET_CPU"] == "arm":
OS_LIBS += [
- "android_support",
"unwind"
]
@@ -210,10 +209,6 @@ if CONFIG["OS_TARGET"] == "Android" and CONFIG["TARGET_CPU"] == "x86":
"-msse2"
]
- OS_LIBS += [
- "android_support"
- ]
-
if CONFIG["OS_TARGET"] == "Linux" and CONFIG["TARGET_CPU"] == "aarch64":
DEFINES["_GNU_SOURCE"] = True
diff --git a/third_party/libwebrtc/video/render/incoming_video_stream_gn/moz.build b/third_party/libwebrtc/video/render/incoming_video_stream_gn/moz.build
index ad1d7fbfb3..36d087a36a 100644
--- a/third_party/libwebrtc/video/render/incoming_video_stream_gn/moz.build
+++ b/third_party/libwebrtc/video/render/incoming_video_stream_gn/moz.build
@@ -195,7 +195,6 @@ if CONFIG["MOZ_X11"] == "1" and CONFIG["OS_TARGET"] == "Linux":
if CONFIG["OS_TARGET"] == "Android" and CONFIG["TARGET_CPU"] == "arm":
OS_LIBS += [
- "android_support",
"unwind"
]
@@ -205,10 +204,6 @@ if CONFIG["OS_TARGET"] == "Android" and CONFIG["TARGET_CPU"] == "x86":
"-msse2"
]
- OS_LIBS += [
- "android_support"
- ]
-
if CONFIG["OS_TARGET"] == "Linux" and CONFIG["TARGET_CPU"] == "aarch64":
DEFINES["_GNU_SOURCE"] = True
diff --git a/third_party/libwebrtc/video/render/video_render_frames_gn/moz.build b/third_party/libwebrtc/video/render/video_render_frames_gn/moz.build
index d5de8cd178..b0b4923e34 100644
--- a/third_party/libwebrtc/video/render/video_render_frames_gn/moz.build
+++ b/third_party/libwebrtc/video/render/video_render_frames_gn/moz.build
@@ -195,7 +195,6 @@ if CONFIG["MOZ_X11"] == "1" and CONFIG["OS_TARGET"] == "Linux":
if CONFIG["OS_TARGET"] == "Android" and CONFIG["TARGET_CPU"] == "arm":
OS_LIBS += [
- "android_support",
"unwind"
]
@@ -205,10 +204,6 @@ if CONFIG["OS_TARGET"] == "Android" and CONFIG["TARGET_CPU"] == "x86":
"-msse2"
]
- OS_LIBS += [
- "android_support"
- ]
-
if CONFIG["OS_TARGET"] == "Linux" and CONFIG["TARGET_CPU"] == "aarch64":
DEFINES["_GNU_SOURCE"] = True
diff --git a/third_party/libwebrtc/video/send_statistics_proxy.cc b/third_party/libwebrtc/video/send_statistics_proxy.cc
index f8ba31beff..324a5d671d 100644
--- a/third_party/libwebrtc/video/send_statistics_proxy.cc
+++ b/third_party/libwebrtc/video/send_statistics_proxy.cc
@@ -658,6 +658,10 @@ void SendStatisticsProxy::UmaSamplesContainer::UpdateHistograms(
<< current_stats.frames_dropped_by_capturer << "\n";
RTC_HISTOGRAMS_COUNTS_1000(kIndex, uma_prefix_ + "DroppedFrames.Capturer",
current_stats.frames_dropped_by_capturer);
+ log_stream << uma_prefix_ << "DroppedFrames.BadTimestamp"
+ << current_stats.frames_dropped_by_bad_timestamp << "\n";
+ RTC_HISTOGRAMS_COUNTS_1000(kIndex, uma_prefix_ + "DroppedFrames.BadTimestamp",
+ current_stats.frames_dropped_by_bad_timestamp);
log_stream << uma_prefix_ << "DroppedFrames.EncoderQueue "
<< current_stats.frames_dropped_by_encoder_queue << "\n";
RTC_HISTOGRAMS_COUNTS_1000(kIndex, uma_prefix_ + "DroppedFrames.EncoderQueue",
@@ -1097,6 +1101,9 @@ void SendStatisticsProxy::OnFrameDropped(DropReason reason) {
case DropReason::kSource:
++stats_.frames_dropped_by_capturer;
break;
+ case DropReason::kBadTimestamp:
+ ++stats_.frames_dropped_by_bad_timestamp;
+ break;
case DropReason::kEncoderQueue:
++stats_.frames_dropped_by_encoder_queue;
break;
diff --git a/third_party/libwebrtc/video/task_queue_frame_decode_scheduler_gn/moz.build b/third_party/libwebrtc/video/task_queue_frame_decode_scheduler_gn/moz.build
index 2651f290bc..302f8420c9 100644
--- a/third_party/libwebrtc/video/task_queue_frame_decode_scheduler_gn/moz.build
+++ b/third_party/libwebrtc/video/task_queue_frame_decode_scheduler_gn/moz.build
@@ -199,7 +199,6 @@ if CONFIG["MOZ_X11"] == "1" and CONFIG["OS_TARGET"] == "Linux":
if CONFIG["OS_TARGET"] == "Android" and CONFIG["TARGET_CPU"] == "arm":
OS_LIBS += [
- "android_support",
"unwind"
]
@@ -209,10 +208,6 @@ if CONFIG["OS_TARGET"] == "Android" and CONFIG["TARGET_CPU"] == "x86":
"-msse2"
]
- OS_LIBS += [
- "android_support"
- ]
-
if CONFIG["OS_TARGET"] == "Linux" and CONFIG["TARGET_CPU"] == "aarch64":
DEFINES["_GNU_SOURCE"] = True
diff --git a/third_party/libwebrtc/video/unique_timestamp_counter_gn/moz.build b/third_party/libwebrtc/video/unique_timestamp_counter_gn/moz.build
index 24b3c5a30b..e38fabc4cc 100644
--- a/third_party/libwebrtc/video/unique_timestamp_counter_gn/moz.build
+++ b/third_party/libwebrtc/video/unique_timestamp_counter_gn/moz.build
@@ -184,7 +184,6 @@ if CONFIG["MOZ_X11"] == "1" and CONFIG["OS_TARGET"] == "Linux":
if CONFIG["OS_TARGET"] == "Android" and CONFIG["TARGET_CPU"] == "arm":
OS_LIBS += [
- "android_support",
"unwind"
]
@@ -194,10 +193,6 @@ if CONFIG["OS_TARGET"] == "Android" and CONFIG["TARGET_CPU"] == "x86":
"-msse2"
]
- OS_LIBS += [
- "android_support"
- ]
-
if CONFIG["OS_TARGET"] == "Linux" and CONFIG["TARGET_CPU"] == "aarch64":
DEFINES["_GNU_SOURCE"] = True
diff --git a/third_party/libwebrtc/video/video_gn/moz.build b/third_party/libwebrtc/video/video_gn/moz.build
index e8ac15dc40..5e3d75d621 100644
--- a/third_party/libwebrtc/video/video_gn/moz.build
+++ b/third_party/libwebrtc/video/video_gn/moz.build
@@ -220,7 +220,6 @@ if CONFIG["MOZ_X11"] == "1" and CONFIG["OS_TARGET"] == "Linux":
if CONFIG["OS_TARGET"] == "Android" and CONFIG["TARGET_CPU"] == "arm":
OS_LIBS += [
- "android_support",
"unwind"
]
@@ -230,10 +229,6 @@ if CONFIG["OS_TARGET"] == "Android" and CONFIG["TARGET_CPU"] == "x86":
"-msse2"
]
- OS_LIBS += [
- "android_support"
- ]
-
if CONFIG["OS_TARGET"] == "Linux" and CONFIG["TARGET_CPU"] == "aarch64":
DEFINES["_GNU_SOURCE"] = True
diff --git a/third_party/libwebrtc/video/video_quality_test.cc b/third_party/libwebrtc/video/video_quality_test.cc
index 971c129329..99b722322a 100644
--- a/third_party/libwebrtc/video/video_quality_test.cc
+++ b/third_party/libwebrtc/video/video_quality_test.cc
@@ -375,7 +375,6 @@ VideoQualityTest::VideoQualityTest(
std::unique_ptr<InjectionComponents> injection_components)
: clock_(Clock::GetRealTimeClock()),
task_queue_factory_(CreateDefaultTaskQueueFactory()),
- rtc_event_log_factory_(task_queue_factory_.get()),
video_decoder_factory_([this](const SdpVideoFormat& format) {
return this->CreateVideoDecoder(format);
}),
@@ -1221,10 +1220,10 @@ void VideoQualityTest::RunWithAnalyzer(const Params& params) {
}
if (!params.logging.rtc_event_log_name.empty()) {
- send_event_log_ = rtc_event_log_factory_.CreateRtcEventLog(
- RtcEventLog::EncodingType::NewFormat);
- recv_event_log_ = rtc_event_log_factory_.CreateRtcEventLog(
- RtcEventLog::EncodingType::NewFormat);
+ std::unique_ptr<RtcEventLog> send_event_log =
+ rtc_event_log_factory_.Create(env());
+ std::unique_ptr<RtcEventLog> recv_event_log =
+ rtc_event_log_factory_.Create(env());
std::unique_ptr<RtcEventLogOutputFile> send_output(
std::make_unique<RtcEventLogOutputFile>(
params.logging.rtc_event_log_name + "_send",
@@ -1234,19 +1233,18 @@ void VideoQualityTest::RunWithAnalyzer(const Params& params) {
params.logging.rtc_event_log_name + "_recv",
RtcEventLog::kUnlimitedOutput));
bool event_log_started =
- send_event_log_->StartLogging(std::move(send_output),
- RtcEventLog::kImmediateOutput) &&
- recv_event_log_->StartLogging(std::move(recv_output),
- RtcEventLog::kImmediateOutput);
+ send_event_log->StartLogging(std::move(send_output),
+ RtcEventLog::kImmediateOutput) &&
+ recv_event_log->StartLogging(std::move(recv_output),
+ RtcEventLog::kImmediateOutput);
RTC_DCHECK(event_log_started);
- } else {
- send_event_log_ = std::make_unique<RtcEventLogNull>();
- recv_event_log_ = std::make_unique<RtcEventLogNull>();
+ SetSendEventLog(std::move(send_event_log));
+ SetRecvEventLog(std::move(recv_event_log));
}
SendTask(task_queue(), [this, &params, &send_transport, &recv_transport]() {
- CallConfig send_call_config(send_event_log_.get());
- CallConfig recv_call_config(recv_event_log_.get());
+ CallConfig send_call_config = SendCallConfig();
+ CallConfig recv_call_config = RecvCallConfig();
send_call_config.bitrate_config = params.call.call_bitrate_config;
recv_call_config.bitrate_config = params.call.call_bitrate_config;
if (params_.audio.enabled)
@@ -1444,10 +1442,10 @@ void VideoQualityTest::RunWithRenderers(const Params& params) {
std::vector<std::unique_ptr<test::VideoRenderer>> loopback_renderers;
if (!params.logging.rtc_event_log_name.empty()) {
- send_event_log_ = rtc_event_log_factory_.CreateRtcEventLog(
- RtcEventLog::EncodingType::NewFormat);
- recv_event_log_ = rtc_event_log_factory_.CreateRtcEventLog(
- RtcEventLog::EncodingType::NewFormat);
+ std::unique_ptr<RtcEventLog> send_event_log =
+ rtc_event_log_factory_.Create(env());
+ std::unique_ptr<RtcEventLog> recv_event_log =
+ rtc_event_log_factory_.Create(env());
std::unique_ptr<RtcEventLogOutputFile> send_output(
std::make_unique<RtcEventLogOutputFile>(
params.logging.rtc_event_log_name + "_send",
@@ -1457,14 +1455,13 @@ void VideoQualityTest::RunWithRenderers(const Params& params) {
params.logging.rtc_event_log_name + "_recv",
RtcEventLog::kUnlimitedOutput));
bool event_log_started =
- send_event_log_->StartLogging(std::move(send_output),
- /*output_period_ms=*/5000) &&
- recv_event_log_->StartLogging(std::move(recv_output),
- /*output_period_ms=*/5000);
+ send_event_log->StartLogging(std::move(send_output),
+ /*output_period_ms=*/5000) &&
+ recv_event_log->StartLogging(std::move(recv_output),
+ /*output_period_ms=*/5000);
RTC_DCHECK(event_log_started);
- } else {
- send_event_log_ = std::make_unique<RtcEventLogNull>();
- recv_event_log_ = std::make_unique<RtcEventLogNull>();
+ SetSendEventLog(std::move(send_event_log));
+ SetRecvEventLog(std::move(recv_event_log));
}
SendTask(task_queue(), [&]() {
@@ -1473,9 +1470,9 @@ void VideoQualityTest::RunWithRenderers(const Params& params) {
// TODO(ivica): Remove bitrate_config and use the default CallConfig(), to
// match the full stack tests.
- CallConfig send_call_config(send_event_log_.get());
+ CallConfig send_call_config = SendCallConfig();
send_call_config.bitrate_config = params_.call.call_bitrate_config;
- CallConfig recv_call_config(recv_event_log_.get());
+ CallConfig recv_call_config = RecvCallConfig();
if (params_.audio.enabled)
InitializeAudioDevice(&send_call_config, &recv_call_config,
diff --git a/third_party/libwebrtc/video/video_receive_stream2.cc b/third_party/libwebrtc/video/video_receive_stream2.cc
index 85cc0aa0dc..33e2f39ced 100644
--- a/third_party/libwebrtc/video/video_receive_stream2.cc
+++ b/third_party/libwebrtc/video/video_receive_stream2.cc
@@ -568,10 +568,7 @@ VideoReceiveStreamInterface::Stats VideoReceiveStream2::GetStats() const {
rtp_receive_statistics_->GetStatistician(rtx_ssrc());
if (rtx_statistician) {
stats.total_bitrate_bps += rtx_statistician->BitrateReceived();
- // TODO(bugs.webrtc.org/15096): remove kill-switch after rollout.
- if (!call_->trials().IsDisabled("WebRTC-Stats-RtxReceiveStats")) {
- stats.rtx_rtp_stats = rtx_statistician->GetStats();
- }
+ stats.rtx_rtp_stats = rtx_statistician->GetStats();
}
}
@@ -917,6 +914,22 @@ int VideoReceiveStream2::DecodeAndMaybeDispatchEncodedFrame(
}
int decode_result = video_receiver_.Decode(frame_ptr);
+ if (decode_result < WEBRTC_VIDEO_CODEC_OK) {
+ // Asynchronous decoders may delay error reporting, potentially resulting in
+ // error reports reflecting issues that occurred several frames back.
+ RTC_LOG(LS_WARNING)
+ << "Failed to decode frame. Return code: " << decode_result
+ << ", SSRC: " << remote_ssrc()
+ << ", frame RTP timestamp: " << frame_ptr->RtpTimestamp()
+ << ", type: " << VideoFrameTypeToString(frame_ptr->FrameType())
+ << ", size: " << frame_ptr->size()
+ << ", width: " << frame_ptr->_encodedWidth
+ << ", height: " << frame_ptr->_encodedHeight
+ << ", spatial idx: " << frame_ptr->SpatialIndex().value_or(-1)
+ << ", temporal idx: " << frame_ptr->TemporalIndex().value_or(-1)
+ << ", id: " << frame_ptr->Id();
+ }
+
if (encoded_frame_output_enabled) {
absl::optional<RecordableEncodedFrame::EncodedResolution>
pending_resolution;
diff --git a/third_party/libwebrtc/video/video_receive_stream_timeout_tracker_gn/moz.build b/third_party/libwebrtc/video/video_receive_stream_timeout_tracker_gn/moz.build
index 8fb9a9c737..f7e5be24c0 100644
--- a/third_party/libwebrtc/video/video_receive_stream_timeout_tracker_gn/moz.build
+++ b/third_party/libwebrtc/video/video_receive_stream_timeout_tracker_gn/moz.build
@@ -199,7 +199,6 @@ if CONFIG["MOZ_X11"] == "1" and CONFIG["OS_TARGET"] == "Linux":
if CONFIG["OS_TARGET"] == "Android" and CONFIG["TARGET_CPU"] == "arm":
OS_LIBS += [
- "android_support",
"unwind"
]
@@ -209,10 +208,6 @@ if CONFIG["OS_TARGET"] == "Android" and CONFIG["TARGET_CPU"] == "x86":
"-msse2"
]
- OS_LIBS += [
- "android_support"
- ]
-
if CONFIG["OS_TARGET"] == "Linux" and CONFIG["TARGET_CPU"] == "aarch64":
DEFINES["_GNU_SOURCE"] = True
diff --git a/third_party/libwebrtc/video/video_stream_buffer_controller_gn/moz.build b/third_party/libwebrtc/video/video_stream_buffer_controller_gn/moz.build
index e60151d967..7da76222b1 100644
--- a/third_party/libwebrtc/video/video_stream_buffer_controller_gn/moz.build
+++ b/third_party/libwebrtc/video/video_stream_buffer_controller_gn/moz.build
@@ -200,7 +200,6 @@ if CONFIG["MOZ_X11"] == "1" and CONFIG["OS_TARGET"] == "Linux":
if CONFIG["OS_TARGET"] == "Android" and CONFIG["TARGET_CPU"] == "arm":
OS_LIBS += [
- "android_support",
"unwind"
]
@@ -210,10 +209,6 @@ if CONFIG["OS_TARGET"] == "Android" and CONFIG["TARGET_CPU"] == "x86":
"-msse2"
]
- OS_LIBS += [
- "android_support"
- ]
-
if CONFIG["OS_TARGET"] == "Linux" and CONFIG["TARGET_CPU"] == "aarch64":
DEFINES["_GNU_SOURCE"] = True
diff --git a/third_party/libwebrtc/video/video_stream_encoder.cc b/third_party/libwebrtc/video/video_stream_encoder.cc
index c5f086e155..669f165635 100644
--- a/third_party/libwebrtc/video/video_stream_encoder.cc
+++ b/third_party/libwebrtc/video/video_stream_encoder.cc
@@ -94,6 +94,18 @@ int GetNumSpatialLayers(const VideoCodec& codec) {
}
}
+absl::optional<EncodedImageCallback::DropReason> MaybeConvertDropReason(
+ VideoStreamEncoderObserver::DropReason reason) {
+ switch (reason) {
+ case VideoStreamEncoderObserver::DropReason::kMediaOptimization:
+ return EncodedImageCallback::DropReason::kDroppedByMediaOptimizations;
+ case VideoStreamEncoderObserver::DropReason::kEncoder:
+ return EncodedImageCallback::DropReason::kDroppedByEncoder;
+ default:
+ return absl::nullopt;
+ }
+}
+
bool RequiresEncoderReset(const VideoCodec& prev_send_codec,
const VideoCodec& new_send_codec,
bool was_encode_called_since_last_initialization) {
@@ -647,7 +659,6 @@ VideoStreamEncoder::VideoStreamEncoder(
: field_trials_(field_trials),
worker_queue_(TaskQueueBase::Current()),
number_of_cores_(number_of_cores),
- sink_(nullptr),
settings_(settings),
allocation_cb_type_(allocation_cb_type),
rate_control_settings_(
@@ -661,39 +672,12 @@ VideoStreamEncoder::VideoStreamEncoder(
? encoder_selector_from_constructor_
: encoder_selector_from_factory_.get()),
encoder_stats_observer_(encoder_stats_observer),
- cadence_callback_(*this),
frame_cadence_adapter_(std::move(frame_cadence_adapter)),
- encoder_initialized_(false),
- max_framerate_(-1),
- pending_encoder_reconfiguration_(false),
- pending_encoder_creation_(false),
- crop_width_(0),
- crop_height_(0),
- encoder_target_bitrate_bps_(absl::nullopt),
- max_data_payload_length_(0),
- encoder_paused_and_dropped_frame_(false),
- was_encode_called_since_last_initialization_(false),
- encoder_failed_(false),
clock_(clock),
- last_captured_timestamp_(0),
delta_ntp_internal_ms_(clock_->CurrentNtpInMilliseconds() -
clock_->TimeInMilliseconds()),
last_frame_log_ms_(clock_->TimeInMilliseconds()),
- captured_frame_count_(0),
- dropped_frame_cwnd_pushback_count_(0),
- dropped_frame_encoder_block_count_(0),
- pending_frame_post_time_us_(0),
- accumulated_update_rect_{0, 0, 0, 0},
- accumulated_update_rect_is_valid_(true),
- animation_start_time_(Timestamp::PlusInfinity()),
- cap_resolution_due_to_video_content_(false),
- expect_resize_state_(ExpectResizeState::kNoResize),
- fec_controller_override_(nullptr),
- force_disable_frame_dropper_(false),
- pending_frame_drops_(0),
- cwnd_frame_counter_(0),
next_frame_types_(1, VideoFrameType::kVideoFrameDelta),
- frame_encode_metadata_writer_(this),
automatic_animation_detection_experiment_(
ParseAutomatincAnimationDetectionFieldTrial()),
input_state_provider_(encoder_stats_observer),
@@ -704,7 +688,6 @@ VideoStreamEncoder::VideoStreamEncoder(
degradation_preference_manager_(
std::make_unique<DegradationPreferenceManager>(
video_stream_adapter_.get())),
- adaptation_constraints_(),
stream_resource_manager_(&input_state_provider_,
encoder_stats_observer,
clock_,
@@ -1499,7 +1482,7 @@ void VideoStreamEncoder::OnEncoderSettingsChanged() {
}
void VideoStreamEncoder::OnFrame(Timestamp post_time,
- int frames_scheduled_for_processing,
+ bool queue_overload,
const VideoFrame& video_frame) {
RTC_DCHECK_RUN_ON(&encoder_queue_);
VideoFrame incoming_frame = video_frame;
@@ -1538,11 +1521,8 @@ void VideoStreamEncoder::OnFrame(Timestamp post_time,
<< incoming_frame.ntp_time_ms()
<< " <= " << last_captured_timestamp_
<< ") for incoming frame. Dropping.";
- encoder_queue_.PostTask([this, incoming_frame]() {
- RTC_DCHECK_RUN_ON(&encoder_queue_);
- accumulated_update_rect_.Union(incoming_frame.update_rect());
- accumulated_update_rect_is_valid_ &= incoming_frame.has_update_rect();
- });
+ ProcessDroppedFrame(incoming_frame,
+ VideoStreamEncoderObserver::DropReason::kBadTimestamp);
return;
}
@@ -1561,25 +1541,24 @@ void VideoStreamEncoder::OnFrame(Timestamp post_time,
bool cwnd_frame_drop =
cwnd_frame_drop_interval_ &&
(cwnd_frame_counter_++ % cwnd_frame_drop_interval_.value() == 0);
- if (frames_scheduled_for_processing == 1 && !cwnd_frame_drop) {
+ if (!queue_overload && !cwnd_frame_drop) {
MaybeEncodeVideoFrame(incoming_frame, post_time.us());
} else {
if (cwnd_frame_drop) {
// Frame drop by congestion window pushback. Do not encode this
// frame.
++dropped_frame_cwnd_pushback_count_;
- encoder_stats_observer_->OnFrameDropped(
- VideoStreamEncoderObserver::DropReason::kCongestionWindow);
} else {
// There is a newer frame in flight. Do not encode this frame.
RTC_LOG(LS_VERBOSE)
<< "Incoming frame dropped due to that the encoder is blocked.";
++dropped_frame_encoder_block_count_;
- encoder_stats_observer_->OnFrameDropped(
- VideoStreamEncoderObserver::DropReason::kEncoderQueue);
}
- accumulated_update_rect_.Union(incoming_frame.update_rect());
- accumulated_update_rect_is_valid_ &= incoming_frame.has_update_rect();
+ ProcessDroppedFrame(
+ incoming_frame,
+ cwnd_frame_drop
+ ? VideoStreamEncoderObserver::DropReason::kCongestionWindow
+ : VideoStreamEncoderObserver::DropReason::kEncoderQueue);
}
if (log_stats) {
RTC_LOG(LS_INFO) << "Number of frames: captured " << captured_frame_count_
@@ -1816,10 +1795,8 @@ void VideoStreamEncoder::MaybeEncodeVideoFrame(const VideoFrame& video_frame,
// Because pending frame will be dropped in any case, we need to
// remember its updated region.
if (pending_frame_) {
- encoder_stats_observer_->OnFrameDropped(
- VideoStreamEncoderObserver::DropReason::kEncoderQueue);
- accumulated_update_rect_.Union(pending_frame_->update_rect());
- accumulated_update_rect_is_valid_ &= pending_frame_->has_update_rect();
+ ProcessDroppedFrame(*pending_frame_,
+ VideoStreamEncoderObserver::DropReason::kEncoderQueue);
}
if (DropDueToSize(video_frame.size())) {
@@ -1833,10 +1810,8 @@ void VideoStreamEncoder::MaybeEncodeVideoFrame(const VideoFrame& video_frame,
} else {
// Ensure that any previously stored frame is dropped.
pending_frame_.reset();
- accumulated_update_rect_.Union(video_frame.update_rect());
- accumulated_update_rect_is_valid_ &= video_frame.has_update_rect();
- encoder_stats_observer_->OnFrameDropped(
- VideoStreamEncoderObserver::DropReason::kEncoderQueue);
+ ProcessDroppedFrame(
+ video_frame, VideoStreamEncoderObserver::DropReason::kEncoderQueue);
}
return;
}
@@ -1854,10 +1829,8 @@ void VideoStreamEncoder::MaybeEncodeVideoFrame(const VideoFrame& video_frame,
// Ensure that any previously stored frame is dropped.
pending_frame_.reset();
TraceFrameDropStart();
- accumulated_update_rect_.Union(video_frame.update_rect());
- accumulated_update_rect_is_valid_ &= video_frame.has_update_rect();
- encoder_stats_observer_->OnFrameDropped(
- VideoStreamEncoderObserver::DropReason::kEncoderQueue);
+ ProcessDroppedFrame(
+ video_frame, VideoStreamEncoderObserver::DropReason::kEncoderQueue);
}
return;
}
@@ -1879,10 +1852,9 @@ void VideoStreamEncoder::MaybeEncodeVideoFrame(const VideoFrame& video_frame,
? last_encoder_rate_settings_->encoder_target.bps()
: 0)
<< ", input frame rate " << framerate_fps;
- OnDroppedFrame(
- EncodedImageCallback::DropReason::kDroppedByMediaOptimizations);
- accumulated_update_rect_.Union(video_frame.update_rect());
- accumulated_update_rect_is_valid_ &= video_frame.has_update_rect();
+ ProcessDroppedFrame(
+ video_frame,
+ VideoStreamEncoderObserver::DropReason::kMediaOptimization);
return;
}
@@ -2228,16 +2200,6 @@ EncodedImageCallback::Result VideoStreamEncoder::OnEncodedImage(
}
void VideoStreamEncoder::OnDroppedFrame(DropReason reason) {
- switch (reason) {
- case DropReason::kDroppedByMediaOptimizations:
- encoder_stats_observer_->OnFrameDropped(
- VideoStreamEncoderObserver::DropReason::kMediaOptimization);
- break;
- case DropReason::kDroppedByEncoder:
- encoder_stats_observer_->OnFrameDropped(
- VideoStreamEncoderObserver::DropReason::kEncoder);
- break;
- }
sink_->OnDroppedFrame(reason);
encoder_queue_.PostTask([this, reason] {
RTC_DCHECK_RUN_ON(&encoder_queue_);
@@ -2396,6 +2358,11 @@ void VideoStreamEncoder::OnVideoSourceRestrictionsUpdated(
<< (reason ? reason->Name() : std::string("<null>"))
<< " to " << restrictions.ToString();
+ if (frame_cadence_adapter_) {
+ frame_cadence_adapter_->UpdateVideoSourceRestrictions(
+ restrictions.max_frame_rate());
+ }
+
// TODO(webrtc:14451) Split video_source_sink_controller_
// so that ownership on restrictions/wants is kept on &encoder_queue_
latest_restrictions_ = restrictions;
@@ -2620,4 +2587,16 @@ void VideoStreamEncoder::RemoveRestrictionsListenerForTesting(
event.Wait(rtc::Event::kForever);
}
+// RTC_RUN_ON(&encoder_queue_)
+void VideoStreamEncoder::ProcessDroppedFrame(
+ const VideoFrame& frame,
+ VideoStreamEncoderObserver::DropReason reason) {
+ accumulated_update_rect_.Union(frame.update_rect());
+ accumulated_update_rect_is_valid_ &= frame.has_update_rect();
+ if (auto converted_reason = MaybeConvertDropReason(reason)) {
+ OnDroppedFrame(*converted_reason);
+ }
+ encoder_stats_observer_->OnFrameDropped(reason);
+}
+
} // namespace webrtc
diff --git a/third_party/libwebrtc/video/video_stream_encoder.h b/third_party/libwebrtc/video/video_stream_encoder.h
index 68f008afc0..f2c21c12b0 100644
--- a/third_party/libwebrtc/video/video_stream_encoder.h
+++ b/third_party/libwebrtc/video/video_stream_encoder.h
@@ -132,6 +132,8 @@ class VideoStreamEncoder : public VideoStreamEncoderInterface,
double cwnd_reduce_ratio);
protected:
+ friend class VideoStreamEncoderFrameCadenceRestrictionTest;
+
// Used for testing. For example the `ScalingObserverInterface` methods must
// be called on `encoder_queue_`.
TaskQueueBase* encoder_queue() { return encoder_queue_.Get(); }
@@ -160,10 +162,9 @@ class VideoStreamEncoder : public VideoStreamEncoderInterface,
: video_stream_encoder_(video_stream_encoder) {}
// FrameCadenceAdapterInterface::Callback overrides.
void OnFrame(Timestamp post_time,
- int frames_scheduled_for_processing,
+ bool queue_overload,
const VideoFrame& frame) override {
- video_stream_encoder_.OnFrame(post_time, frames_scheduled_for_processing,
- frame);
+ video_stream_encoder_.OnFrame(post_time, queue_overload, frame);
}
void OnDiscardedFrame() override {
video_stream_encoder_.OnDiscardedFrame();
@@ -212,7 +213,7 @@ class VideoStreamEncoder : public VideoStreamEncoderInterface,
void ReconfigureEncoder() RTC_RUN_ON(&encoder_queue_);
void OnEncoderSettingsChanged() RTC_RUN_ON(&encoder_queue_);
void OnFrame(Timestamp post_time,
- int frames_scheduled_for_processing,
+ bool queue_overload,
const VideoFrame& video_frame);
void OnDiscardedFrame();
void RequestRefreshFrame();
@@ -266,12 +267,16 @@ class VideoStreamEncoder : public VideoStreamEncoderInterface,
const EncodedImage& encoded_image,
const CodecSpecificInfo* codec_specific_info);
+ void ProcessDroppedFrame(const VideoFrame& frame,
+ VideoStreamEncoderObserver::DropReason reason)
+ RTC_RUN_ON(&encoder_queue_);
+
const FieldTrialsView& field_trials_;
TaskQueueBase* const worker_queue_;
const int number_of_cores_;
- EncoderSink* sink_;
+ EncoderSink* sink_ = nullptr;
const VideoStreamEncoderSettings settings_;
const BitrateAllocationCallbackType allocation_cb_type_;
const RateControlSettings rate_control_settings_;
@@ -287,7 +292,7 @@ class VideoStreamEncoder : public VideoStreamEncoderInterface,
VideoStreamEncoderObserver* const encoder_stats_observer_;
// Adapter that avoids public inheritance of the cadence adapter's callback
// interface.
- CadenceCallback cadence_callback_;
+ CadenceCallback cadence_callback_{*this};
// Frame cadence encoder adapter. Frames enter this adapter first, and it then
// forwards them to our OnFrame method.
std::unique_ptr<FrameCadenceAdapterInterface> frame_cadence_adapter_
@@ -296,70 +301,74 @@ class VideoStreamEncoder : public VideoStreamEncoderInterface,
VideoEncoderConfig encoder_config_ RTC_GUARDED_BY(&encoder_queue_);
std::unique_ptr<VideoEncoder> encoder_ RTC_GUARDED_BY(&encoder_queue_)
RTC_PT_GUARDED_BY(&encoder_queue_);
- bool encoder_initialized_;
+ bool encoder_initialized_ = false;
std::unique_ptr<VideoBitrateAllocator> rate_allocator_
RTC_GUARDED_BY(&encoder_queue_) RTC_PT_GUARDED_BY(&encoder_queue_);
- int max_framerate_ RTC_GUARDED_BY(&encoder_queue_);
+ int max_framerate_ RTC_GUARDED_BY(&encoder_queue_) = -1;
// Set when ConfigureEncoder has been called in order to lazy reconfigure the
// encoder on the next frame.
- bool pending_encoder_reconfiguration_ RTC_GUARDED_BY(&encoder_queue_);
+ bool pending_encoder_reconfiguration_ RTC_GUARDED_BY(&encoder_queue_) = false;
// Set when configuration must create a new encoder object, e.g.,
// because of a codec change.
- bool pending_encoder_creation_ RTC_GUARDED_BY(&encoder_queue_);
+ bool pending_encoder_creation_ RTC_GUARDED_BY(&encoder_queue_) = false;
absl::InlinedVector<SetParametersCallback, 2> encoder_configuration_callbacks_
RTC_GUARDED_BY(&encoder_queue_);
absl::optional<VideoFrameInfo> last_frame_info_
RTC_GUARDED_BY(&encoder_queue_);
- int crop_width_ RTC_GUARDED_BY(&encoder_queue_);
- int crop_height_ RTC_GUARDED_BY(&encoder_queue_);
+ int crop_width_ RTC_GUARDED_BY(&encoder_queue_) = 0;
+ int crop_height_ RTC_GUARDED_BY(&encoder_queue_) = 0;
absl::optional<uint32_t> encoder_target_bitrate_bps_
RTC_GUARDED_BY(&encoder_queue_);
- size_t max_data_payload_length_ RTC_GUARDED_BY(&encoder_queue_);
+ size_t max_data_payload_length_ RTC_GUARDED_BY(&encoder_queue_) = 0;
absl::optional<EncoderRateSettings> last_encoder_rate_settings_
RTC_GUARDED_BY(&encoder_queue_);
- bool encoder_paused_and_dropped_frame_ RTC_GUARDED_BY(&encoder_queue_);
+ bool encoder_paused_and_dropped_frame_ RTC_GUARDED_BY(&encoder_queue_) =
+ false;
// Set to true if at least one frame was sent to encoder since last encoder
// initialization.
bool was_encode_called_since_last_initialization_
- RTC_GUARDED_BY(&encoder_queue_);
+ RTC_GUARDED_BY(&encoder_queue_) = false;
- bool encoder_failed_ RTC_GUARDED_BY(&encoder_queue_);
+ bool encoder_failed_ RTC_GUARDED_BY(&encoder_queue_) = false;
Clock* const clock_;
// Used to make sure incoming time stamp is increasing for every frame.
- int64_t last_captured_timestamp_ RTC_GUARDED_BY(&encoder_queue_);
+ int64_t last_captured_timestamp_ RTC_GUARDED_BY(&encoder_queue_) = 0;
// Delta used for translating between NTP and internal timestamps.
const int64_t delta_ntp_internal_ms_ RTC_GUARDED_BY(&encoder_queue_);
int64_t last_frame_log_ms_ RTC_GUARDED_BY(&encoder_queue_);
- int captured_frame_count_ RTC_GUARDED_BY(&encoder_queue_);
- int dropped_frame_cwnd_pushback_count_ RTC_GUARDED_BY(&encoder_queue_);
- int dropped_frame_encoder_block_count_ RTC_GUARDED_BY(&encoder_queue_);
+ int captured_frame_count_ RTC_GUARDED_BY(&encoder_queue_) = 0;
+ int dropped_frame_cwnd_pushback_count_ RTC_GUARDED_BY(&encoder_queue_) = 0;
+ int dropped_frame_encoder_block_count_ RTC_GUARDED_BY(&encoder_queue_) = 0;
absl::optional<VideoFrame> pending_frame_ RTC_GUARDED_BY(&encoder_queue_);
- int64_t pending_frame_post_time_us_ RTC_GUARDED_BY(&encoder_queue_);
+ int64_t pending_frame_post_time_us_ RTC_GUARDED_BY(&encoder_queue_) = 0;
VideoFrame::UpdateRect accumulated_update_rect_
RTC_GUARDED_BY(&encoder_queue_);
- bool accumulated_update_rect_is_valid_ RTC_GUARDED_BY(&encoder_queue_);
+ bool accumulated_update_rect_is_valid_ RTC_GUARDED_BY(&encoder_queue_) = true;
// Used for automatic content type detection.
absl::optional<VideoFrame::UpdateRect> last_update_rect_
RTC_GUARDED_BY(&encoder_queue_);
- Timestamp animation_start_time_ RTC_GUARDED_BY(&encoder_queue_);
- bool cap_resolution_due_to_video_content_ RTC_GUARDED_BY(&encoder_queue_);
+ Timestamp animation_start_time_ RTC_GUARDED_BY(&encoder_queue_) =
+ Timestamp::PlusInfinity();
+ bool cap_resolution_due_to_video_content_ RTC_GUARDED_BY(&encoder_queue_) =
+ false;
// Used to correctly ignore changes in update_rect introduced by
// resize triggered by animation detection.
enum class ExpectResizeState {
kNoResize, // Normal operation.
kResize, // Resize was triggered by the animation detection.
kFirstFrameAfterResize // Resize observed.
- } expect_resize_state_ RTC_GUARDED_BY(&encoder_queue_);
+ } expect_resize_state_ RTC_GUARDED_BY(&encoder_queue_) =
+ ExpectResizeState::kNoResize;
FecControllerOverride* fec_controller_override_
- RTC_GUARDED_BY(&encoder_queue_);
+ RTC_GUARDED_BY(&encoder_queue_) = nullptr;
absl::optional<int64_t> last_parameters_update_ms_
RTC_GUARDED_BY(&encoder_queue_);
absl::optional<int64_t> last_encode_info_ms_ RTC_GUARDED_BY(&encoder_queue_);
@@ -372,18 +381,18 @@ class VideoStreamEncoder : public VideoStreamEncoderInterface,
// disabled if VideoEncoder::GetEncoderInfo() indicates that the encoder has a
// trusted rate controller. This is determined on a per-frame basis, as the
// encoder behavior might dynamically change.
- bool force_disable_frame_dropper_ RTC_GUARDED_BY(&encoder_queue_);
+ bool force_disable_frame_dropper_ RTC_GUARDED_BY(&encoder_queue_) = false;
// Incremented on worker thread whenever `frame_dropper_` determines that a
// frame should be dropped. Decremented on whichever thread runs
// OnEncodedImage(), which is only called by one thread but not necessarily
// the worker thread.
- std::atomic<int> pending_frame_drops_;
+ std::atomic<int> pending_frame_drops_{0};
// Congestion window frame drop ratio (drop 1 in every
// cwnd_frame_drop_interval_ frames).
absl::optional<int> cwnd_frame_drop_interval_ RTC_GUARDED_BY(&encoder_queue_);
// Frame counter for congestion window frame drop.
- int cwnd_frame_counter_ RTC_GUARDED_BY(&encoder_queue_);
+ int cwnd_frame_counter_ RTC_GUARDED_BY(&encoder_queue_) = 0;
std::unique_ptr<EncoderBitrateAdjuster> bitrate_adjuster_
RTC_GUARDED_BY(&encoder_queue_);
@@ -392,7 +401,7 @@ class VideoStreamEncoder : public VideoStreamEncoderInterface,
// turn this into a simple bool `pending_keyframe_request_`.
std::vector<VideoFrameType> next_frame_types_ RTC_GUARDED_BY(&encoder_queue_);
- FrameEncodeMetadataWriter frame_encode_metadata_writer_;
+ FrameEncodeMetadataWriter frame_encode_metadata_writer_{this};
struct AutomaticAnimationDetectionExperiment {
bool enabled = false;
diff --git a/third_party/libwebrtc/video/video_stream_encoder_impl_gn/moz.build b/third_party/libwebrtc/video/video_stream_encoder_impl_gn/moz.build
index 2ea2fce60b..af4e29ee0a 100644
--- a/third_party/libwebrtc/video/video_stream_encoder_impl_gn/moz.build
+++ b/third_party/libwebrtc/video/video_stream_encoder_impl_gn/moz.build
@@ -205,7 +205,6 @@ if CONFIG["MOZ_X11"] == "1" and CONFIG["OS_TARGET"] == "Linux":
if CONFIG["OS_TARGET"] == "Android" and CONFIG["TARGET_CPU"] == "arm":
OS_LIBS += [
- "android_support",
"unwind"
]
@@ -215,10 +214,6 @@ if CONFIG["OS_TARGET"] == "Android" and CONFIG["TARGET_CPU"] == "x86":
"-msse2"
]
- OS_LIBS += [
- "android_support"
- ]
-
if CONFIG["OS_TARGET"] == "Linux" and CONFIG["TARGET_CPU"] == "aarch64":
DEFINES["_GNU_SOURCE"] = True
diff --git a/third_party/libwebrtc/video/video_stream_encoder_interface_gn/moz.build b/third_party/libwebrtc/video/video_stream_encoder_interface_gn/moz.build
index 0d40ef9c8f..beeb7f9117 100644
--- a/third_party/libwebrtc/video/video_stream_encoder_interface_gn/moz.build
+++ b/third_party/libwebrtc/video/video_stream_encoder_interface_gn/moz.build
@@ -187,16 +187,9 @@ if CONFIG["MOZ_X11"] == "1" and CONFIG["OS_TARGET"] == "Linux":
if CONFIG["OS_TARGET"] == "Android" and CONFIG["TARGET_CPU"] == "arm":
OS_LIBS += [
- "android_support",
"unwind"
]
-if CONFIG["OS_TARGET"] == "Android" and CONFIG["TARGET_CPU"] == "x86":
-
- OS_LIBS += [
- "android_support"
- ]
-
if CONFIG["OS_TARGET"] == "Linux" and CONFIG["TARGET_CPU"] == "aarch64":
DEFINES["_GNU_SOURCE"] = True
diff --git a/third_party/libwebrtc/video/video_stream_encoder_observer.h b/third_party/libwebrtc/video/video_stream_encoder_observer.h
index c10412181d..95ca5fa887 100644
--- a/third_party/libwebrtc/video/video_stream_encoder_observer.h
+++ b/third_party/libwebrtc/video/video_stream_encoder_observer.h
@@ -58,6 +58,7 @@ class VideoStreamEncoderObserver : public CpuOveruseMetricsObserver {
enum class DropReason {
kSource,
+ kBadTimestamp,
kEncoderQueue,
kEncoder,
kMediaOptimization,
diff --git a/third_party/libwebrtc/video/video_stream_encoder_unittest.cc b/third_party/libwebrtc/video/video_stream_encoder_unittest.cc
index fa28368d68..6fa99081cd 100644
--- a/third_party/libwebrtc/video/video_stream_encoder_unittest.cc
+++ b/third_party/libwebrtc/video/video_stream_encoder_unittest.cc
@@ -136,8 +136,8 @@ void PassAFrame(
FrameCadenceAdapterInterface::Callback* video_stream_encoder_callback,
int64_t ntp_time_ms) {
encoder_queue->PostTask([video_stream_encoder_callback, ntp_time_ms] {
- video_stream_encoder_callback->OnFrame(Timestamp::Millis(ntp_time_ms), 1,
- CreateSimpleNV12Frame());
+ video_stream_encoder_callback->OnFrame(Timestamp::Millis(ntp_time_ms),
+ false, CreateSimpleNV12Frame());
});
}
@@ -783,6 +783,10 @@ class MockFrameCadenceAdapter : public FrameCadenceAdapterInterface {
UpdateLayerStatus,
(size_t spatial_index, bool enabled),
(override));
+ MOCK_METHOD(void,
+ UpdateVideoSourceRestrictions,
+ (absl::optional<double>),
+ (override));
MOCK_METHOD(void, ProcessKeyFrameRequest, (), (override));
};
@@ -9580,4 +9584,60 @@ TEST(VideoStreamEncoderFrameCadenceTest,
kMaxFps);
}
+class VideoStreamEncoderFrameCadenceRestrictionTest : public ::testing::Test {
+ public:
+ VideoStreamEncoderFrameCadenceRestrictionTest()
+ : adapter_ptr_(adapter_.get()),
+ fake_resource_(FakeResource::Create("FakeResource")),
+ video_stream_encoder_(
+ factory_.Create(std::move(adapter_), &encoder_queue_)) {}
+
+ ~VideoStreamEncoderFrameCadenceRestrictionTest() {
+ factory_.DepleteTaskQueues();
+ }
+
+ void UpdateVideoSourceRestrictions(VideoSourceRestrictions restrictions) {
+ encoder_queue_->PostTask([this, restrictions] {
+ RTC_DCHECK_RUN_ON(encoder_queue_);
+ video_stream_encoder_->OnVideoSourceRestrictionsUpdated(
+ restrictions, VideoAdaptationCounters(), fake_resource_,
+ VideoSourceRestrictions());
+ });
+ }
+
+ protected:
+ SimpleVideoStreamEncoderFactory factory_;
+ std::unique_ptr<NiceMock<MockFrameCadenceAdapter>> adapter_{
+ std::make_unique<NiceMock<MockFrameCadenceAdapter>>()};
+ NiceMock<MockFrameCadenceAdapter>* adapter_ptr_;
+ TaskQueueBase* encoder_queue_{nullptr};
+ rtc::scoped_refptr<FakeResource> fake_resource_;
+ VideoSourceRestrictions restrictions_;
+ std::unique_ptr<SimpleVideoStreamEncoderFactory::AdaptedVideoStreamEncoder>
+ video_stream_encoder_;
+};
+
+TEST_F(VideoStreamEncoderFrameCadenceRestrictionTest,
+ UpdatesVideoSourceRestrictionsUnRestricted) {
+ EXPECT_CALL(*adapter_ptr_, UpdateVideoSourceRestrictions(Eq(absl::nullopt)));
+ UpdateVideoSourceRestrictions(VideoSourceRestrictions());
+}
+
+TEST_F(VideoStreamEncoderFrameCadenceRestrictionTest,
+ UpdatesVideoSourceRestrictionsWithMaxFrameRateRestriction) {
+ restrictions_.set_max_frame_rate(20);
+ EXPECT_CALL(*adapter_ptr_, UpdateVideoSourceRestrictions(Optional(20)));
+ UpdateVideoSourceRestrictions(restrictions_);
+}
+
+TEST_F(VideoStreamEncoderFrameCadenceRestrictionTest,
+ UpdatesVideoSourceRestrictionsWithoutMaxFrameRateRestriction) {
+ // Restrictions in resolution count as restriction updated, even though the
+ // FPS is unlimited.
+ restrictions_.set_max_pixels_per_frame(99);
+ restrictions_.set_target_pixels_per_frame(101);
+ EXPECT_CALL(*adapter_ptr_, UpdateVideoSourceRestrictions(Eq(absl::nullopt)));
+ UpdateVideoSourceRestrictions(restrictions_);
+}
+
} // namespace webrtc