New api function CreateVideoStreamEncoder.
Bug: webrtc:8830 Change-Id: I01de86f601e48f76e6b41b4182ce006d397a190c Reviewed-on: https://webrtc-review.googlesource.com/78260 Commit-Queue: Niels Moller <nisse@webrtc.org> Reviewed-by: Erik Språng <sprang@webrtc.org> Cr-Commit-Position: refs/heads/master@{#24079}
This commit is contained in:
parent
e507b0ce8e
commit
213618e37e
@ -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",
|
||||
]
|
||||
}
|
||||
|
||||
@ -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",
|
||||
],
|
||||
}
|
||||
|
||||
27
api/video/video_stream_encoder_create.cc
Normal file
27
api/video/video_stream_encoder_create.cc
Normal file
@ -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<VideoStreamEncoderInterface> CreateVideoStreamEncoder(
|
||||
uint32_t number_of_cores,
|
||||
VideoStreamEncoderObserver* encoder_stats_observer,
|
||||
const VideoStreamEncoderSettings& settings,
|
||||
// Deprecated, used for tests only.
|
||||
rtc::VideoSinkInterface<VideoFrame>* pre_encode_callback) {
|
||||
return rtc::MakeUnique<VideoStreamEncoder>(
|
||||
number_of_cores, encoder_stats_observer, settings, pre_encode_callback,
|
||||
rtc::MakeUnique<OveruseFrameDetector>(encoder_stats_observer));
|
||||
}
|
||||
} // namespace webrtc
|
||||
41
api/video/video_stream_encoder_create.h
Normal file
41
api/video/video_stream_encoder_create.h
Normal file
@ -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 <map>
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
|
||||
#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<VideoStreamEncoderInterface> CreateVideoStreamEncoder(
|
||||
uint32_t number_of_cores,
|
||||
VideoStreamEncoderObserver* encoder_stats_observer,
|
||||
const VideoStreamEncoderSettings& settings,
|
||||
// Deprecated, used for tests only.
|
||||
rtc::VideoSinkInterface<VideoFrame>* pre_encode_callback);
|
||||
|
||||
inline std::unique_ptr<VideoStreamEncoderInterface> 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_
|
||||
@ -47,8 +47,6 @@ class VideoStreamEncoderInterface : public rtc::VideoSinkInterface<VideoFrame> {
|
||||
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
|
||||
|
||||
94
api/video/video_stream_encoder_observer.h
Normal file
94
api/video/video_stream_encoder_observer.h
Normal file
@ -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 <vector>
|
||||
|
||||
#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<int> num_resolution_reductions = 0;
|
||||
absl::optional<int> 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<VideoStream>& 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_
|
||||
31
api/video/video_stream_encoder_settings.h
Normal file
31
api/video/video_stream_encoder_settings.h
Normal file
@ -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_
|
||||
@ -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",
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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;
|
||||
|
||||
|
||||
@ -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",
|
||||
|
||||
@ -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;
|
||||
|
||||
|
||||
@ -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
|
||||
|
||||
@ -15,6 +15,7 @@
|
||||
#include <memory>
|
||||
|
||||
#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<CpuOveruseMetrics> metrics_ RTC_GUARDED_BY(task_checker_);
|
||||
absl::optional<int> encode_usage_percent_ RTC_GUARDED_BY(task_checker_);
|
||||
|
||||
int64_t num_process_times_ RTC_GUARDED_BY(task_checker_);
|
||||
|
||||
|
||||
@ -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<OveruseFrameDetectorUnderTest> overuse_detector_;
|
||||
CpuOveruseMetrics metrics_;
|
||||
int encode_usage_percent_ = -1;
|
||||
|
||||
static const auto reason_ = AdaptationObserverInterface::AdaptReason::kCpu;
|
||||
};
|
||||
|
||||
@ -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());
|
||||
|
||||
@ -16,6 +16,7 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#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<VideoStream>& streams);
|
||||
const std::vector<VideoStream>& 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,
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -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 {
|
||||
|
||||
|
||||
@ -11,6 +11,7 @@
|
||||
|
||||
#include <utility>
|
||||
|
||||
#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<VideoStreamEncoder>(
|
||||
num_cpu_cores, &stats_proxy_, config_.encoder_settings,
|
||||
config_.pre_encode_callback,
|
||||
absl::make_unique<OveruseFrameDetector>(&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.
|
||||
|
||||
@ -16,6 +16,7 @@
|
||||
#include <vector>
|
||||
|
||||
#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<VideoSendStreamImpl> send_stream_;
|
||||
std::unique_ptr<VideoStreamEncoder> video_stream_encoder_;
|
||||
std::unique_ptr<VideoStreamEncoderInterface> video_stream_encoder_;
|
||||
};
|
||||
|
||||
} // namespace internal
|
||||
|
||||
@ -16,6 +16,7 @@
|
||||
#include <vector>
|
||||
|
||||
#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:
|
||||
|
||||
@ -16,11 +16,9 @@
|
||||
#include <utility>
|
||||
|
||||
#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<VideoFrame>* pre_encode_callback,
|
||||
std::unique_ptr<OveruseFrameDetector> 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;
|
||||
}
|
||||
|
||||
|
||||
@ -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<VideoFrame>* pre_encode_callback,
|
||||
std::unique_ptr<OveruseFrameDetector> 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<VideoSourceProxy> 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<OveruseFrameDetector> overuse_detector_
|
||||
@ -202,7 +193,7 @@ class VideoStreamEncoder : public VideoStreamEncoderInterface,
|
||||
std::unique_ptr<QualityScaler> quality_scaler_ RTC_GUARDED_BY(&encoder_queue_)
|
||||
RTC_PT_GUARDED_BY(&encoder_queue_);
|
||||
|
||||
SendStatisticsProxy* const stats_proxy_;
|
||||
VideoStreamEncoderObserver* const encoder_stats_observer_;
|
||||
rtc::VideoSinkInterface<VideoFrame>* const pre_encode_callback_;
|
||||
// |thread_checker_| checks that public methods that are related to lifetime
|
||||
// of VideoStreamEncoder are called on the same thread.
|
||||
|
||||
@ -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<int> 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);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user