diff --git a/video/BUILD.gn b/video/BUILD.gn index 99a6e76fad..e8cd0cfede 100644 --- a/video/BUILD.gn +++ b/video/BUILD.gn @@ -321,8 +321,10 @@ rtc_library("video_stream_encoder_impl") { "../rtc_base/system:no_unique_address", "../rtc_base/task_utils:pending_task_safety_flag", "../rtc_base/task_utils:repeating_task", + "../rtc_base/task_utils:to_queued_task", "../system_wrappers", "../system_wrappers:field_trial", + "../system_wrappers:metrics", "adaptation:video_adaptation", ] absl_deps = [ diff --git a/video/video_stream_encoder.cc b/video/video_stream_encoder.cc index f3872cce5b..1e68c3d46c 100644 --- a/video/video_stream_encoder.cc +++ b/video/video_stream_encoder.cc @@ -44,9 +44,11 @@ #include "rtc_base/logging.h" #include "rtc_base/strings/string_builder.h" #include "rtc_base/system/no_unique_address.h" +#include "rtc_base/task_utils/to_queued_task.h" #include "rtc_base/thread_annotations.h" #include "rtc_base/trace_event.h" #include "system_wrappers/include/field_trial.h" +#include "system_wrappers/include/metrics.h" #include "video/adaptation/video_stream_encoder_resource_manager.h" #include "video/alignment_adjuster.h" @@ -825,6 +827,8 @@ void VideoStreamEncoder::ConfigureEncoder(VideoEncoderConfig config, pending_encoder_creation_ = (!encoder_ || encoder_config_.video_format != config.video_format || max_data_payload_length_ != max_data_payload_length); + if (encoder_config_.content_type != config.content_type) + has_reported_screenshare_frame_rate_umas_ = false; encoder_config_ = std::move(config); max_data_payload_length_ = max_data_payload_length; pending_encoder_reconfiguration_ = true; @@ -1322,6 +1326,7 @@ void VideoStreamEncoder::OnFrame(const VideoFrame& video_frame) { encoder_queue_.PostTask( [this, incoming_frame, post_time_us, log_stats]() { RTC_DCHECK_RUN_ON(&encoder_queue_); + MaybeReportFrameRateConstraintUmas(); encoder_stats_observer_->OnIncomingFrame(incoming_frame.width(), incoming_frame.height()); ++captured_frame_count_; @@ -2353,6 +2358,64 @@ void VideoStreamEncoder::QueueRequestEncoderSwitch( })); } +// RTC_RUN_ON(&encoder_queue_) +void VideoStreamEncoder::MaybeReportFrameRateConstraintUmas() { + if (has_reported_screenshare_frame_rate_umas_) + return; + has_reported_screenshare_frame_rate_umas_ = true; + bool is_screenshare = + encoder_config_.content_type == VideoEncoderConfig::ContentType::kScreen; + if (!is_screenshare) + return; + main_queue_->PostTask(ToQueuedTask(task_safety_, [this] { + RTC_DCHECK_RUN_ON(main_queue_); + RTC_HISTOGRAM_BOOLEAN("WebRTC.Screenshare.FrameRateConstraints.Exists", + source_constraints_.has_value()); + if (source_constraints_.has_value()) { + RTC_HISTOGRAM_BOOLEAN( + "WebRTC.Screenshare.FrameRateConstraints.Min.Exists", + source_constraints_->min_fps.has_value()); + if (source_constraints_->min_fps.has_value()) { + RTC_HISTOGRAM_COUNTS_100( + "WebRTC.Screenshare.FrameRateConstraints.Min.Value", + source_constraints_->min_fps.value()); + } + RTC_HISTOGRAM_BOOLEAN( + "WebRTC.Screenshare.FrameRateConstraints.Max.Exists", + source_constraints_->max_fps.has_value()); + if (source_constraints_->max_fps.has_value()) { + RTC_HISTOGRAM_COUNTS_100( + "WebRTC.Screenshare.FrameRateConstraints.Max.Value", + source_constraints_->max_fps.value()); + } + if (!source_constraints_->min_fps.has_value()) { + if (source_constraints_->max_fps.has_value()) { + RTC_HISTOGRAM_COUNTS_100( + "WebRTC.Screenshare.FrameRateConstraints.MinUnset.Max", + source_constraints_->max_fps.value()); + } + } else if (source_constraints_->max_fps.has_value()) { + if (source_constraints_->min_fps.value() < + source_constraints_->max_fps.value()) { + RTC_HISTOGRAM_COUNTS_100( + "WebRTC.Screenshare.FrameRateConstraints.MinLessThanMax.Min", + source_constraints_->min_fps.value()); + RTC_HISTOGRAM_COUNTS_100( + "WebRTC.Screenshare.FrameRateConstraints.MinLessThanMax.Max", + source_constraints_->max_fps.value()); + } + constexpr int kMaxBucketCount = + 60 * /*max min_fps=*/60 + /*max max_fps=*/60 - 1; + RTC_HISTOGRAM_ENUMERATION_SPARSE( + "WebRTC.Screenshare.FrameRateConstraints.60MinPlusMaxMinusOne", + source_constraints_->min_fps.value() * 60 + + source_constraints_->max_fps.value() - 1, + /*boundary=*/kMaxBucketCount); + } + } + })); +} + void VideoStreamEncoder::InjectAdaptationResource( rtc::scoped_refptr resource, VideoAdaptationReason reason) { diff --git a/video/video_stream_encoder.h b/video/video_stream_encoder.h index 93c79030e3..8ba0342e2c 100644 --- a/video/video_stream_encoder.h +++ b/video/video_stream_encoder.h @@ -228,6 +228,9 @@ class VideoStreamEncoder : public VideoStreamEncoderInterface, void QueueRequestEncoderSwitch(const webrtc::SdpVideoFormat& format) RTC_RUN_ON(&encoder_queue_); + // Reports UMAs on frame rate constraints usage on the first call. + void MaybeReportFrameRateConstraintUmas() RTC_RUN_ON(&encoder_queue_); + TaskQueueBase* const main_queue_; const uint32_t number_of_cores_; @@ -244,6 +247,8 @@ class VideoStreamEncoder : public VideoStreamEncoderInterface, // The source's constraints. absl::optional source_constraints_ RTC_GUARDED_BY(main_queue_); + bool has_reported_screenshare_frame_rate_umas_ + RTC_GUARDED_BY(&encoder_queue_) = false; VideoEncoderConfig encoder_config_ RTC_GUARDED_BY(&encoder_queue_); std::unique_ptr encoder_ RTC_GUARDED_BY(&encoder_queue_)