diff --git a/api/video/BUILD.gn b/api/video/BUILD.gn index 73f477ac29..b13d84eaf0 100644 --- a/api/video/BUILD.gn +++ b/api/video/BUILD.gn @@ -135,6 +135,8 @@ rtc_source_set("video_stream_encoder") { visibility = [ "*" ] sources = [ "video_stream_encoder_interface.h", + "video_stream_encoder_observer.h", + "video_stream_encoder_settings.h", ] deps = [ @@ -143,5 +145,27 @@ rtc_source_set("video_stream_encoder") { # For rtpparameters.h "..:libjingle_peerconnection_api", "../video_codecs:video_codecs_api", + "//third_party/abseil-cpp/absl/types:optional", + ] +} + +rtc_source_set("video_stream_encoder_create") { + visibility = [ "*" ] + allow_poison = [ "software_video_codecs" ] # TODO(bugs.webrtc.org/7925): Remove. + sources = [ + "video_stream_encoder_create.cc", + "video_stream_encoder_create.h", + ] + + if (!build_with_chromium && is_clang) { + # Suppress warnings from the Chromium Clang plugin (bugs.webrtc.org/163). + suppressed_configs += [ "//build/config/clang:find_bad_constructs" ] + } + + deps = [ + ":video_stream_encoder", + "../../rtc_base:ptr_util", + "../../video:video_stream_encoder_impl", + "../video_codecs:video_codecs_api", ] } diff --git a/api/video/DEPS b/api/video/DEPS index 3cdc754464..aec927baaa 100644 --- a/api/video/DEPS +++ b/api/video/DEPS @@ -8,4 +8,7 @@ specific_include_rules = { "video_stream_decoder_create.cc": [ "+video/video_stream_decoder_impl.h", ], + "video_stream_encoder_create.cc": [ + "+video/video_stream_encoder.h", + ], } diff --git a/api/video/video_stream_encoder_create.cc b/api/video/video_stream_encoder_create.cc new file mode 100644 index 0000000000..b376a4878f --- /dev/null +++ b/api/video/video_stream_encoder_create.cc @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2018 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#include "api/video/video_stream_encoder_create.h" + +#include "rtc_base/ptr_util.h" +#include "video/video_stream_encoder.h" + +namespace webrtc { +std::unique_ptr CreateVideoStreamEncoder( + uint32_t number_of_cores, + VideoStreamEncoderObserver* encoder_stats_observer, + const VideoStreamEncoderSettings& settings, + // Deprecated, used for tests only. + rtc::VideoSinkInterface* pre_encode_callback) { + return rtc::MakeUnique( + number_of_cores, encoder_stats_observer, settings, pre_encode_callback, + rtc::MakeUnique(encoder_stats_observer)); +} +} // namespace webrtc diff --git a/api/video/video_stream_encoder_create.h b/api/video/video_stream_encoder_create.h new file mode 100644 index 0000000000..911727327c --- /dev/null +++ b/api/video/video_stream_encoder_create.h @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2018 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef API_VIDEO_VIDEO_STREAM_ENCODER_CREATE_H_ +#define API_VIDEO_VIDEO_STREAM_ENCODER_CREATE_H_ + +#include +#include +#include + +#include "api/video/video_stream_encoder_interface.h" +#include "api/video/video_stream_encoder_observer.h" +#include "api/video/video_stream_encoder_settings.h" + +namespace webrtc { + +std::unique_ptr CreateVideoStreamEncoder( + uint32_t number_of_cores, + VideoStreamEncoderObserver* encoder_stats_observer, + const VideoStreamEncoderSettings& settings, + // Deprecated, used for tests only. + rtc::VideoSinkInterface* pre_encode_callback); + +inline std::unique_ptr CreateVideoStreamEncoder( + uint32_t number_of_cores, + VideoStreamEncoderObserver* encoder_stats_observer, + const VideoStreamEncoderSettings& settings) { + return CreateVideoStreamEncoder(number_of_cores, encoder_stats_observer, + settings, nullptr); +} + +} // namespace webrtc + +#endif // API_VIDEO_VIDEO_STREAM_ENCODER_CREATE_H_ diff --git a/api/video/video_stream_encoder_interface.h b/api/video/video_stream_encoder_interface.h index 44dc6f4972..2f95e5851e 100644 --- a/api/video/video_stream_encoder_interface.h +++ b/api/video/video_stream_encoder_interface.h @@ -47,8 +47,6 @@ class VideoStreamEncoderInterface : public rtc::VideoSinkInterface { int min_transmit_bitrate_bps) = 0; }; - ~VideoStreamEncoderInterface() override = default; - // Sets the source that will provide video frames to the VideoStreamEncoder's // OnFrame method. |degradation_preference| control whether or not resolution // or frame rate may be reduced. The VideoStreamEncoder registers itself with diff --git a/api/video/video_stream_encoder_observer.h b/api/video/video_stream_encoder_observer.h new file mode 100644 index 0000000000..ac5c8a1f5b --- /dev/null +++ b/api/video/video_stream_encoder_observer.h @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2018 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef API_VIDEO_VIDEO_STREAM_ENCODER_OBSERVER_H_ +#define API_VIDEO_VIDEO_STREAM_ENCODER_OBSERVER_H_ + +#include + +#include "absl/types/optional.h" +#include "api/video_codecs/video_encoder.h" +#include "api/video_codecs/video_encoder_config.h" + +namespace webrtc { + +// TODO(nisse): Used for the OnSendEncodedImage callback below. The callback +// wants metadata such as size, encode timing, qp, but doesn't need actual +// encoded data. So use some other type to represent that. +class EncodedImage; + +// Broken out into a base class, with public inheritance below, only to ease +// unit testing of the internal class OveruseFrameDetector. +class CpuOveruseMetricsObserver { + public: + virtual ~CpuOveruseMetricsObserver() = default; + virtual void OnEncodedFrameTimeMeasured(int encode_duration_ms, + int encode_usage_percent) = 0; +}; + +class VideoStreamEncoderObserver : public CpuOveruseMetricsObserver { + public: + // Number of resolution and framerate reductions (unset if disabled). + struct AdaptationSteps { + absl::optional num_resolution_reductions = 0; + absl::optional num_framerate_reductions = 0; + }; + + // TODO(nisse): There are too many enums to represent this. Besides + // this one, see AdaptationObserverInterface::AdaptReason and + // WebRtcVideoChannel::AdaptReason. + enum class AdaptationReason { + kNone, // Used for reset of counters. + kCpu, + kQuality, + }; + + // TODO(nisse): Duplicates enum EncodedImageCallback::DropReason. + enum class DropReason { + kSource, + kEncoderQueue, + kEncoder, + kMediaOptimization + }; + + virtual ~VideoStreamEncoderObserver() = default; + + virtual void OnIncomingFrame(int width, int height) = 0; + + // TODO(nisse): Merge into one callback per encoded frame. + using CpuOveruseMetricsObserver::OnEncodedFrameTimeMeasured; + virtual void OnSendEncodedImage(const EncodedImage& encoded_image, + const CodecSpecificInfo* codec_info) = 0; + + virtual void OnFrameDropped(DropReason reason) = 0; + + // Used to indicate change in content type, which may require a change in + // how stats are collected and set the configured preferred media bitrate. + virtual void OnEncoderReconfigured( + const VideoEncoderConfig& encoder_config, + const std::vector& streams) = 0; + + virtual void OnAdaptationChanged(AdaptationReason reason, + const AdaptationSteps& cpu_steps, + const AdaptationSteps& quality_steps) = 0; + virtual void OnMinPixelLimitReached() = 0; + virtual void OnInitialQualityResolutionAdaptDown() = 0; + + virtual void OnSuspendChange(bool is_suspended) = 0; + + // TODO(nisse): VideoStreamEncoder wants to query the stats, which makes this + // not a pure observer. GetInputFrameRate is needed for the cpu adaptation, so + // can be deleted if that responsibility is moved out to a VideoStreamAdaptor + // class. + virtual int GetInputFrameRate() const = 0; +}; + +} // namespace webrtc +#endif // API_VIDEO_VIDEO_STREAM_ENCODER_OBSERVER_H_ diff --git a/api/video/video_stream_encoder_settings.h b/api/video/video_stream_encoder_settings.h new file mode 100644 index 0000000000..b67f33c982 --- /dev/null +++ b/api/video/video_stream_encoder_settings.h @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2018 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef API_VIDEO_VIDEO_STREAM_ENCODER_SETTINGS_H_ +#define API_VIDEO_VIDEO_STREAM_ENCODER_SETTINGS_H_ + +#include "api/video_codecs/video_encoder_factory.h" + +namespace webrtc { + +struct VideoStreamEncoderSettings { + VideoStreamEncoderSettings() = default; + + // Enables the new method to estimate the cpu load from encoding, used for + // cpu adaptation. + bool experiment_cpu_load_estimator = false; + + // Ownership stays with WebrtcVideoEngine (delegated from PeerConnection). + VideoEncoderFactory* encoder_factory = nullptr; +}; + +} // namespace webrtc + +#endif // API_VIDEO_VIDEO_STREAM_ENCODER_SETTINGS_H_ diff --git a/call/BUILD.gn b/call/BUILD.gn index afba0a4e2b..6819361ea3 100644 --- a/call/BUILD.gn +++ b/call/BUILD.gn @@ -242,6 +242,7 @@ rtc_source_set("video_stream_api") { "../api:libjingle_peerconnection_api", "../api:transport_api", "../api/video:video_frame", + "../api/video:video_stream_encoder", "../api/video_codecs:video_codecs_api", "../common_video:common_video", "../modules/rtp_rtcp:rtp_rtcp_format", diff --git a/call/video_send_stream.cc b/call/video_send_stream.cc index bb590fa170..6b93fe2823 100644 --- a/call/video_send_stream.cc +++ b/call/video_send_stream.cc @@ -72,7 +72,8 @@ VideoSendStream::Config::Config::~Config() = default; std::string VideoSendStream::Config::ToString() const { char buf[2 * 1024]; rtc::SimpleStringBuilder ss(buf); - ss << "{encoder_settings: " << encoder_settings.ToString(); + ss << "{encoder_settings: { experiment_cpu_load_estimator: " + << (encoder_settings.experiment_cpu_load_estimator ? "on" : "off") << "}}"; ss << ", rtp: " << rtp.ToString(); ss << ", rtcp: " << rtcp.ToString(); ss << ", pre_encode_callback: " @@ -87,12 +88,4 @@ std::string VideoSendStream::Config::ToString() const { return ss.str(); } -std::string VideoSendStream::Config::EncoderSettings::ToString() const { - char buf[1024]; - rtc::SimpleStringBuilder ss(buf); - ss << "{encoder_factory: " - << (encoder_factory ? "(VideoEncoderFactory)" : "(nullptr)"); - ss << '}'; - return ss.str(); -} } // namespace webrtc diff --git a/call/video_send_stream.h b/call/video_send_stream.h index 428ae201ad..ef98ae4094 100644 --- a/call/video_send_stream.h +++ b/call/video_send_stream.h @@ -19,6 +19,7 @@ #include "api/call/transport.h" #include "api/video/video_sink_interface.h" #include "api/video/video_source_interface.h" +#include "api/video/video_stream_encoder_settings.h" #include "api/video_codecs/video_encoder_config.h" #include "api/video_codecs/video_encoder_factory.h" #include "call/rtp_config.h" @@ -104,17 +105,7 @@ class VideoSendStream { std::string ToString() const; - struct EncoderSettings { - EncoderSettings() = default; - std::string ToString() const; - - // Enables the new method to estimate the cpu load from encoding, used for - // cpu adaptation. - bool experiment_cpu_load_estimator = false; - - // Ownership stays with WebrtcVideoEngine (delegated from PeerConnection). - VideoEncoderFactory* encoder_factory = nullptr; - } encoder_settings; + VideoStreamEncoderSettings encoder_settings; RtpConfig rtp; diff --git a/video/BUILD.gn b/video/BUILD.gn index 844941ac4c..3c9cdb37e0 100644 --- a/video/BUILD.gn +++ b/video/BUILD.gn @@ -14,8 +14,6 @@ rtc_static_library("video") { "call_stats.h", "encoder_rtcp_feedback.cc", "encoder_rtcp_feedback.h", - "overuse_frame_detector.cc", - "overuse_frame_detector.h", "quality_threshold.cc", "quality_threshold.h", "receive_statistics_proxy.cc", @@ -46,8 +44,6 @@ rtc_static_library("video") { "video_send_stream_impl.h", "video_stream_decoder.cc", "video_stream_decoder.h", - "video_stream_encoder.cc", - "video_stream_encoder.h", ] if (!build_with_chromium && is_clang) { @@ -65,6 +61,7 @@ rtc_static_library("video") { "../api/video:video_frame", "../api/video:video_frame_i420", "../api/video:video_stream_encoder", + "../api/video:video_stream_encoder_create", "../api/video_codecs:video_codecs_api", "../call:bitrate_allocator", "../call:call_interfaces", @@ -137,6 +134,50 @@ rtc_source_set("video_stream_decoder_impl") { ] } +rtc_source_set("video_stream_encoder_impl") { + visibility = [ "*" ] + + # visibility = [ "../api/video:video_stream_encoder_create" ] + # In modules/video_coding, there's a dependency video_coding --> webrtc_vp8 + allow_poison = [ "software_video_codecs" ] # TODO(bugs.webrtc.org/7925): Remove. + sources = [ + "overuse_frame_detector.cc", + "overuse_frame_detector.h", + "video_stream_encoder.cc", + "video_stream_encoder.h", + ] + + if (!build_with_chromium && is_clang) { + # Suppress warnings from the Chromium Clang plugin (bugs.webrtc.org/163). + suppressed_configs += [ "//build/config/clang:find_bad_constructs" ] + } + + deps = [ + "../api/video:video_bitrate_allocator", + "../api/video:video_frame", + "../api/video:video_frame_i420", + "../api/video:video_stream_encoder", + "../api/video_codecs:video_codecs_api", + "../common_video:common_video", + "../modules/video_coding", + "../modules/video_coding:video_coding_utility", + "../rtc_base:checks", + "../rtc_base:criticalsection", + "../rtc_base:logging", + "../rtc_base:macromagic", + "../rtc_base:rtc_base_approved", + "../rtc_base:rtc_event", + "../rtc_base:rtc_numerics", + "../rtc_base:rtc_task_queue", + "../rtc_base:sequenced_task_checker", + "../rtc_base:timeutils", + "../rtc_base/experiments:quality_scaling_experiment", + "../rtc_base/system:fallthrough", + "../system_wrappers:field_trial_api", + "//third_party/abseil-cpp/absl/types:optional", + ] +} + if (rtc_include_tests) { rtc_source_set("video_mocks") { testonly = true @@ -144,7 +185,7 @@ if (rtc_include_tests) { "test/mock_video_stream_encoder.h", ] deps = [ - ":video", + "../api/video:video_stream_encoder", "../test:test_support", ] } @@ -380,6 +421,7 @@ if (rtc_include_tests) { deps = [ ":video", ":video_mocks", + ":video_stream_encoder_impl", "../api/video:video_frame", "../api/video:video_frame_i420", "../api/video_codecs:video_codecs_api", diff --git a/video/encoder_rtcp_feedback.cc b/video/encoder_rtcp_feedback.cc index f88bca94dd..8b680b260f 100644 --- a/video/encoder_rtcp_feedback.cc +++ b/video/encoder_rtcp_feedback.cc @@ -10,8 +10,8 @@ #include "video/encoder_rtcp_feedback.h" +#include "api/video/video_stream_encoder_interface.h" #include "rtc_base/checks.h" -#include "video/video_stream_encoder.h" static const int kMinKeyFrameRequestIntervalMs = 300; diff --git a/video/overuse_frame_detector.cc b/video/overuse_frame_detector.cc index 77cca6117f..0dfc29ef4e 100644 --- a/video/overuse_frame_detector.cc +++ b/video/overuse_frame_detector.cc @@ -552,11 +552,10 @@ void OveruseFrameDetector::StopCheckForOveruse() { void OveruseFrameDetector::EncodedFrameTimeMeasured(int encode_duration_ms) { RTC_DCHECK_CALLED_SEQUENTIALLY(&task_checker_); - if (!metrics_) - metrics_ = CpuOveruseMetrics(); - metrics_->encode_usage_percent = usage_->Value(); + encode_usage_percent_ = usage_->Value(); - metrics_observer_->OnEncodedFrameTimeMeasured(encode_duration_ms, *metrics_); + metrics_observer_->OnEncodedFrameTimeMeasured(encode_duration_ms, + *encode_usage_percent_); } bool OveruseFrameDetector::FrameSizeChanged(int num_pixels) const { @@ -583,7 +582,7 @@ void OveruseFrameDetector::ResetAll(int num_pixels) { usage_->Reset(); last_capture_time_us_ = -1; num_process_times_ = 0; - metrics_ = absl::nullopt; + encode_usage_percent_ = absl::nullopt; OnTargetFramerateUpdated(max_framerate_); } @@ -627,12 +626,13 @@ void OveruseFrameDetector::CheckForOveruse( RTC_DCHECK_CALLED_SEQUENTIALLY(&task_checker_); RTC_DCHECK(observer); ++num_process_times_; - if (num_process_times_ <= options_.min_process_count || !metrics_) + if (num_process_times_ <= options_.min_process_count || + !encode_usage_percent_) return; int64_t now_ms = rtc::TimeMillis(); - if (IsOverusing(*metrics_)) { + if (IsOverusing(*encode_usage_percent_)) { // If the last thing we did was going up, and now have to back down, we need // to check if this peak was short. If so we should back off to avoid going // back and forth between this load, the system doesn't seem to handle it. @@ -656,7 +656,7 @@ void OveruseFrameDetector::CheckForOveruse( ++num_overuse_detections_; observer->AdaptDown(kScaleReasonCpu); - } else if (IsUnderusing(*metrics_, now_ms)) { + } else if (IsUnderusing(*encode_usage_percent_, now_ms)) { last_rampup_time_ms_ = now_ms; in_quick_rampup_ = true; @@ -667,7 +667,7 @@ void OveruseFrameDetector::CheckForOveruse( in_quick_rampup_ ? kQuickRampUpDelayMs : current_rampup_delay_ms_; RTC_LOG(LS_VERBOSE) << " Frame stats: " - << " encode usage " << metrics_->encode_usage_percent + << " encode usage " << *encode_usage_percent_ << " overuse detections " << num_overuse_detections_ << " rampup delay " << rampup_delay; } @@ -680,11 +680,10 @@ void OveruseFrameDetector::SetOptions(const CpuOveruseOptions& options) { usage_ = CreateProcessingUsage(options); } -bool OveruseFrameDetector::IsOverusing(const CpuOveruseMetrics& metrics) { +bool OveruseFrameDetector::IsOverusing(int usage_percent) { RTC_DCHECK_CALLED_SEQUENTIALLY(&task_checker_); - if (metrics.encode_usage_percent >= - options_.high_encode_usage_threshold_percent) { + if (usage_percent >= options_.high_encode_usage_threshold_percent) { ++checks_above_threshold_; } else { checks_above_threshold_ = 0; @@ -692,14 +691,12 @@ bool OveruseFrameDetector::IsOverusing(const CpuOveruseMetrics& metrics) { return checks_above_threshold_ >= options_.high_threshold_consecutive_count; } -bool OveruseFrameDetector::IsUnderusing(const CpuOveruseMetrics& metrics, - int64_t time_now) { +bool OveruseFrameDetector::IsUnderusing(int usage_percent, int64_t time_now) { RTC_DCHECK_CALLED_SEQUENTIALLY(&task_checker_); int delay = in_quick_rampup_ ? kQuickRampUpDelayMs : current_rampup_delay_ms_; if (time_now < last_rampup_time_ms_ + delay) return false; - return metrics.encode_usage_percent < - options_.low_encode_usage_threshold_percent; + return usage_percent < options_.low_encode_usage_threshold_percent; } } // namespace webrtc diff --git a/video/overuse_frame_detector.h b/video/overuse_frame_detector.h index c3f3cfa052..ea0d76dd90 100644 --- a/video/overuse_frame_detector.h +++ b/video/overuse_frame_detector.h @@ -15,6 +15,7 @@ #include #include "absl/types/optional.h" +#include "api/video/video_stream_encoder_observer.h" #include "modules/video_coding/utility/quality_scaler.h" #include "rtc_base/constructormagic.h" #include "rtc_base/numerics/exp_filter.h" @@ -44,20 +45,6 @@ struct CpuOveruseOptions { int filter_time_ms; // Time constant for averaging }; -struct CpuOveruseMetrics { - CpuOveruseMetrics() : encode_usage_percent(-1) {} - - int encode_usage_percent; // Average encode time divided by the average time - // difference between incoming captured frames. -}; - -class CpuOveruseMetricsObserver { - public: - virtual ~CpuOveruseMetricsObserver() {} - virtual void OnEncodedFrameTimeMeasured(int encode_duration_ms, - const CpuOveruseMetrics& metrics) = 0; -}; - // Use to detect system overuse based on the send-side processing time of // incoming frames. All methods must be called on a single task queue but it can // be created and destroyed on an arbitrary thread. @@ -124,8 +111,8 @@ class OveruseFrameDetector { class CheckOveruseTask; void EncodedFrameTimeMeasured(int encode_duration_ms); - bool IsOverusing(const CpuOveruseMetrics& metrics); - bool IsUnderusing(const CpuOveruseMetrics& metrics, int64_t time_now); + bool IsOverusing(int encode_usage_percent); + bool IsUnderusing(int encode_usage_percent, int64_t time_now); bool FrameTimeoutDetected(int64_t now) const; bool FrameSizeChanged(int num_pixels) const; @@ -141,7 +128,7 @@ class OveruseFrameDetector { // Stats metrics. CpuOveruseMetricsObserver* const metrics_observer_; - absl::optional metrics_ RTC_GUARDED_BY(task_checker_); + absl::optional encode_usage_percent_ RTC_GUARDED_BY(task_checker_); int64_t num_process_times_ RTC_GUARDED_BY(task_checker_); diff --git a/video/overuse_frame_detector_unittest.cc b/video/overuse_frame_detector_unittest.cc index 5ebc203b46..41db0f00f6 100644 --- a/video/overuse_frame_detector_unittest.cc +++ b/video/overuse_frame_detector_unittest.cc @@ -77,8 +77,8 @@ class OveruseFrameDetectorTest : public ::testing::Test, } void OnEncodedFrameTimeMeasured(int encode_time_ms, - const CpuOveruseMetrics& metrics) override { - metrics_ = metrics; + int encode_usage_percent) override { + encode_usage_percent_ = encode_usage_percent; } int InitialUsage() { @@ -165,7 +165,7 @@ class OveruseFrameDetectorTest : public ::testing::Test, overuse_detector_->CheckForOveruse(observer_); } - int UsagePercent() { return metrics_.encode_usage_percent; } + int UsagePercent() { return encode_usage_percent_; } int64_t OveruseProcessingTimeLimitForFramerate(int fps) const { int64_t frame_interval = rtc::kNumMicrosecsPerSec / fps; @@ -186,7 +186,7 @@ class OveruseFrameDetectorTest : public ::testing::Test, MockCpuOveruseObserver mock_observer_; AdaptationObserverInterface* observer_; std::unique_ptr overuse_detector_; - CpuOveruseMetrics metrics_; + int encode_usage_percent_ = -1; static const auto reason_ = AdaptationObserverInterface::AdaptReason::kCpu; }; diff --git a/video/send_statistics_proxy.cc b/video/send_statistics_proxy.cc index b446d193dd..dac3c03dad 100644 --- a/video/send_statistics_proxy.cc +++ b/video/send_statistics_proxy.cc @@ -653,14 +653,13 @@ void SendStatisticsProxy::OnEncoderReconfigured( streams.empty() ? 0 : (streams.back().width * streams.back().height); } -void SendStatisticsProxy::OnEncodedFrameTimeMeasured( - int encode_time_ms, - const CpuOveruseMetrics& metrics) { +void SendStatisticsProxy::OnEncodedFrameTimeMeasured(int encode_time_ms, + int encode_usage_percent) { rtc::CritScope lock(&crit_); uma_container_->encode_time_counter_.Add(encode_time_ms); encode_time_.Apply(1.0f, encode_time_ms); stats_.avg_encode_time_ms = round(encode_time_.filtered()); - stats_.encode_usage_percent = metrics.encode_usage_percent; + stats_.encode_usage_percent = encode_usage_percent; } void SendStatisticsProxy::OnSuspendChange(bool is_suspended) { @@ -960,6 +959,11 @@ void SendStatisticsProxy::OnSendEncodedImage( } } +int SendStatisticsProxy::GetInputFrameRate() const { + rtc::CritScope lock(&crit_); + return round(uma_container_->input_frame_rate_tracker_.ComputeRate()); +} + int SendStatisticsProxy::GetSendFrameRate() const { rtc::CritScope lock(&crit_); return round(encoded_frame_rate_tracker_.ComputeRate()); @@ -982,62 +986,55 @@ void SendStatisticsProxy::OnIncomingFrame(int width, int height) { } } -void SendStatisticsProxy::OnFrameDroppedBySource() { +void SendStatisticsProxy::OnFrameDropped(DropReason reason) { rtc::CritScope lock(&crit_); - ++stats_.frames_dropped_by_capturer; + switch (reason) { + case DropReason::kSource: + ++stats_.frames_dropped_by_capturer; + break; + case DropReason::kEncoderQueue: + ++stats_.frames_dropped_by_encoder_queue; + break; + case DropReason::kEncoder: + ++stats_.frames_dropped_by_encoder; + break; + case DropReason::kMediaOptimization: + ++stats_.frames_dropped_by_rate_limiter; + break; + } } -void SendStatisticsProxy::OnFrameDroppedInEncoderQueue() { +void SendStatisticsProxy::OnAdaptationChanged( + AdaptationReason reason, + const AdaptationSteps& cpu_counts, + const AdaptationSteps& quality_counts) { rtc::CritScope lock(&crit_); - ++stats_.frames_dropped_by_encoder_queue; -} - -void SendStatisticsProxy::OnFrameDroppedByEncoder() { - rtc::CritScope lock(&crit_); - ++stats_.frames_dropped_by_encoder; -} - -void SendStatisticsProxy::OnFrameDroppedByMediaOptimizations() { - rtc::CritScope lock(&crit_); - ++stats_.frames_dropped_by_rate_limiter; -} - -void SendStatisticsProxy::SetAdaptationStats( - const VideoStreamEncoder::AdaptCounts& cpu_counts, - const VideoStreamEncoder::AdaptCounts& quality_counts) { - rtc::CritScope lock(&crit_); - SetAdaptTimer(cpu_counts, &uma_container_->cpu_adapt_timer_); - SetAdaptTimer(quality_counts, &uma_container_->quality_adapt_timer_); - UpdateAdaptationStats(cpu_counts, quality_counts); -} - -void SendStatisticsProxy::OnCpuAdaptationChanged( - const VideoStreamEncoder::AdaptCounts& cpu_counts, - const VideoStreamEncoder::AdaptCounts& quality_counts) { - rtc::CritScope lock(&crit_); - ++stats_.number_of_cpu_adapt_changes; - UpdateAdaptationStats(cpu_counts, quality_counts); -} - -void SendStatisticsProxy::OnQualityAdaptationChanged( - const VideoStreamEncoder::AdaptCounts& cpu_counts, - const VideoStreamEncoder::AdaptCounts& quality_counts) { - rtc::CritScope lock(&crit_); - TryUpdateInitialQualityResolutionAdaptUp(quality_counts); - ++stats_.number_of_quality_adapt_changes; + switch (reason) { + case AdaptationReason::kNone: + SetAdaptTimer(cpu_counts, &uma_container_->cpu_adapt_timer_); + SetAdaptTimer(quality_counts, &uma_container_->quality_adapt_timer_); + break; + case AdaptationReason::kCpu: + ++stats_.number_of_cpu_adapt_changes; + break; + case AdaptationReason::kQuality: + TryUpdateInitialQualityResolutionAdaptUp(quality_counts); + ++stats_.number_of_quality_adapt_changes; + break; + } UpdateAdaptationStats(cpu_counts, quality_counts); } void SendStatisticsProxy::UpdateAdaptationStats( - const VideoStreamEncoder::AdaptCounts& cpu_counts, - const VideoStreamEncoder::AdaptCounts& quality_counts) { - cpu_downscales_ = cpu_counts.resolution; - quality_downscales_ = quality_counts.resolution; + const AdaptationSteps& cpu_counts, + const AdaptationSteps& quality_counts) { + cpu_downscales_ = cpu_counts.num_resolution_reductions.value_or(-1); + quality_downscales_ = quality_counts.num_resolution_reductions.value_or(-1); - stats_.cpu_limited_resolution = cpu_counts.resolution > 0; - stats_.cpu_limited_framerate = cpu_counts.fps > 0; - stats_.bw_limited_resolution = quality_counts.resolution > 0; - stats_.bw_limited_framerate = quality_counts.fps > 0; + stats_.cpu_limited_resolution = cpu_counts.num_resolution_reductions > 0; + stats_.cpu_limited_framerate = cpu_counts.num_framerate_reductions > 0; + stats_.bw_limited_resolution = quality_counts.num_resolution_reductions > 0; + stats_.bw_limited_framerate = quality_counts.num_framerate_reductions > 0; } // TODO(asapersson): Include fps changes. @@ -1047,12 +1044,13 @@ void SendStatisticsProxy::OnInitialQualityResolutionAdaptDown() { } void SendStatisticsProxy::TryUpdateInitialQualityResolutionAdaptUp( - const VideoStreamEncoder::AdaptCounts& quality_counts) { + const AdaptationSteps& quality_counts) { if (uma_container_->initial_quality_changes_.down == 0) return; if (quality_downscales_ > 0 && - quality_counts.resolution < quality_downscales_) { + quality_counts.num_resolution_reductions.value_or(-1) < + quality_downscales_) { // Adapting up in quality. if (uma_container_->initial_quality_changes_.down > uma_container_->initial_quality_changes_.up) { @@ -1061,10 +1059,9 @@ void SendStatisticsProxy::TryUpdateInitialQualityResolutionAdaptUp( } } -void SendStatisticsProxy::SetAdaptTimer( - const VideoStreamEncoder::AdaptCounts& counts, - StatsTimer* timer) { - if (counts.resolution >= 0 || counts.fps >= 0) { +void SendStatisticsProxy::SetAdaptTimer(const AdaptationSteps& counts, + StatsTimer* timer) { + if (counts.num_resolution_reductions || counts.num_framerate_reductions) { // Adaptation enabled. if (!stats_.suspended) timer->Start(clock_->TimeInMilliseconds()); diff --git a/video/send_statistics_proxy.h b/video/send_statistics_proxy.h index 5bc6c90cdd..97b4a4afe6 100644 --- a/video/send_statistics_proxy.h +++ b/video/send_statistics_proxy.h @@ -16,6 +16,7 @@ #include #include +#include "api/video/video_stream_encoder_observer.h" #include "call/video_send_stream.h" #include "common_types.h" // NOLINT(build/include) #include "modules/video_coding/include/video_codec_interface.h" @@ -25,14 +26,12 @@ #include "rtc_base/ratetracker.h" #include "rtc_base/thread_annotations.h" #include "system_wrappers/include/clock.h" -#include "video/overuse_frame_detector.h" #include "video/report_block_stats.h" #include "video/stats_counter.h" -#include "video/video_stream_encoder.h" namespace webrtc { -class SendStatisticsProxy : public CpuOveruseMetricsObserver, +class SendStatisticsProxy : public VideoStreamEncoderObserver, public RtcpStatisticsCallback, public RtcpPacketTypeCounterObserver, public StreamDataCountersCallback, @@ -53,44 +52,37 @@ class SendStatisticsProxy : public CpuOveruseMetricsObserver, virtual VideoSendStream::Stats GetStats(); void OnSendEncodedImage(const EncodedImage& encoded_image, - const CodecSpecificInfo* codec_info); + const CodecSpecificInfo* codec_info) override; // Used to update incoming frame rate. - void OnIncomingFrame(int width, int height); + void OnIncomingFrame(int width, int height) override; // Dropped frame stats. - void OnFrameDroppedBySource(); - void OnFrameDroppedInEncoderQueue(); - void OnFrameDroppedByEncoder(); - void OnFrameDroppedByMediaOptimizations(); + void OnFrameDropped(DropReason) override; // Adaptation stats. - void SetAdaptationStats( - const VideoStreamEncoder::AdaptCounts& cpu_counts, - const VideoStreamEncoder::AdaptCounts& quality_counts); - void OnCpuAdaptationChanged( - const VideoStreamEncoder::AdaptCounts& cpu_counts, - const VideoStreamEncoder::AdaptCounts& quality_counts); - void OnQualityAdaptationChanged( - const VideoStreamEncoder::AdaptCounts& cpu_counts, - const VideoStreamEncoder::AdaptCounts& quality_counts); - void OnMinPixelLimitReached(); - void OnInitialQualityResolutionAdaptDown(); + void OnAdaptationChanged(AdaptationReason reason, + const AdaptationSteps& cpu_counts, + const AdaptationSteps& quality_counts) override; - void OnSuspendChange(bool is_suspended); + void OnMinPixelLimitReached() override; + void OnInitialQualityResolutionAdaptDown() override; + + void OnSuspendChange(bool is_suspended) override; void OnInactiveSsrc(uint32_t ssrc); // Used to indicate change in content type, which may require a change in // how stats are collected. void OnEncoderReconfigured(const VideoEncoderConfig& encoder_config, - const std::vector& streams); + const std::vector& streams) override; // Used to update the encoder target rate. void OnSetEncoderTargetRate(uint32_t bitrate_bps); // Implements CpuOveruseMetricsObserver. void OnEncodedFrameTimeMeasured(int encode_time_ms, - const CpuOveruseMetrics& metrics) override; + int encode_usage_percent) override; + int GetInputFrameRate() const override; int GetSendFrameRate() const; protected: @@ -216,14 +208,13 @@ class SendStatisticsProxy : public CpuOveruseMetricsObserver, VideoSendStream::StreamStats* GetStatsEntry(uint32_t ssrc) RTC_EXCLUSIVE_LOCKS_REQUIRED(crit_); - void SetAdaptTimer(const VideoStreamEncoder::AdaptCounts& counts, - StatsTimer* timer) RTC_EXCLUSIVE_LOCKS_REQUIRED(crit_); - void UpdateAdaptationStats( - const VideoStreamEncoder::AdaptCounts& cpu_counts, - const VideoStreamEncoder::AdaptCounts& quality_counts) + void SetAdaptTimer(const AdaptationSteps& counts, StatsTimer* timer) + RTC_EXCLUSIVE_LOCKS_REQUIRED(crit_); + void UpdateAdaptationStats(const AdaptationSteps& cpu_counts, + const AdaptationSteps& quality_counts) RTC_EXCLUSIVE_LOCKS_REQUIRED(crit_); void TryUpdateInitialQualityResolutionAdaptUp( - const VideoStreamEncoder::AdaptCounts& quality_counts) + const AdaptationSteps& quality_counts) RTC_EXCLUSIVE_LOCKS_REQUIRED(crit_); void UpdateEncoderFallbackStats(const CodecSpecificInfo* codec_info, diff --git a/video/send_statistics_proxy_unittest.cc b/video/send_statistics_proxy_unittest.cc index ee4ef5d6f9..f4e2fe7486 100644 --- a/video/send_statistics_proxy_unittest.cc +++ b/video/send_statistics_proxy_unittest.cc @@ -309,13 +309,13 @@ TEST_F(SendStatisticsProxyTest, SendSideDelay) { TEST_F(SendStatisticsProxyTest, OnEncodedFrameTimeMeasured) { const int kEncodeTimeMs = 11; - CpuOveruseMetrics metrics; - metrics.encode_usage_percent = 80; - statistics_proxy_->OnEncodedFrameTimeMeasured(kEncodeTimeMs, metrics); + int encode_usage_percent = 80; + statistics_proxy_->OnEncodedFrameTimeMeasured(kEncodeTimeMs, + encode_usage_percent); VideoSendStream::Stats stats = statistics_proxy_->GetStats(); EXPECT_EQ(kEncodeTimeMs, stats.avg_encode_time_ms); - EXPECT_EQ(metrics.encode_usage_percent, stats.encode_usage_percent); + EXPECT_EQ(encode_usage_percent, stats.encode_usage_percent); } TEST_F(SendStatisticsProxyTest, OnSendEncodedImageIncreasesFramesEncoded) { @@ -350,72 +350,92 @@ TEST_F(SendStatisticsProxyTest, OnSendEncodedImageWithoutQpQpSumWontExist) { } TEST_F(SendStatisticsProxyTest, GetCpuAdaptationStats) { - VideoStreamEncoder::AdaptCounts cpu_counts; - VideoStreamEncoder::AdaptCounts quality_counts; + SendStatisticsProxy::AdaptationSteps cpu_counts; + SendStatisticsProxy::AdaptationSteps quality_counts; EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_framerate); EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_resolution); - cpu_counts.fps = 1; - cpu_counts.resolution = 0; - statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts); + cpu_counts.num_framerate_reductions = 1; + cpu_counts.num_resolution_reductions = 0; + statistics_proxy_->OnAdaptationChanged( + VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts, + quality_counts); EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_framerate); EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_resolution); - cpu_counts.fps = 0; - cpu_counts.resolution = 1; - statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts); + cpu_counts.num_framerate_reductions = 0; + cpu_counts.num_resolution_reductions = 1; + statistics_proxy_->OnAdaptationChanged( + VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts, + quality_counts); EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_framerate); EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_resolution); - cpu_counts.fps = 1; - cpu_counts.resolution = -1; - statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts); + cpu_counts.num_framerate_reductions = 1; + cpu_counts.num_resolution_reductions = absl::nullopt; + statistics_proxy_->OnAdaptationChanged( + VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts, + quality_counts); EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_framerate); EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_resolution); - cpu_counts.fps = -1; - cpu_counts.resolution = -1; - statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts); + cpu_counts.num_framerate_reductions = absl::nullopt; + cpu_counts.num_resolution_reductions = absl::nullopt; + statistics_proxy_->OnAdaptationChanged( + VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts, + quality_counts); EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_framerate); EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_resolution); } TEST_F(SendStatisticsProxyTest, GetQualityAdaptationStats) { - VideoStreamEncoder::AdaptCounts cpu_counts; - VideoStreamEncoder::AdaptCounts quality_counts; + SendStatisticsProxy::AdaptationSteps cpu_counts; + SendStatisticsProxy::AdaptationSteps quality_counts; EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate); EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution); - quality_counts.fps = 1; - quality_counts.resolution = 0; - statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts); + quality_counts.num_framerate_reductions = 1; + quality_counts.num_resolution_reductions = 0; + statistics_proxy_->OnAdaptationChanged( + VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts, + quality_counts); EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_framerate); EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution); - quality_counts.fps = 0; - quality_counts.resolution = 1; - statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts); + quality_counts.num_framerate_reductions = 0; + quality_counts.num_resolution_reductions = 1; + statistics_proxy_->OnAdaptationChanged( + VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts, + quality_counts); EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate); EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution); - quality_counts.fps = 1; - quality_counts.resolution = -1; - statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts); + quality_counts.num_framerate_reductions = 1; + quality_counts.num_resolution_reductions = absl::nullopt; + statistics_proxy_->OnAdaptationChanged( + VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts, + quality_counts); EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_framerate); EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution); - quality_counts.fps = -1; - quality_counts.resolution = -1; - statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts); + quality_counts.num_framerate_reductions = absl::nullopt; + quality_counts.num_resolution_reductions = absl::nullopt; + statistics_proxy_->OnAdaptationChanged( + VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts, + quality_counts); EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate); EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution); } TEST_F(SendStatisticsProxyTest, GetStatsReportsCpuAdaptChanges) { - VideoStreamEncoder::AdaptCounts cpu_counts; - VideoStreamEncoder::AdaptCounts quality_counts; + SendStatisticsProxy::AdaptationSteps cpu_counts; + SendStatisticsProxy::AdaptationSteps quality_counts; EXPECT_EQ(0, statistics_proxy_->GetStats().number_of_cpu_adapt_changes); - cpu_counts.resolution = 1; - statistics_proxy_->OnCpuAdaptationChanged(cpu_counts, quality_counts); + cpu_counts.num_resolution_reductions = 1; + statistics_proxy_->OnAdaptationChanged( + VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts, + quality_counts); EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_framerate); EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_resolution); EXPECT_EQ(1, statistics_proxy_->GetStats().number_of_cpu_adapt_changes); - cpu_counts.resolution = 2; - statistics_proxy_->OnCpuAdaptationChanged(cpu_counts, quality_counts); + cpu_counts.num_resolution_reductions = 2; + statistics_proxy_->OnAdaptationChanged( + VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts, + quality_counts); EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_framerate); EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_resolution); EXPECT_EQ(2, statistics_proxy_->GetStats().number_of_cpu_adapt_changes); @@ -423,18 +443,22 @@ TEST_F(SendStatisticsProxyTest, GetStatsReportsCpuAdaptChanges) { } TEST_F(SendStatisticsProxyTest, GetStatsReportsQualityAdaptChanges) { - VideoStreamEncoder::AdaptCounts cpu_counts; - VideoStreamEncoder::AdaptCounts quality_counts; + SendStatisticsProxy::AdaptationSteps cpu_counts; + SendStatisticsProxy::AdaptationSteps quality_counts; EXPECT_EQ(0, statistics_proxy_->GetStats().number_of_quality_adapt_changes); - quality_counts.fps = 1; - statistics_proxy_->OnQualityAdaptationChanged(cpu_counts, quality_counts); + quality_counts.num_framerate_reductions = 1; + statistics_proxy_->OnAdaptationChanged( + VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts, + quality_counts); EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_framerate); EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution); EXPECT_EQ(1, statistics_proxy_->GetStats().number_of_quality_adapt_changes); - quality_counts.fps = 0; - statistics_proxy_->OnQualityAdaptationChanged(cpu_counts, quality_counts); + quality_counts.num_framerate_reductions = 0; + statistics_proxy_->OnAdaptationChanged( + VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts, + quality_counts); EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate); EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution); EXPECT_EQ(2, statistics_proxy_->GetStats().number_of_quality_adapt_changes); @@ -456,9 +480,11 @@ TEST_F(SendStatisticsProxyTest, AdaptChangesNotReported_MinRuntimeNotPassed) { // First RTP packet sent. UpdateDataCounters(kFirstSsrc); // Enable adaptation. - VideoStreamEncoder::AdaptCounts cpu_counts; - VideoStreamEncoder::AdaptCounts quality_counts; - statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts); + SendStatisticsProxy::AdaptationSteps cpu_counts; + SendStatisticsProxy::AdaptationSteps quality_counts; + statistics_proxy_->OnAdaptationChanged( + VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts, + quality_counts); // Min runtime has not passed. fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000 - 1); statistics_proxy_.reset(); @@ -471,9 +497,11 @@ TEST_F(SendStatisticsProxyTest, ZeroAdaptChangesReported) { // First RTP packet sent. UpdateDataCounters(kFirstSsrc); // Enable adaptation. - VideoStreamEncoder::AdaptCounts cpu_counts; - VideoStreamEncoder::AdaptCounts quality_counts; - statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts); + SendStatisticsProxy::AdaptationSteps cpu_counts; + SendStatisticsProxy::AdaptationSteps quality_counts; + statistics_proxy_->OnAdaptationChanged( + VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts, + quality_counts); // Min runtime has passed. fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000); statistics_proxy_.reset(); @@ -489,11 +517,15 @@ TEST_F(SendStatisticsProxyTest, CpuAdaptChangesReported) { // First RTP packet sent. UpdateDataCounters(kFirstSsrc); // Enable adaptation. - VideoStreamEncoder::AdaptCounts cpu_counts; - VideoStreamEncoder::AdaptCounts quality_counts; - statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts); + SendStatisticsProxy::AdaptationSteps cpu_counts; + SendStatisticsProxy::AdaptationSteps quality_counts; + statistics_proxy_->OnAdaptationChanged( + VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts, + quality_counts); // Adapt changes: 1, elapsed time: 10 sec => 6 per minute. - statistics_proxy_->OnCpuAdaptationChanged(cpu_counts, quality_counts); + statistics_proxy_->OnAdaptationChanged( + VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts, + quality_counts); fake_clock_.AdvanceTimeMilliseconds(10000); statistics_proxy_.reset(); EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu")); @@ -504,11 +536,15 @@ TEST_F(SendStatisticsProxyTest, ExcludesInitialQualityAdaptDownChange) { // First RTP packet sent. UpdateDataCounters(kFirstSsrc); // Enable adaptation. - VideoStreamEncoder::AdaptCounts cpu_counts; - VideoStreamEncoder::AdaptCounts quality_counts; - statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts); + SendStatisticsProxy::AdaptationSteps cpu_counts; + SendStatisticsProxy::AdaptationSteps quality_counts; + statistics_proxy_->OnAdaptationChanged( + VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts, + quality_counts); // Adapt changes: 1 (1 initial) = 0, elapsed time: 10 sec => 0 per minute. - statistics_proxy_->OnQualityAdaptationChanged(cpu_counts, quality_counts); + statistics_proxy_->OnAdaptationChanged( + VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts, + quality_counts); statistics_proxy_->OnInitialQualityResolutionAdaptDown(); fake_clock_.AdvanceTimeMilliseconds(10000); statistics_proxy_.reset(); @@ -522,18 +558,26 @@ TEST_F(SendStatisticsProxyTest, ExcludesInitialQualityAdaptDownChanges) { // First RTP packet sent. UpdateDataCounters(kFirstSsrc); // Enable adaptation. - VideoStreamEncoder::AdaptCounts cpu_counts; - VideoStreamEncoder::AdaptCounts quality_counts; - statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts); + SendStatisticsProxy::AdaptationSteps cpu_counts; + SendStatisticsProxy::AdaptationSteps quality_counts; + statistics_proxy_->OnAdaptationChanged( + VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts, + quality_counts); // Adapt changes: 3 (2 initial) = 1, elapsed time: 10 sec => 6 per minute. - quality_counts.resolution = 1; - statistics_proxy_->OnQualityAdaptationChanged(cpu_counts, quality_counts); + quality_counts.num_resolution_reductions = 1; + statistics_proxy_->OnAdaptationChanged( + VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts, + quality_counts); statistics_proxy_->OnInitialQualityResolutionAdaptDown(); - quality_counts.resolution = 2; - statistics_proxy_->OnQualityAdaptationChanged(cpu_counts, quality_counts); + quality_counts.num_resolution_reductions = 2; + statistics_proxy_->OnAdaptationChanged( + VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts, + quality_counts); statistics_proxy_->OnInitialQualityResolutionAdaptDown(); - quality_counts.resolution = 3; - statistics_proxy_->OnQualityAdaptationChanged(cpu_counts, quality_counts); + quality_counts.num_resolution_reductions = 3; + statistics_proxy_->OnAdaptationChanged( + VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts, + quality_counts); fake_clock_.AdvanceTimeMilliseconds(10000); statistics_proxy_.reset(); EXPECT_EQ(1, @@ -546,11 +590,15 @@ TEST_F(SendStatisticsProxyTest, InitialQualityAdaptChangesNotExcludedOnError) { // First RTP packet sent. UpdateDataCounters(kFirstSsrc); // Enable adaptation. - VideoStreamEncoder::AdaptCounts cpu_counts; - VideoStreamEncoder::AdaptCounts quality_counts; - statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts); + SendStatisticsProxy::AdaptationSteps cpu_counts; + SendStatisticsProxy::AdaptationSteps quality_counts; + statistics_proxy_->OnAdaptationChanged( + VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts, + quality_counts); // Adapt changes: 1 (2 initial) = 1, elapsed time: 10 sec => 6 per minute. - statistics_proxy_->OnQualityAdaptationChanged(cpu_counts, quality_counts); + statistics_proxy_->OnAdaptationChanged( + VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts, + quality_counts); statistics_proxy_->OnInitialQualityResolutionAdaptDown(); statistics_proxy_->OnInitialQualityResolutionAdaptDown(); fake_clock_.AdvanceTimeMilliseconds(10000); @@ -565,28 +613,46 @@ TEST_F(SendStatisticsProxyTest, ExcludesInitialQualityAdaptDownAndUpChanges) { // First RTP packet sent. UpdateDataCounters(kFirstSsrc); // Enable adaptation. - VideoStreamEncoder::AdaptCounts cpu_counts; - VideoStreamEncoder::AdaptCounts quality_counts; - statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts); + SendStatisticsProxy::AdaptationSteps cpu_counts; + SendStatisticsProxy::AdaptationSteps quality_counts; + statistics_proxy_->OnAdaptationChanged( + VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts, + quality_counts); // Adapt changes: 8 (4 initial) = 4, elapsed time: 10 sec => 24 per minute. - quality_counts.resolution = 1; - statistics_proxy_->OnQualityAdaptationChanged(cpu_counts, quality_counts); + quality_counts.num_resolution_reductions = 1; + statistics_proxy_->OnAdaptationChanged( + VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts, + quality_counts); statistics_proxy_->OnInitialQualityResolutionAdaptDown(); - quality_counts.resolution = 2; - statistics_proxy_->OnQualityAdaptationChanged(cpu_counts, quality_counts); + quality_counts.num_resolution_reductions = 2; + statistics_proxy_->OnAdaptationChanged( + VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts, + quality_counts); statistics_proxy_->OnInitialQualityResolutionAdaptDown(); - quality_counts.resolution = 3; - statistics_proxy_->OnQualityAdaptationChanged(cpu_counts, quality_counts); - quality_counts.fps = 1; - statistics_proxy_->OnQualityAdaptationChanged(cpu_counts, quality_counts); - quality_counts.fps = 0; - statistics_proxy_->OnQualityAdaptationChanged(cpu_counts, quality_counts); - quality_counts.resolution = 2; // Initial resolution up. - statistics_proxy_->OnQualityAdaptationChanged(cpu_counts, quality_counts); - quality_counts.resolution = 1; // Initial resolution up. - statistics_proxy_->OnQualityAdaptationChanged(cpu_counts, quality_counts); - quality_counts.resolution = 0; - statistics_proxy_->OnQualityAdaptationChanged(cpu_counts, quality_counts); + quality_counts.num_resolution_reductions = 3; + statistics_proxy_->OnAdaptationChanged( + VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts, + quality_counts); + quality_counts.num_framerate_reductions = 1; + statistics_proxy_->OnAdaptationChanged( + VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts, + quality_counts); + quality_counts.num_framerate_reductions = 0; + statistics_proxy_->OnAdaptationChanged( + VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts, + quality_counts); + quality_counts.num_resolution_reductions = 2; // Initial resolution up. + statistics_proxy_->OnAdaptationChanged( + VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts, + quality_counts); + quality_counts.num_resolution_reductions = 1; // Initial resolution up. + statistics_proxy_->OnAdaptationChanged( + VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts, + quality_counts); + quality_counts.num_resolution_reductions = 0; + statistics_proxy_->OnAdaptationChanged( + VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts, + quality_counts); fake_clock_.AdvanceTimeMilliseconds(10000); statistics_proxy_.reset(); @@ -601,41 +667,61 @@ TEST_F(SendStatisticsProxyTest, AdaptChangesStatsExcludesDisabledTime) { UpdateDataCounters(kFirstSsrc); // Disable quality adaptation. - VideoStreamEncoder::AdaptCounts cpu_counts; - VideoStreamEncoder::AdaptCounts quality_counts; - quality_counts.fps = -1; - quality_counts.resolution = -1; - statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts); + SendStatisticsProxy::AdaptationSteps cpu_counts; + SendStatisticsProxy::AdaptationSteps quality_counts; + quality_counts.num_framerate_reductions = absl::nullopt; + quality_counts.num_resolution_reductions = absl::nullopt; + statistics_proxy_->OnAdaptationChanged( + VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts, + quality_counts); fake_clock_.AdvanceTimeMilliseconds(10000); // Enable quality adaptation. // Adapt changes: 2, elapsed time: 20 sec. - quality_counts.fps = 0; - statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts); + quality_counts.num_framerate_reductions = 0; + statistics_proxy_->OnAdaptationChanged( + VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts, + quality_counts); fake_clock_.AdvanceTimeMilliseconds(5000); - statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts); + statistics_proxy_->OnAdaptationChanged( + VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts, + quality_counts); fake_clock_.AdvanceTimeMilliseconds(9000); - statistics_proxy_->OnQualityAdaptationChanged(cpu_counts, quality_counts); + statistics_proxy_->OnAdaptationChanged( + VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts, + quality_counts); fake_clock_.AdvanceTimeMilliseconds(6000); - statistics_proxy_->OnQualityAdaptationChanged(cpu_counts, quality_counts); + statistics_proxy_->OnAdaptationChanged( + VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts, + quality_counts); // Disable quality adaptation. - quality_counts.fps = -1; - statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts); + quality_counts.num_framerate_reductions = absl::nullopt; + statistics_proxy_->OnAdaptationChanged( + VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts, + quality_counts); fake_clock_.AdvanceTimeMilliseconds(30000); // Enable quality adaptation. // Adapt changes: 1, elapsed time: 10 sec. - quality_counts.resolution = 0; - statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts); - statistics_proxy_->OnQualityAdaptationChanged(cpu_counts, quality_counts); + quality_counts.num_resolution_reductions = 0; + statistics_proxy_->OnAdaptationChanged( + VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts, + quality_counts); + statistics_proxy_->OnAdaptationChanged( + VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts, + quality_counts); fake_clock_.AdvanceTimeMilliseconds(10000); // Disable quality adaptation. - quality_counts.resolution = -1; - statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts); + quality_counts.num_resolution_reductions = absl::nullopt; + statistics_proxy_->OnAdaptationChanged( + VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts, + quality_counts); fake_clock_.AdvanceTimeMilliseconds(5000); - statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts); + statistics_proxy_->OnAdaptationChanged( + VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts, + quality_counts); fake_clock_.AdvanceTimeMilliseconds(20000); // Adapt changes: 3, elapsed time: 30 sec => 6 per minute. @@ -669,13 +755,19 @@ TEST_F(SendStatisticsProxyTest, QualityAdaptChangesStatsExcludesSuspendedTime) { UpdateDataCounters(kFirstSsrc); // Enable adaptation. - VideoStreamEncoder::AdaptCounts cpu_counts; - VideoStreamEncoder::AdaptCounts quality_counts; + SendStatisticsProxy::AdaptationSteps cpu_counts; + SendStatisticsProxy::AdaptationSteps quality_counts; // Adapt changes: 2, elapsed time: 20 sec. - statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts); + statistics_proxy_->OnAdaptationChanged( + VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts, + quality_counts); fake_clock_.AdvanceTimeMilliseconds(20000); - statistics_proxy_->OnQualityAdaptationChanged(cpu_counts, quality_counts); - statistics_proxy_->OnQualityAdaptationChanged(cpu_counts, quality_counts); + statistics_proxy_->OnAdaptationChanged( + VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts, + quality_counts); + statistics_proxy_->OnAdaptationChanged( + VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts, + quality_counts); // Suspend and resume video. statistics_proxy_->OnSuspendChange(true); @@ -683,7 +775,9 @@ TEST_F(SendStatisticsProxyTest, QualityAdaptChangesStatsExcludesSuspendedTime) { statistics_proxy_->OnSuspendChange(false); // Adapt changes: 1, elapsed time: 10 sec. - statistics_proxy_->OnQualityAdaptationChanged(cpu_counts, quality_counts); + statistics_proxy_->OnAdaptationChanged( + VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts, + quality_counts); fake_clock_.AdvanceTimeMilliseconds(10000); // Adapt changes: 3, elapsed time: 30 sec => 6 per minute. @@ -703,21 +797,27 @@ TEST_F(SendStatisticsProxyTest, CpuAdaptChangesStatsExcludesSuspendedTime) { fake_clock_.AdvanceTimeMilliseconds(30000); // Enable adaptation. - VideoStreamEncoder::AdaptCounts cpu_counts; - VideoStreamEncoder::AdaptCounts quality_counts; + SendStatisticsProxy::AdaptationSteps cpu_counts; + SendStatisticsProxy::AdaptationSteps quality_counts; // Adapt changes: 1, elapsed time: 20 sec. - statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts); + statistics_proxy_->OnAdaptationChanged( + VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts, + quality_counts); fake_clock_.AdvanceTimeMilliseconds(10000); - statistics_proxy_->OnCpuAdaptationChanged(cpu_counts, quality_counts); + statistics_proxy_->OnAdaptationChanged( + VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts, + quality_counts); // Video not suspended, stats time already started. statistics_proxy_->OnSuspendChange(false); fake_clock_.AdvanceTimeMilliseconds(10000); // Disable adaptation. - cpu_counts.fps = -1; - cpu_counts.resolution = -1; - statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts); + cpu_counts.num_framerate_reductions = absl::nullopt; + cpu_counts.num_resolution_reductions = absl::nullopt; + statistics_proxy_->OnAdaptationChanged( + VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts, + quality_counts); fake_clock_.AdvanceTimeMilliseconds(30000); // Suspend and resume video, stats time not started when scaling not enabled. @@ -728,11 +828,15 @@ TEST_F(SendStatisticsProxyTest, CpuAdaptChangesStatsExcludesSuspendedTime) { // Enable adaptation. // Adapt changes: 1, elapsed time: 10 sec. - cpu_counts.fps = 0; - cpu_counts.resolution = 0; - statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts); + cpu_counts.num_framerate_reductions = 0; + cpu_counts.num_resolution_reductions = 0; + statistics_proxy_->OnAdaptationChanged( + VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts, + quality_counts); fake_clock_.AdvanceTimeMilliseconds(10000); - statistics_proxy_->OnCpuAdaptationChanged(cpu_counts, quality_counts); + statistics_proxy_->OnAdaptationChanged( + VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts, + quality_counts); // Adapt changes: 2, elapsed time: 30 sec => 4 per minute. statistics_proxy_.reset(); @@ -748,16 +852,20 @@ TEST_F(SendStatisticsProxyTest, AdaptChangesStatsNotStartedIfVideoSuspended) { statistics_proxy_->OnSuspendChange(true); // Enable adaptation, stats time not started when suspended. - VideoStreamEncoder::AdaptCounts cpu_counts; - VideoStreamEncoder::AdaptCounts quality_counts; - statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts); + SendStatisticsProxy::AdaptationSteps cpu_counts; + SendStatisticsProxy::AdaptationSteps quality_counts; + statistics_proxy_->OnAdaptationChanged( + VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts, + quality_counts); fake_clock_.AdvanceTimeMilliseconds(10000); // Resume video, stats time started. // Adapt changes: 1, elapsed time: 10 sec. statistics_proxy_->OnSuspendChange(false); fake_clock_.AdvanceTimeMilliseconds(10000); - statistics_proxy_->OnCpuAdaptationChanged(cpu_counts, quality_counts); + statistics_proxy_->OnAdaptationChanged( + VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts, + quality_counts); // Adapt changes: 1, elapsed time: 10 sec => 6 per minute. statistics_proxy_.reset(); @@ -768,15 +876,19 @@ TEST_F(SendStatisticsProxyTest, AdaptChangesStatsNotStartedIfVideoSuspended) { TEST_F(SendStatisticsProxyTest, AdaptChangesStatsRestartsOnFirstSentPacket) { // Send first packet, adaptation enabled. // Elapsed time before first packet is sent should be excluded. - VideoStreamEncoder::AdaptCounts cpu_counts; - VideoStreamEncoder::AdaptCounts quality_counts; - statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts); + SendStatisticsProxy::AdaptationSteps cpu_counts; + SendStatisticsProxy::AdaptationSteps quality_counts; + statistics_proxy_->OnAdaptationChanged( + VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts, + quality_counts); fake_clock_.AdvanceTimeMilliseconds(10000); UpdateDataCounters(kFirstSsrc); // Adapt changes: 1, elapsed time: 10 sec. fake_clock_.AdvanceTimeMilliseconds(10000); - statistics_proxy_->OnQualityAdaptationChanged(cpu_counts, quality_counts); + statistics_proxy_->OnAdaptationChanged( + VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts, + quality_counts); UpdateDataCounters(kFirstSsrc); // Adapt changes: 1, elapsed time: 10 sec => 6 per minute. @@ -789,13 +901,17 @@ TEST_F(SendStatisticsProxyTest, AdaptChangesStatsRestartsOnFirstSentPacket) { TEST_F(SendStatisticsProxyTest, AdaptChangesStatsStartedAfterFirstSentPacket) { // Enable and disable adaptation. - VideoStreamEncoder::AdaptCounts cpu_counts; - VideoStreamEncoder::AdaptCounts quality_counts; - statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts); + SendStatisticsProxy::AdaptationSteps cpu_counts; + SendStatisticsProxy::AdaptationSteps quality_counts; + statistics_proxy_->OnAdaptationChanged( + VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts, + quality_counts); fake_clock_.AdvanceTimeMilliseconds(60000); - cpu_counts.fps = -1; - cpu_counts.resolution = -1; - statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts); + cpu_counts.num_framerate_reductions = absl::nullopt; + cpu_counts.num_resolution_reductions = absl::nullopt; + statistics_proxy_->OnAdaptationChanged( + VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts, + quality_counts); // Send first packet, scaling disabled. // Elapsed time before first packet is sent should be excluded. @@ -803,14 +919,18 @@ TEST_F(SendStatisticsProxyTest, AdaptChangesStatsStartedAfterFirstSentPacket) { fake_clock_.AdvanceTimeMilliseconds(60000); // Enable adaptation. - cpu_counts.resolution = 0; - statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts); + cpu_counts.num_resolution_reductions = 0; + statistics_proxy_->OnAdaptationChanged( + VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts, + quality_counts); fake_clock_.AdvanceTimeMilliseconds(10000); UpdateDataCounters(kFirstSsrc); // Adapt changes: 1, elapsed time: 20 sec. fake_clock_.AdvanceTimeMilliseconds(10000); - statistics_proxy_->OnCpuAdaptationChanged(cpu_counts, quality_counts); + statistics_proxy_->OnAdaptationChanged( + VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts, + quality_counts); // Adapt changes: 1, elapsed time: 20 sec => 3 per minute. statistics_proxy_.reset(); @@ -821,16 +941,22 @@ TEST_F(SendStatisticsProxyTest, AdaptChangesStatsStartedAfterFirstSentPacket) { TEST_F(SendStatisticsProxyTest, AdaptChangesReportedAfterContentSwitch) { // First RTP packet sent, cpu adaptation enabled. UpdateDataCounters(kFirstSsrc); - VideoStreamEncoder::AdaptCounts cpu_counts; - VideoStreamEncoder::AdaptCounts quality_counts; - quality_counts.fps = -1; - quality_counts.resolution = -1; - statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts); + SendStatisticsProxy::AdaptationSteps cpu_counts; + SendStatisticsProxy::AdaptationSteps quality_counts; + quality_counts.num_framerate_reductions = absl::nullopt; + quality_counts.num_resolution_reductions = absl::nullopt; + statistics_proxy_->OnAdaptationChanged( + VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts, + quality_counts); // Adapt changes: 2, elapsed time: 15 sec => 8 per minute. - statistics_proxy_->OnCpuAdaptationChanged(cpu_counts, quality_counts); + statistics_proxy_->OnAdaptationChanged( + VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts, + quality_counts); fake_clock_.AdvanceTimeMilliseconds(6000); - statistics_proxy_->OnCpuAdaptationChanged(cpu_counts, quality_counts); + statistics_proxy_->OnAdaptationChanged( + VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts, + quality_counts); fake_clock_.AdvanceTimeMilliseconds(9000); // Switch content type, real-time stats should be updated. @@ -844,13 +970,23 @@ TEST_F(SendStatisticsProxyTest, AdaptChangesReportedAfterContentSwitch) { // First RTP packet sent, scaling enabled. UpdateDataCounters(kFirstSsrc); - statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts); + statistics_proxy_->OnAdaptationChanged( + VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts, + quality_counts); // Adapt changes: 4, elapsed time: 120 sec => 2 per minute. - statistics_proxy_->OnCpuAdaptationChanged(cpu_counts, quality_counts); - statistics_proxy_->OnCpuAdaptationChanged(cpu_counts, quality_counts); - statistics_proxy_->OnCpuAdaptationChanged(cpu_counts, quality_counts); - statistics_proxy_->OnCpuAdaptationChanged(cpu_counts, quality_counts); + statistics_proxy_->OnAdaptationChanged( + VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts, + quality_counts); + statistics_proxy_->OnAdaptationChanged( + VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts, + quality_counts); + statistics_proxy_->OnAdaptationChanged( + VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts, + quality_counts); + statistics_proxy_->OnAdaptationChanged( + VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts, + quality_counts); fake_clock_.AdvanceTimeMilliseconds(120000); statistics_proxy_.reset(); @@ -1007,10 +1143,12 @@ TEST_F(SendStatisticsProxyTest, SentFpsHistogramExcludesSuspendedTime) { } TEST_F(SendStatisticsProxyTest, CpuLimitedHistogramNotUpdatedWhenDisabled) { - VideoStreamEncoder::AdaptCounts cpu_counts; - VideoStreamEncoder::AdaptCounts quality_counts; - cpu_counts.resolution = -1; - statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts); + SendStatisticsProxy::AdaptationSteps cpu_counts; + SendStatisticsProxy::AdaptationSteps quality_counts; + cpu_counts.num_resolution_reductions = absl::nullopt; + statistics_proxy_->OnAdaptationChanged( + VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts, + quality_counts); for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i) statistics_proxy_->OnIncomingFrame(kWidth, kHeight); @@ -1021,16 +1159,20 @@ TEST_F(SendStatisticsProxyTest, CpuLimitedHistogramNotUpdatedWhenDisabled) { } TEST_F(SendStatisticsProxyTest, CpuLimitedHistogramUpdated) { - VideoStreamEncoder::AdaptCounts cpu_counts; - VideoStreamEncoder::AdaptCounts quality_counts; - cpu_counts.resolution = 0; - statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts); + SendStatisticsProxy::AdaptationSteps cpu_counts; + SendStatisticsProxy::AdaptationSteps quality_counts; + cpu_counts.num_resolution_reductions = 0; + statistics_proxy_->OnAdaptationChanged( + VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts, + quality_counts); for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i) statistics_proxy_->OnIncomingFrame(kWidth, kHeight); - cpu_counts.resolution = 1; - statistics_proxy_->OnCpuAdaptationChanged(cpu_counts, quality_counts); + cpu_counts.num_resolution_reductions = 1; + statistics_proxy_->OnAdaptationChanged( + VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts, + quality_counts); for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i) statistics_proxy_->OnIncomingFrame(kWidth, kHeight); @@ -1388,10 +1530,12 @@ TEST_F(SendStatisticsProxyTest, TEST_F(SendStatisticsProxyTest, QualityLimitedHistogramsNotUpdatedWhenDisabled) { - VideoStreamEncoder::AdaptCounts cpu_counts; - VideoStreamEncoder::AdaptCounts quality_counts; - quality_counts.resolution = -1; - statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts); + SendStatisticsProxy::AdaptationSteps cpu_counts; + SendStatisticsProxy::AdaptationSteps quality_counts; + quality_counts.num_resolution_reductions = absl::nullopt; + statistics_proxy_->OnAdaptationChanged( + VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts, + quality_counts); EncodedImage encoded_image; for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i) statistics_proxy_->OnSendEncodedImage(encoded_image, &kDefaultCodecInfo); @@ -1406,10 +1550,12 @@ TEST_F(SendStatisticsProxyTest, TEST_F(SendStatisticsProxyTest, QualityLimitedHistogramsUpdatedWhenEnabled_NoResolutionDownscale) { - VideoStreamEncoder::AdaptCounts cpu_counts; - VideoStreamEncoder::AdaptCounts quality_counts; - quality_counts.resolution = 0; - statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts); + SendStatisticsProxy::AdaptationSteps cpu_counts; + SendStatisticsProxy::AdaptationSteps quality_counts; + quality_counts.num_resolution_reductions = 0; + statistics_proxy_->OnAdaptationChanged( + VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts, + quality_counts); EncodedImage encoded_image; for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i) statistics_proxy_->OnSendEncodedImage(encoded_image, &kDefaultCodecInfo); @@ -1428,10 +1574,12 @@ TEST_F(SendStatisticsProxyTest, TEST_F(SendStatisticsProxyTest, QualityLimitedHistogramsUpdatedWhenEnabled_TwoResolutionDownscales) { const int kDownscales = 2; - VideoStreamEncoder::AdaptCounts cpu_counts; - VideoStreamEncoder::AdaptCounts quality_counts; - quality_counts.resolution = kDownscales; - statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts); + SendStatisticsProxy::AdaptationSteps cpu_counts; + SendStatisticsProxy::AdaptationSteps quality_counts; + quality_counts.num_resolution_reductions = kDownscales; + statistics_proxy_->OnAdaptationChanged( + VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts, + quality_counts); EncodedImage encoded_image; for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i) statistics_proxy_->OnSendEncodedImage(encoded_image, &kDefaultCodecInfo); @@ -1507,10 +1655,12 @@ TEST_F(SendStatisticsProxyTest, GetStatsReportsBandwidthLimitedResolution) { EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution); // Resolution scaled due to quality. - VideoStreamEncoder::AdaptCounts cpu_counts; - VideoStreamEncoder::AdaptCounts quality_counts; - quality_counts.resolution = 1; - statistics_proxy_->OnQualityAdaptationChanged(cpu_counts, quality_counts); + SendStatisticsProxy::AdaptationSteps cpu_counts; + SendStatisticsProxy::AdaptationSteps quality_counts; + quality_counts.num_resolution_reductions = 1; + statistics_proxy_->OnAdaptationChanged( + VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts, + quality_counts); statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr); EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution); } diff --git a/video/test/mock_video_stream_encoder.h b/video/test/mock_video_stream_encoder.h index 049b8c147f..8ce6f41246 100644 --- a/video/test/mock_video_stream_encoder.h +++ b/video/test/mock_video_stream_encoder.h @@ -10,8 +10,8 @@ #ifndef VIDEO_TEST_MOCK_VIDEO_STREAM_ENCODER_H_ #define VIDEO_TEST_MOCK_VIDEO_STREAM_ENCODER_H_ +#include "api/video/video_stream_encoder_interface.h" #include "test/gmock.h" -#include "video/video_stream_encoder.h" namespace webrtc { diff --git a/video/video_send_stream.cc b/video/video_send_stream.cc index f65c8c58ae..9271f764cf 100644 --- a/video/video_send_stream.cc +++ b/video/video_send_stream.cc @@ -11,6 +11,7 @@ #include +#include "api/video/video_stream_encoder_create.h" #include "modules/rtp_rtcp/source/rtp_sender.h" #include "rtc_base/logging.h" #include "video/video_send_stream_impl.h" @@ -77,10 +78,9 @@ VideoSendStream::VideoSendStream( content_type_(encoder_config.content_type) { RTC_DCHECK(config_.encoder_settings.encoder_factory); - video_stream_encoder_ = absl::make_unique( - num_cpu_cores, &stats_proxy_, config_.encoder_settings, - config_.pre_encode_callback, - absl::make_unique(&stats_proxy_)); + video_stream_encoder_ = CreateVideoStreamEncoder(num_cpu_cores, &stats_proxy_, + config_.encoder_settings, + config_.pre_encode_callback); // TODO(srte): Initialization should not be done posted on a task queue. // Note that the posted task must not outlive this scope since the closure // references local variables. diff --git a/video/video_send_stream.h b/video/video_send_stream.h index 69c2401ef4..9ca73c0abf 100644 --- a/video/video_send_stream.h +++ b/video/video_send_stream.h @@ -16,6 +16,7 @@ #include #include "api/fec_controller.h" +#include "api/video/video_stream_encoder_interface.h" #include "call/bitrate_allocator.h" #include "call/video_receive_stream.h" #include "call/video_send_stream.h" @@ -25,7 +26,6 @@ #include "rtc_base/task_queue.h" #include "video/send_delay_stats.h" #include "video/send_statistics_proxy.h" -#include "video/video_stream_encoder.h" namespace webrtc { namespace test { @@ -36,6 +36,7 @@ class CallStats; class SendSideCongestionController; class IvfFileWriter; class ProcessThread; +class RateLimiter; class RtpRtcp; class RtpTransportControllerSendInterface; class RtcEventLog; @@ -113,7 +114,7 @@ class VideoSendStream : public webrtc::VideoSendStream { const VideoSendStream::Config config_; const VideoEncoderConfig::ContentType content_type_; std::unique_ptr send_stream_; - std::unique_ptr video_stream_encoder_; + std::unique_ptr video_stream_encoder_; }; } // namespace internal diff --git a/video/video_send_stream_impl.h b/video/video_send_stream_impl.h index f87356ee84..9e4359929d 100644 --- a/video/video_send_stream_impl.h +++ b/video/video_send_stream_impl.h @@ -16,6 +16,7 @@ #include #include "api/video/video_bitrate_allocator.h" +#include "api/video/video_stream_encoder_interface.h" #include "call/bitrate_allocator.h" #include "call/rtp_video_sender_interface.h" #include "common_types.h" // NOLINT(build/include) @@ -27,7 +28,6 @@ #include "video/send_delay_stats.h" #include "video/send_statistics_proxy.h" #include "video/video_send_stream.h" -#include "video/video_stream_encoder.h" namespace webrtc { namespace internal { @@ -42,7 +42,7 @@ namespace internal { class VideoSendStreamImpl : public webrtc::BitrateAllocatorObserver, public webrtc::OverheadObserver, public webrtc::VCMProtectionCallback, - public VideoStreamEncoder::EncoderSink, + public VideoStreamEncoderInterface::EncoderSink, public VideoBitrateAllocationObserver, public webrtc::PacketFeedbackObserver { public: diff --git a/video/video_stream_encoder.cc b/video/video_stream_encoder.cc index 69d3284a50..b0d450f67e 100644 --- a/video/video_stream_encoder.cc +++ b/video/video_stream_encoder.cc @@ -16,11 +16,9 @@ #include #include "api/video/i420_buffer.h" -#include "api/video/video_bitrate_allocator.h" #include "common_video/include/video_frame.h" #include "modules/video_coding/include/video_codec_initializer.h" #include "modules/video_coding/include/video_coding.h" -#include "modules/video_coding/include/video_coding_defines.h" #include "rtc_base/arraysize.h" #include "rtc_base/checks.h" #include "rtc_base/experiments/quality_scaling_experiment.h" @@ -30,7 +28,6 @@ #include "rtc_base/timeutils.h" #include "rtc_base/trace_event.h" #include "video/overuse_frame_detector.h" -#include "video/send_statistics_proxy.h" namespace webrtc { @@ -86,7 +83,7 @@ bool IsFramerateScalingEnabled(DegradationPreference degradation_preference) { // out). This should effectively turn off CPU adaptations for systems that // remotely cope with the load right now. CpuOveruseOptions GetCpuOveruseOptions( - const VideoSendStream::Config::EncoderSettings& settings, + const VideoStreamEncoderSettings& settings, bool full_overuse_time) { CpuOveruseOptions options; @@ -315,8 +312,8 @@ class VideoStreamEncoder::VideoSourceProxy { VideoStreamEncoder::VideoStreamEncoder( uint32_t number_of_cores, - SendStatisticsProxy* stats_proxy, - const VideoSendStream::Config::EncoderSettings& settings, + VideoStreamEncoderObserver* encoder_stats_observer, + const VideoStreamEncoderSettings& settings, rtc::VideoSinkInterface* pre_encode_callback, std::unique_ptr overuse_detector) : shutdown_event_(true /* manual_reset */, false), @@ -328,7 +325,7 @@ VideoStreamEncoder::VideoStreamEncoder( settings_(settings), video_sender_(Clock::GetRealTimeClock(), this), overuse_detector_(std::move(overuse_detector)), - stats_proxy_(stats_proxy), + encoder_stats_observer_(encoder_stats_observer), pre_encode_callback_(pre_encode_callback), max_framerate_(-1), pending_encoder_reconfiguration_(false), @@ -348,7 +345,7 @@ VideoStreamEncoder::VideoStreamEncoder( dropped_frame_count_(0), bitrate_observer_(nullptr), encoder_queue_("EncoderQueue") { - RTC_DCHECK(stats_proxy); + RTC_DCHECK(encoder_stats_observer); RTC_DCHECK(overuse_detector_); } @@ -574,7 +571,7 @@ void VideoStreamEncoder::ReconfigureEncoder() { video_sender_.UpdateChannelParameters(rate_allocator_.get(), bitrate_observer_); - stats_proxy_->OnEncoderReconfigured(encoder_config_, streams); + encoder_stats_observer_->OnEncoderReconfigured(encoder_config_, streams); pending_encoder_reconfiguration_ = false; @@ -623,8 +620,9 @@ void VideoStreamEncoder::ConfigureQualityScaler() { initial_rampup_ = kMaxInitialFramedrop; } - stats_proxy_->SetAdaptationStats(GetActiveCounts(kCpu), - GetActiveCounts(kQuality)); + encoder_stats_observer_->OnAdaptationChanged( + VideoStreamEncoderObserver::AdaptationReason::kNone, + GetActiveCounts(kCpu), GetActiveCounts(kQuality)); } void VideoStreamEncoder::OnFrame(const VideoFrame& video_frame) { @@ -680,8 +678,8 @@ void VideoStreamEncoder::OnFrame(const VideoFrame& video_frame) { encoder_queue_.PostTask( [this, incoming_frame, post_time_us, log_stats]() { RTC_DCHECK_RUN_ON(&encoder_queue_); - stats_proxy_->OnIncomingFrame(incoming_frame.width(), - incoming_frame.height()); + encoder_stats_observer_->OnIncomingFrame(incoming_frame.width(), + incoming_frame.height()); ++captured_frame_count_; const int posted_frames_waiting_for_encode = posted_frames_waiting_for_encode_.fetch_sub(1); @@ -693,7 +691,8 @@ void VideoStreamEncoder::OnFrame(const VideoFrame& video_frame) { RTC_LOG(LS_VERBOSE) << "Incoming frame dropped due to that the encoder is blocked."; ++dropped_frame_count_; - stats_proxy_->OnFrameDroppedInEncoderQueue(); + encoder_stats_observer_->OnFrameDropped( + VideoStreamEncoderObserver::DropReason::kEncoderQueue); } if (log_stats) { RTC_LOG(LS_INFO) << "Number of frames: captured " @@ -708,7 +707,8 @@ void VideoStreamEncoder::OnFrame(const VideoFrame& video_frame) { } void VideoStreamEncoder::OnDiscardedFrame() { - stats_proxy_->OnFrameDroppedBySource(); + encoder_stats_observer_->OnFrameDropped( + VideoStreamEncoderObserver::DropReason::kSource); } bool VideoStreamEncoder::EncoderPaused() const { @@ -780,7 +780,7 @@ void VideoStreamEncoder::MaybeEncodeVideoFrame(const VideoFrame& video_frame, int count = GetConstAdaptCounter().ResolutionCount(kQuality); AdaptDown(kQuality); if (GetConstAdaptCounter().ResolutionCount(kQuality) > count) { - stats_proxy_->OnInitialQualityResolutionAdaptDown(); + encoder_stats_observer_->OnInitialQualityResolutionAdaptDown(); } ++initial_rampup_; // Storing references to a native buffer risks blocking frame capture. @@ -869,7 +869,8 @@ EncodedImageCallback::Result VideoStreamEncoder::OnEncodedImage( // Encoded is called on whatever thread the real encoder implementation run // on. In the case of hardware encoders, there might be several encoders // running in parallel on different threads. - stats_proxy_->OnSendEncodedImage(encoded_image, codec_specific_info); + encoder_stats_observer_->OnSendEncodedImage(encoded_image, + codec_specific_info); EncodedImageCallback::Result result = sink_->OnEncodedImage(encoded_image, codec_specific_info, fragmentation); @@ -904,7 +905,8 @@ EncodedImageCallback::Result VideoStreamEncoder::OnEncodedImage( void VideoStreamEncoder::OnDroppedFrame(DropReason reason) { switch (reason) { case DropReason::kDroppedByMediaOptimizations: - stats_proxy_->OnFrameDroppedByMediaOptimizations(); + encoder_stats_observer_->OnFrameDropped( + VideoStreamEncoderObserver::DropReason::kMediaOptimization); encoder_queue_.PostTask([this] { RTC_DCHECK_RUN_ON(&encoder_queue_); if (quality_scaler_) @@ -912,7 +914,8 @@ void VideoStreamEncoder::OnDroppedFrame(DropReason reason) { }); break; case DropReason::kDroppedByEncoder: - stats_proxy_->OnFrameDroppedByEncoder(); + encoder_stats_observer_->OnFrameDropped( + VideoStreamEncoderObserver::DropReason::kEncoder); encoder_queue_.PostTask([this] { RTC_DCHECK_RUN_ON(&encoder_queue_); if (quality_scaler_) @@ -952,7 +955,7 @@ void VideoStreamEncoder::OnBitrateUpdated(uint32_t bitrate_bps, if (video_suspension_changed) { RTC_LOG(LS_INFO) << "Video suspend state changed to: " << (video_is_suspended ? "suspended" : "not suspended"); - stats_proxy_->OnSuspendChange(video_is_suspended); + encoder_stats_observer_->OnSuspendChange(video_is_suspended); } if (video_suspension_changed && !video_is_suspended && pending_frame_ && !DropDueToSize(pending_frame_->size())) { @@ -979,7 +982,7 @@ void VideoStreamEncoder::AdaptDown(AdaptReason reason) { RTC_DCHECK_RUN_ON(&encoder_queue_); AdaptationRequest adaptation_request = { last_frame_info_->pixel_count(), - stats_proxy_->GetStats().input_frame_rate, + encoder_stats_observer_->GetInputFrameRate(), AdaptationRequest::Mode::kAdaptDown}; bool downgrade_requested = @@ -1034,7 +1037,7 @@ void VideoStreamEncoder::AdaptDown(AdaptReason reason) { encoder_->GetScalingSettings().min_pixels_per_frame, &min_pixels_reached)) { if (min_pixels_reached) - stats_proxy_->OnMinPixelLimitReached(); + encoder_stats_observer_->OnMinPixelLimitReached(); return; } GetAdaptCounter().IncrementResolution(reason); @@ -1074,7 +1077,7 @@ void VideoStreamEncoder::AdaptUp(AdaptReason reason) { AdaptationRequest adaptation_request = { last_frame_info_->pixel_count(), - stats_proxy_->GetStats().input_frame_rate, + encoder_stats_observer_->GetInputFrameRate(), AdaptationRequest::Mode::kAdaptUp}; bool adapt_up_requested = @@ -1150,38 +1153,41 @@ void VideoStreamEncoder::AdaptUp(AdaptReason reason) { RTC_LOG(LS_INFO) << adapt_counter.ToString(); } +// TODO(nisse): Delete, once AdaptReason and AdaptationReason are merged. void VideoStreamEncoder::UpdateAdaptationStats(AdaptReason reason) { switch (reason) { case kCpu: - stats_proxy_->OnCpuAdaptationChanged(GetActiveCounts(kCpu), - GetActiveCounts(kQuality)); + encoder_stats_observer_->OnAdaptationChanged( + VideoStreamEncoderObserver::AdaptationReason::kCpu, + GetActiveCounts(kCpu), GetActiveCounts(kQuality)); break; case kQuality: - stats_proxy_->OnQualityAdaptationChanged(GetActiveCounts(kCpu), - GetActiveCounts(kQuality)); + encoder_stats_observer_->OnAdaptationChanged( + VideoStreamEncoderObserver::AdaptationReason::kQuality, + GetActiveCounts(kCpu), GetActiveCounts(kQuality)); break; } } -VideoStreamEncoder::AdaptCounts VideoStreamEncoder::GetActiveCounts( +VideoStreamEncoderObserver::AdaptationSteps VideoStreamEncoder::GetActiveCounts( AdaptReason reason) { - VideoStreamEncoder::AdaptCounts counts = + VideoStreamEncoderObserver::AdaptationSteps counts = GetConstAdaptCounter().Counts(reason); switch (reason) { case kCpu: if (!IsFramerateScalingEnabled(degradation_preference_)) - counts.fps = -1; + counts.num_framerate_reductions = absl::nullopt; if (!IsResolutionScalingEnabled(degradation_preference_)) - counts.resolution = -1; + counts.num_resolution_reductions = absl::nullopt; break; case kQuality: if (!IsFramerateScalingEnabled(degradation_preference_) || !quality_scaler_) { - counts.fps = -1; + counts.num_framerate_reductions = absl::nullopt; } if (!IsResolutionScalingEnabled(degradation_preference_) || !quality_scaler_) { - counts.resolution = -1; + counts.num_resolution_reductions = absl::nullopt; } break; } @@ -1213,11 +1219,11 @@ std::string VideoStreamEncoder::AdaptCounter::ToString() const { return ss.str(); } -VideoStreamEncoder::AdaptCounts VideoStreamEncoder::AdaptCounter::Counts( - int reason) const { - AdaptCounts counts; - counts.fps = fps_counters_[reason]; - counts.resolution = resolution_counters_[reason]; +VideoStreamEncoderObserver::AdaptationSteps +VideoStreamEncoder::AdaptCounter::Counts(int reason) const { + VideoStreamEncoderObserver::AdaptationSteps counts; + counts.num_framerate_reductions = fps_counters_[reason]; + counts.num_resolution_reductions = resolution_counters_[reason]; return counts; } diff --git a/video/video_stream_encoder.h b/video/video_stream_encoder.h index e9558baeb6..8d228a43f6 100644 --- a/video/video_stream_encoder.h +++ b/video/video_stream_encoder.h @@ -21,23 +21,19 @@ #include "api/video/video_rotation.h" #include "api/video/video_sink_interface.h" #include "api/video/video_stream_encoder_interface.h" +#include "api/video/video_stream_encoder_observer.h" +#include "api/video/video_stream_encoder_settings.h" #include "api/video_codecs/video_encoder.h" -#include "call/video_send_stream.h" -#include "common_types.h" // NOLINT(build/include) -#include "modules/video_coding/include/video_coding_defines.h" #include "modules/video_coding/utility/quality_scaler.h" #include "modules/video_coding/video_coding_impl.h" #include "rtc_base/criticalsection.h" #include "rtc_base/event.h" #include "rtc_base/sequenced_task_checker.h" #include "rtc_base/task_queue.h" -#include "typedefs.h" // NOLINT(build/include) #include "video/overuse_frame_detector.h" namespace webrtc { -class SendStatisticsProxy; - // VideoStreamEncoder represent a video encoder that accepts raw video frames as // input and produces an encoded bit stream. // Usage: @@ -51,15 +47,9 @@ class VideoStreamEncoder : public VideoStreamEncoderInterface, // Protected only to provide access to tests. protected AdaptationObserverInterface { public: - // Number of resolution and framerate reductions (-1: disabled). - struct AdaptCounts { - int resolution = 0; - int fps = 0; - }; - VideoStreamEncoder(uint32_t number_of_cores, - SendStatisticsProxy* stats_proxy, - const VideoSendStream::Config::EncoderSettings& settings, + VideoStreamEncoderObserver* encoder_stats_observer, + const VideoStreamEncoderSettings& settings, rtc::VideoSinkInterface* pre_encode_callback, std::unique_ptr overuse_detector); ~VideoStreamEncoder() override; @@ -149,7 +139,7 @@ class VideoStreamEncoder : public VideoStreamEncoderInterface, ~AdaptCounter(); // Get number of adaptation downscales for |reason|. - AdaptCounts Counts(int reason) const; + VideoStreamEncoderObserver::AdaptationSteps Counts(int reason) const; std::string ToString() const; @@ -182,7 +172,8 @@ class VideoStreamEncoder : public VideoStreamEncoderInterface, AdaptCounter& GetAdaptCounter() RTC_RUN_ON(&encoder_queue_); const AdaptCounter& GetConstAdaptCounter() RTC_RUN_ON(&encoder_queue_); void UpdateAdaptationStats(AdaptReason reason) RTC_RUN_ON(&encoder_queue_); - AdaptCounts GetActiveCounts(AdaptReason reason) RTC_RUN_ON(&encoder_queue_); + VideoStreamEncoderObserver::AdaptationSteps GetActiveCounts( + AdaptReason reason) RTC_RUN_ON(&encoder_queue_); rtc::Event shutdown_event_; @@ -194,7 +185,7 @@ class VideoStreamEncoder : public VideoStreamEncoderInterface, const std::unique_ptr source_proxy_; EncoderSink* sink_; - const VideoSendStream::Config::EncoderSettings settings_; + const VideoStreamEncoderSettings settings_; vcm::VideoSender video_sender_ RTC_GUARDED_BY(&encoder_queue_); const std::unique_ptr overuse_detector_ @@ -202,7 +193,7 @@ class VideoStreamEncoder : public VideoStreamEncoderInterface, std::unique_ptr quality_scaler_ RTC_GUARDED_BY(&encoder_queue_) RTC_PT_GUARDED_BY(&encoder_queue_); - SendStatisticsProxy* const stats_proxy_; + VideoStreamEncoderObserver* const encoder_stats_observer_; rtc::VideoSinkInterface* const pre_encode_callback_; // |thread_checker_| checks that public methods that are related to lifetime // of VideoStreamEncoder are called on the same thread. diff --git a/video/video_stream_encoder_unittest.cc b/video/video_stream_encoder_unittest.cc index 8ce5071422..32053abf54 100644 --- a/video/video_stream_encoder_unittest.cc +++ b/video/video_stream_encoder_unittest.cc @@ -92,9 +92,8 @@ class CpuOveruseDetectorProxy : public OveruseFrameDetector { class VideoStreamEncoderUnderTest : public VideoStreamEncoder { public: - VideoStreamEncoderUnderTest( - SendStatisticsProxy* stats_proxy, - const VideoSendStream::Config::EncoderSettings& settings) + VideoStreamEncoderUnderTest(SendStatisticsProxy* stats_proxy, + const VideoStreamEncoderSettings& settings) : VideoStreamEncoder(1 /* number_of_cores */, stats_proxy, settings, @@ -225,6 +224,7 @@ class AdaptingFrameForwarder : public test::FrameForwarder { absl::optional last_height_; }; +// TODO(nisse): Mock only VideoStreamEncoderObserver. class MockableSendStatisticsProxy : public SendStatisticsProxy { public: MockableSendStatisticsProxy(Clock* clock, @@ -239,6 +239,12 @@ class MockableSendStatisticsProxy : public SendStatisticsProxy { return SendStatisticsProxy::GetStats(); } + int GetInputFrameRate() const override { + rtc::CritScope cs(&lock_); + if (mock_stats_) + return mock_stats_->input_frame_rate; + return SendStatisticsProxy::GetInputFrameRate(); + } void SetMockStats(const VideoSendStream::Stats& stats) { rtc::CritScope cs(&lock_); mock_stats_.emplace(stats);