Update adaptation stats to support degradations in both resolution and framerate.
Add AdaptCounter class which holds the number of downgrade counts per degradation way (resolution/fps) and reason (cpu/quality). BUG=webrtc:7607 Review-Url: https://codereview.webrtc.org/2871623002 Cr-Commit-Position: refs/heads/master@{#18156}
This commit is contained in:
parent
9a6f4d4316
commit
09f0561675
@ -305,8 +305,8 @@ void SendStatisticsProxy::UmaSamplesContainer::UpdateHistograms(
|
||||
}
|
||||
|
||||
if (first_rtp_stats_time_ms_ != -1) {
|
||||
quality_scaling_timer_.Stop(clock_->TimeInMilliseconds());
|
||||
int64_t elapsed_sec = quality_scaling_timer_.total_ms / 1000;
|
||||
quality_adapt_timer_.Stop(clock_->TimeInMilliseconds());
|
||||
int64_t elapsed_sec = quality_adapt_timer_.total_ms / 1000;
|
||||
if (elapsed_sec >= metrics::kMinRunTimeInSeconds) {
|
||||
int quality_changes = current_stats.number_of_quality_adapt_changes -
|
||||
start_stats_.number_of_quality_adapt_changes;
|
||||
@ -314,8 +314,8 @@ void SendStatisticsProxy::UmaSamplesContainer::UpdateHistograms(
|
||||
uma_prefix_ + "AdaptChangesPerMinute.Quality",
|
||||
quality_changes * 60 / elapsed_sec);
|
||||
}
|
||||
cpu_scaling_timer_.Stop(clock_->TimeInMilliseconds());
|
||||
elapsed_sec = cpu_scaling_timer_.total_ms / 1000;
|
||||
cpu_adapt_timer_.Stop(clock_->TimeInMilliseconds());
|
||||
elapsed_sec = cpu_adapt_timer_.total_ms / 1000;
|
||||
if (elapsed_sec >= metrics::kMinRunTimeInSeconds) {
|
||||
int cpu_changes = current_stats.number_of_cpu_adapt_changes -
|
||||
start_stats_.number_of_cpu_adapt_changes;
|
||||
@ -510,14 +510,14 @@ void SendStatisticsProxy::OnSuspendChange(bool is_suspended) {
|
||||
uma_container_->retransmit_byte_counter_.ProcessAndPauseForDuration(kMinMs);
|
||||
uma_container_->fec_byte_counter_.ProcessAndPauseForDuration(kMinMs);
|
||||
// Stop adaptation stats.
|
||||
uma_container_->cpu_scaling_timer_.Stop(now_ms);
|
||||
uma_container_->quality_scaling_timer_.Stop(now_ms);
|
||||
uma_container_->cpu_adapt_timer_.Stop(now_ms);
|
||||
uma_container_->quality_adapt_timer_.Stop(now_ms);
|
||||
} else {
|
||||
// Start adaptation stats if scaling is enabled.
|
||||
if (cpu_downscales_ >= 0)
|
||||
uma_container_->cpu_scaling_timer_.Start(now_ms);
|
||||
uma_container_->cpu_adapt_timer_.Start(now_ms);
|
||||
if (quality_downscales_ >= 0)
|
||||
uma_container_->quality_scaling_timer_.Start(now_ms);
|
||||
uma_container_->quality_adapt_timer_.Start(now_ms);
|
||||
// Stop pause explicitly for stats that may be zero/not updated for some
|
||||
// time.
|
||||
uma_container_->rtx_byte_counter_.ProcessAndStopPause();
|
||||
@ -734,50 +734,53 @@ void SendStatisticsProxy::OnIncomingFrame(int width, int height) {
|
||||
"ssrc", rtp_config_.ssrcs[0]);
|
||||
}
|
||||
|
||||
void SendStatisticsProxy::SetCpuScalingStats(int num_cpu_downscales) {
|
||||
void SendStatisticsProxy::SetAdaptationStats(
|
||||
const ViEEncoder::AdaptCounts& cpu_counts,
|
||||
const ViEEncoder::AdaptCounts& quality_counts) {
|
||||
rtc::CritScope lock(&crit_);
|
||||
cpu_downscales_ = num_cpu_downscales;
|
||||
stats_.cpu_limited_resolution = num_cpu_downscales > 0;
|
||||
|
||||
if (num_cpu_downscales >= 0) {
|
||||
// Scaling enabled.
|
||||
if (!stats_.suspended)
|
||||
uma_container_->cpu_scaling_timer_.Start(clock_->TimeInMilliseconds());
|
||||
return;
|
||||
}
|
||||
uma_container_->cpu_scaling_timer_.Stop(clock_->TimeInMilliseconds());
|
||||
SetAdaptTimer(cpu_counts, &uma_container_->cpu_adapt_timer_);
|
||||
SetAdaptTimer(quality_counts, &uma_container_->quality_adapt_timer_);
|
||||
UpdateAdaptationStats(cpu_counts, quality_counts);
|
||||
}
|
||||
|
||||
void SendStatisticsProxy::SetQualityScalingStats(int num_quality_downscales) {
|
||||
void SendStatisticsProxy::OnCpuAdaptationChanged(
|
||||
const ViEEncoder::AdaptCounts& cpu_counts,
|
||||
const ViEEncoder::AdaptCounts& quality_counts) {
|
||||
rtc::CritScope lock(&crit_);
|
||||
quality_downscales_ = num_quality_downscales;
|
||||
stats_.bw_limited_resolution = quality_downscales_ > 0;
|
||||
|
||||
if (num_quality_downscales >= 0) {
|
||||
// Scaling enabled.
|
||||
if (!stats_.suspended) {
|
||||
uma_container_->quality_scaling_timer_.Start(
|
||||
clock_->TimeInMilliseconds());
|
||||
}
|
||||
return;
|
||||
}
|
||||
uma_container_->quality_scaling_timer_.Stop(clock_->TimeInMilliseconds());
|
||||
}
|
||||
|
||||
void SendStatisticsProxy::OnCpuRestrictedResolutionChanged(
|
||||
bool cpu_restricted_resolution) {
|
||||
rtc::CritScope lock(&crit_);
|
||||
stats_.cpu_limited_resolution = cpu_restricted_resolution;
|
||||
++stats_.number_of_cpu_adapt_changes;
|
||||
UpdateAdaptationStats(cpu_counts, quality_counts);
|
||||
TRACE_EVENT_INSTANT0("webrtc_stats", "WebRTC.Video.CpuAdaptationChanges");
|
||||
}
|
||||
|
||||
void SendStatisticsProxy::OnQualityRestrictedResolutionChanged(
|
||||
int num_quality_downscales) {
|
||||
void SendStatisticsProxy::OnQualityAdaptationChanged(
|
||||
const ViEEncoder::AdaptCounts& cpu_counts,
|
||||
const ViEEncoder::AdaptCounts& quality_counts) {
|
||||
rtc::CritScope lock(&crit_);
|
||||
++stats_.number_of_quality_adapt_changes;
|
||||
quality_downscales_ = num_quality_downscales;
|
||||
stats_.bw_limited_resolution = quality_downscales_ > 0;
|
||||
UpdateAdaptationStats(cpu_counts, quality_counts);
|
||||
}
|
||||
|
||||
void SendStatisticsProxy::UpdateAdaptationStats(
|
||||
const ViEEncoder::AdaptCounts& cpu_counts,
|
||||
const ViEEncoder::AdaptCounts& quality_counts) {
|
||||
cpu_downscales_ = cpu_counts.resolution;
|
||||
quality_downscales_ = quality_counts.resolution;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
void SendStatisticsProxy::SetAdaptTimer(const ViEEncoder::AdaptCounts& counts,
|
||||
StatsTimer* timer) {
|
||||
if (counts.resolution >= 0 || counts.fps >= 0) {
|
||||
// Adaptation enabled.
|
||||
if (!stats_.suspended)
|
||||
timer->Start(clock_->TimeInMilliseconds());
|
||||
return;
|
||||
}
|
||||
timer->Stop(clock_->TimeInMilliseconds());
|
||||
}
|
||||
|
||||
void SendStatisticsProxy::RtcpPacketTypesCounterUpdated(
|
||||
@ -833,8 +836,8 @@ void SendStatisticsProxy::DataCountersUpdated(
|
||||
if (uma_container_->first_rtp_stats_time_ms_ == -1) {
|
||||
int64_t now_ms = clock_->TimeInMilliseconds();
|
||||
uma_container_->first_rtp_stats_time_ms_ = now_ms;
|
||||
uma_container_->cpu_scaling_timer_.Restart(now_ms);
|
||||
uma_container_->quality_scaling_timer_.Restart(now_ms);
|
||||
uma_container_->cpu_adapt_timer_.Restart(now_ms);
|
||||
uma_container_->quality_adapt_timer_.Restart(now_ms);
|
||||
}
|
||||
|
||||
uma_container_->total_byte_counter_.Set(counters.transmitted.TotalBytes(),
|
||||
|
||||
@ -57,10 +57,14 @@ class SendStatisticsProxy : public CpuOveruseMetricsObserver,
|
||||
// Used to update incoming frame rate.
|
||||
void OnIncomingFrame(int width, int height);
|
||||
|
||||
void OnCpuRestrictedResolutionChanged(bool cpu_restricted_resolution);
|
||||
void OnQualityRestrictedResolutionChanged(int num_quality_downscales);
|
||||
void SetCpuScalingStats(int num_cpu_downscales); // -1: disabled.
|
||||
void SetQualityScalingStats(int num_quality_downscales); // -1: disabled.
|
||||
// Adaptation stats.
|
||||
void SetAdaptationStats(const ViEEncoder::AdaptCounts& cpu_counts,
|
||||
const ViEEncoder::AdaptCounts& quality_counts);
|
||||
void OnCpuAdaptationChanged(const ViEEncoder::AdaptCounts& cpu_counts,
|
||||
const ViEEncoder::AdaptCounts& quality_counts);
|
||||
void OnQualityAdaptationChanged(
|
||||
const ViEEncoder::AdaptCounts& cpu_counts,
|
||||
const ViEEncoder::AdaptCounts& quality_counts);
|
||||
|
||||
void OnEncoderStatsUpdate(uint32_t framerate, uint32_t bitrate);
|
||||
void OnSuspendChange(bool is_suspended);
|
||||
@ -160,6 +164,12 @@ class SendStatisticsProxy : public CpuOveruseMetricsObserver,
|
||||
VideoSendStream::StreamStats* GetStatsEntry(uint32_t ssrc)
|
||||
EXCLUSIVE_LOCKS_REQUIRED(crit_);
|
||||
|
||||
void SetAdaptTimer(const ViEEncoder::AdaptCounts& counts, StatsTimer* timer)
|
||||
EXCLUSIVE_LOCKS_REQUIRED(crit_);
|
||||
void UpdateAdaptationStats(const ViEEncoder::AdaptCounts& cpu_counts,
|
||||
const ViEEncoder::AdaptCounts& quality_counts)
|
||||
EXCLUSIVE_LOCKS_REQUIRED(crit_);
|
||||
|
||||
Clock* const clock_;
|
||||
const std::string payload_name_;
|
||||
const VideoSendStream::Config::Rtp rtp_config_;
|
||||
@ -215,8 +225,8 @@ class SendStatisticsProxy : public CpuOveruseMetricsObserver,
|
||||
RateAccCounter fec_byte_counter_;
|
||||
int64_t first_rtcp_stats_time_ms_;
|
||||
int64_t first_rtp_stats_time_ms_;
|
||||
StatsTimer cpu_scaling_timer_;
|
||||
StatsTimer quality_scaling_timer_;
|
||||
StatsTimer cpu_adapt_timer_;
|
||||
StatsTimer quality_adapt_timer_;
|
||||
BoolSampleCounter paused_time_counter_;
|
||||
TargetRateUpdates target_rate_updates_;
|
||||
ReportBlockStats report_block_stats_;
|
||||
|
||||
@ -367,61 +367,99 @@ TEST_F(SendStatisticsProxyTest, OnSendEncodedImageWithoutQpQpSumWontExist) {
|
||||
EXPECT_EQ(rtc::Optional<uint64_t>(), statistics_proxy_->GetStats().qp_sum);
|
||||
}
|
||||
|
||||
TEST_F(SendStatisticsProxyTest, SetCpuScalingUpdatesStats) {
|
||||
TEST_F(SendStatisticsProxyTest, GetCpuAdaptationStats) {
|
||||
ViEEncoder::AdaptCounts cpu_counts;
|
||||
ViEEncoder::AdaptCounts quality_counts;
|
||||
EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_framerate);
|
||||
EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_resolution);
|
||||
statistics_proxy_->SetCpuScalingStats(-1);
|
||||
cpu_counts.fps = 1;
|
||||
cpu_counts.resolution = 0;
|
||||
statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts);
|
||||
EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_framerate);
|
||||
EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_resolution);
|
||||
statistics_proxy_->SetCpuScalingStats(0);
|
||||
EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_resolution);
|
||||
statistics_proxy_->SetCpuScalingStats(1);
|
||||
cpu_counts.fps = 0;
|
||||
cpu_counts.resolution = 1;
|
||||
statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts);
|
||||
EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_framerate);
|
||||
EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_resolution);
|
||||
}
|
||||
|
||||
TEST_F(SendStatisticsProxyTest, SetQualityScalingUpdatesStats) {
|
||||
EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
|
||||
statistics_proxy_->SetQualityScalingStats(-1);
|
||||
EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
|
||||
statistics_proxy_->SetQualityScalingStats(0);
|
||||
EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
|
||||
statistics_proxy_->SetQualityScalingStats(1);
|
||||
EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution);
|
||||
}
|
||||
|
||||
TEST_F(SendStatisticsProxyTest, GetStatsReportsCpuResolutionChanges) {
|
||||
cpu_counts.fps = 1;
|
||||
cpu_counts.resolution = -1;
|
||||
statistics_proxy_->SetAdaptationStats(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);
|
||||
EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_framerate);
|
||||
EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_resolution);
|
||||
}
|
||||
|
||||
TEST_F(SendStatisticsProxyTest, GetQualityAdaptationStats) {
|
||||
ViEEncoder::AdaptCounts cpu_counts;
|
||||
ViEEncoder::AdaptCounts 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);
|
||||
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);
|
||||
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);
|
||||
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);
|
||||
EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
|
||||
EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
|
||||
}
|
||||
|
||||
TEST_F(SendStatisticsProxyTest, GetStatsReportsCpuAdaptChanges) {
|
||||
ViEEncoder::AdaptCounts cpu_counts;
|
||||
ViEEncoder::AdaptCounts quality_counts;
|
||||
EXPECT_EQ(0, statistics_proxy_->GetStats().number_of_cpu_adapt_changes);
|
||||
|
||||
statistics_proxy_->OnCpuRestrictedResolutionChanged(true);
|
||||
cpu_counts.resolution = 1;
|
||||
statistics_proxy_->OnCpuAdaptationChanged(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);
|
||||
|
||||
statistics_proxy_->OnCpuRestrictedResolutionChanged(false);
|
||||
EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_resolution);
|
||||
cpu_counts.resolution = 2;
|
||||
statistics_proxy_->OnCpuAdaptationChanged(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);
|
||||
EXPECT_EQ(0, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
|
||||
}
|
||||
|
||||
TEST_F(SendStatisticsProxyTest, GetStatsReportsQualityResolutionChanges) {
|
||||
EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
|
||||
TEST_F(SendStatisticsProxyTest, GetStatsReportsQualityAdaptChanges) {
|
||||
ViEEncoder::AdaptCounts cpu_counts;
|
||||
ViEEncoder::AdaptCounts quality_counts;
|
||||
EXPECT_EQ(0, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
|
||||
|
||||
statistics_proxy_->OnQualityRestrictedResolutionChanged(1);
|
||||
EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution);
|
||||
quality_counts.fps = 1;
|
||||
statistics_proxy_->OnQualityAdaptationChanged(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);
|
||||
|
||||
statistics_proxy_->OnQualityRestrictedResolutionChanged(2);
|
||||
EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution);
|
||||
EXPECT_EQ(2, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
|
||||
|
||||
statistics_proxy_->OnQualityRestrictedResolutionChanged(1);
|
||||
EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution);
|
||||
EXPECT_EQ(3, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
|
||||
|
||||
statistics_proxy_->OnQualityRestrictedResolutionChanged(0);
|
||||
quality_counts.fps = 0;
|
||||
statistics_proxy_->OnQualityAdaptationChanged(cpu_counts, quality_counts);
|
||||
EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
|
||||
EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
|
||||
EXPECT_EQ(4, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
|
||||
EXPECT_EQ(2, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
|
||||
EXPECT_EQ(0, statistics_proxy_->GetStats().number_of_cpu_adapt_changes);
|
||||
}
|
||||
|
||||
TEST_F(SendStatisticsProxyTest, AdaptChangesNotReported_ScalingNotEnabled) {
|
||||
TEST_F(SendStatisticsProxyTest, AdaptChangesNotReported_AdaptationNotEnabled) {
|
||||
// First RTP packet sent.
|
||||
UpdateDataCounters(kFirstSsrc);
|
||||
// Min runtime has passed.
|
||||
@ -435,9 +473,10 @@ TEST_F(SendStatisticsProxyTest, AdaptChangesNotReported_ScalingNotEnabled) {
|
||||
TEST_F(SendStatisticsProxyTest, AdaptChangesNotReported_MinRuntimeNotPassed) {
|
||||
// First RTP packet sent.
|
||||
UpdateDataCounters(kFirstSsrc);
|
||||
// Enable scaling.
|
||||
statistics_proxy_->SetQualityScalingStats(0);
|
||||
statistics_proxy_->SetCpuScalingStats(0);
|
||||
// Enable adaptation.
|
||||
ViEEncoder::AdaptCounts cpu_counts;
|
||||
ViEEncoder::AdaptCounts quality_counts;
|
||||
statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts);
|
||||
// Min runtime has not passed.
|
||||
fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000 - 1);
|
||||
statistics_proxy_.reset();
|
||||
@ -446,26 +485,18 @@ TEST_F(SendStatisticsProxyTest, AdaptChangesNotReported_MinRuntimeNotPassed) {
|
||||
metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
|
||||
}
|
||||
|
||||
TEST_F(SendStatisticsProxyTest, ZeroCpuAdaptChangesReported) {
|
||||
TEST_F(SendStatisticsProxyTest, ZeroAdaptChangesReported) {
|
||||
// First RTP packet sent.
|
||||
UpdateDataCounters(kFirstSsrc);
|
||||
// Enable scaling.
|
||||
statistics_proxy_->SetCpuScalingStats(0);
|
||||
// Enable adaptation.
|
||||
ViEEncoder::AdaptCounts cpu_counts;
|
||||
ViEEncoder::AdaptCounts quality_counts;
|
||||
statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts);
|
||||
// Min runtime has passed.
|
||||
fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
|
||||
statistics_proxy_.reset();
|
||||
EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
|
||||
EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Cpu", 0));
|
||||
}
|
||||
|
||||
TEST_F(SendStatisticsProxyTest, ZeroQualityAdaptChangesReported) {
|
||||
// First RTP packet sent.
|
||||
UpdateDataCounters(kFirstSsrc);
|
||||
// Enable scaling.
|
||||
statistics_proxy_->SetQualityScalingStats(0);
|
||||
// Min runtime has passed.
|
||||
fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
|
||||
statistics_proxy_.reset();
|
||||
EXPECT_EQ(1,
|
||||
metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
|
||||
EXPECT_EQ(
|
||||
@ -475,10 +506,12 @@ TEST_F(SendStatisticsProxyTest, ZeroQualityAdaptChangesReported) {
|
||||
TEST_F(SendStatisticsProxyTest, CpuAdaptChangesReported) {
|
||||
// First RTP packet sent.
|
||||
UpdateDataCounters(kFirstSsrc);
|
||||
// Enable scaling.
|
||||
// Enable adaptation.
|
||||
ViEEncoder::AdaptCounts cpu_counts;
|
||||
ViEEncoder::AdaptCounts quality_counts;
|
||||
statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts);
|
||||
// Adapt changes: 1, elapsed time: 10 sec => 6 per minute.
|
||||
statistics_proxy_->SetCpuScalingStats(0);
|
||||
statistics_proxy_->OnCpuRestrictedResolutionChanged(true);
|
||||
statistics_proxy_->OnCpuAdaptationChanged(cpu_counts, quality_counts);
|
||||
fake_clock_.AdvanceTimeMilliseconds(10000);
|
||||
statistics_proxy_.reset();
|
||||
EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
|
||||
@ -489,34 +522,42 @@ TEST_F(SendStatisticsProxyTest, AdaptChangesStatsExcludesDisabledTime) {
|
||||
// First RTP packet sent.
|
||||
UpdateDataCounters(kFirstSsrc);
|
||||
|
||||
// Disable scaling.
|
||||
statistics_proxy_->SetQualityScalingStats(-1);
|
||||
// Disable quality adaptation.
|
||||
ViEEncoder::AdaptCounts cpu_counts;
|
||||
ViEEncoder::AdaptCounts quality_counts;
|
||||
quality_counts.fps = -1;
|
||||
quality_counts.resolution = -1;
|
||||
statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts);
|
||||
fake_clock_.AdvanceTimeMilliseconds(10000);
|
||||
|
||||
// Enable scaling.
|
||||
// Enable quality adaptation.
|
||||
// Adapt changes: 2, elapsed time: 20 sec.
|
||||
statistics_proxy_->SetQualityScalingStats(0);
|
||||
quality_counts.fps = 0;
|
||||
statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts);
|
||||
fake_clock_.AdvanceTimeMilliseconds(5000);
|
||||
statistics_proxy_->SetQualityScalingStats(1);
|
||||
statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts);
|
||||
fake_clock_.AdvanceTimeMilliseconds(9000);
|
||||
statistics_proxy_->OnQualityRestrictedResolutionChanged(1);
|
||||
statistics_proxy_->OnQualityAdaptationChanged(cpu_counts, quality_counts);
|
||||
fake_clock_.AdvanceTimeMilliseconds(6000);
|
||||
statistics_proxy_->OnQualityRestrictedResolutionChanged(2);
|
||||
statistics_proxy_->OnQualityAdaptationChanged(cpu_counts, quality_counts);
|
||||
|
||||
// Disable scaling.
|
||||
statistics_proxy_->SetQualityScalingStats(-1);
|
||||
// Disable quality adaptation.
|
||||
quality_counts.fps = -1;
|
||||
statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts);
|
||||
fake_clock_.AdvanceTimeMilliseconds(30000);
|
||||
|
||||
// Enable scaling.
|
||||
// Enable quality adaptation.
|
||||
// Adapt changes: 1, elapsed time: 10 sec.
|
||||
statistics_proxy_->SetQualityScalingStats(0);
|
||||
statistics_proxy_->OnQualityRestrictedResolutionChanged(1);
|
||||
quality_counts.resolution = 0;
|
||||
statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts);
|
||||
statistics_proxy_->OnQualityAdaptationChanged(cpu_counts, quality_counts);
|
||||
fake_clock_.AdvanceTimeMilliseconds(10000);
|
||||
|
||||
// Disable scaling.
|
||||
statistics_proxy_->SetQualityScalingStats(-1);
|
||||
// Disable quality adaptation.
|
||||
quality_counts.resolution = -1;
|
||||
statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts);
|
||||
fake_clock_.AdvanceTimeMilliseconds(5000);
|
||||
statistics_proxy_->SetQualityScalingStats(-1);
|
||||
statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts);
|
||||
fake_clock_.AdvanceTimeMilliseconds(20000);
|
||||
|
||||
// Adapt changes: 3, elapsed time: 30 sec => 6 per minute.
|
||||
@ -549,12 +590,14 @@ TEST_F(SendStatisticsProxyTest, QualityAdaptChangesStatsExcludesSuspendedTime) {
|
||||
// First RTP packet sent.
|
||||
UpdateDataCounters(kFirstSsrc);
|
||||
|
||||
// Enable scaling.
|
||||
// Enable adaptation.
|
||||
ViEEncoder::AdaptCounts cpu_counts;
|
||||
ViEEncoder::AdaptCounts quality_counts;
|
||||
// Adapt changes: 2, elapsed time: 20 sec.
|
||||
statistics_proxy_->SetQualityScalingStats(0);
|
||||
statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts);
|
||||
fake_clock_.AdvanceTimeMilliseconds(20000);
|
||||
statistics_proxy_->OnQualityRestrictedResolutionChanged(1);
|
||||
statistics_proxy_->OnQualityRestrictedResolutionChanged(2);
|
||||
statistics_proxy_->OnQualityAdaptationChanged(cpu_counts, quality_counts);
|
||||
statistics_proxy_->OnQualityAdaptationChanged(cpu_counts, quality_counts);
|
||||
|
||||
// Suspend and resume video.
|
||||
statistics_proxy_->OnSuspendChange(true);
|
||||
@ -562,7 +605,7 @@ TEST_F(SendStatisticsProxyTest, QualityAdaptChangesStatsExcludesSuspendedTime) {
|
||||
statistics_proxy_->OnSuspendChange(false);
|
||||
|
||||
// Adapt changes: 1, elapsed time: 10 sec.
|
||||
statistics_proxy_->OnQualityRestrictedResolutionChanged(3);
|
||||
statistics_proxy_->OnQualityAdaptationChanged(cpu_counts, quality_counts);
|
||||
fake_clock_.AdvanceTimeMilliseconds(10000);
|
||||
|
||||
// Adapt changes: 3, elapsed time: 30 sec => 6 per minute.
|
||||
@ -581,18 +624,22 @@ TEST_F(SendStatisticsProxyTest, CpuAdaptChangesStatsExcludesSuspendedTime) {
|
||||
statistics_proxy_->OnSuspendChange(false);
|
||||
fake_clock_.AdvanceTimeMilliseconds(30000);
|
||||
|
||||
// Enable scaling.
|
||||
// Enable adaptation.
|
||||
ViEEncoder::AdaptCounts cpu_counts;
|
||||
ViEEncoder::AdaptCounts quality_counts;
|
||||
// Adapt changes: 1, elapsed time: 20 sec.
|
||||
statistics_proxy_->SetCpuScalingStats(0);
|
||||
statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts);
|
||||
fake_clock_.AdvanceTimeMilliseconds(10000);
|
||||
statistics_proxy_->OnCpuRestrictedResolutionChanged(true);
|
||||
statistics_proxy_->OnCpuAdaptationChanged(cpu_counts, quality_counts);
|
||||
|
||||
// Video not suspended, stats time already started.
|
||||
statistics_proxy_->OnSuspendChange(false);
|
||||
fake_clock_.AdvanceTimeMilliseconds(10000);
|
||||
|
||||
// Disable scaling.
|
||||
statistics_proxy_->SetCpuScalingStats(-1);
|
||||
// Disable adaptation.
|
||||
cpu_counts.fps = -1;
|
||||
cpu_counts.resolution = -1;
|
||||
statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts);
|
||||
fake_clock_.AdvanceTimeMilliseconds(30000);
|
||||
|
||||
// Suspend and resume video, stats time not started when scaling not enabled.
|
||||
@ -601,11 +648,13 @@ TEST_F(SendStatisticsProxyTest, CpuAdaptChangesStatsExcludesSuspendedTime) {
|
||||
statistics_proxy_->OnSuspendChange(false);
|
||||
fake_clock_.AdvanceTimeMilliseconds(30000);
|
||||
|
||||
// Enable scaling.
|
||||
// Enable adaptation.
|
||||
// Adapt changes: 1, elapsed time: 10 sec.
|
||||
statistics_proxy_->SetCpuScalingStats(0);
|
||||
cpu_counts.fps = 0;
|
||||
cpu_counts.resolution = 0;
|
||||
statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts);
|
||||
fake_clock_.AdvanceTimeMilliseconds(10000);
|
||||
statistics_proxy_->OnCpuRestrictedResolutionChanged(true);
|
||||
statistics_proxy_->OnCpuAdaptationChanged(cpu_counts, quality_counts);
|
||||
|
||||
// Adapt changes: 2, elapsed time: 30 sec => 4 per minute.
|
||||
statistics_proxy_.reset();
|
||||
@ -620,15 +669,17 @@ TEST_F(SendStatisticsProxyTest, AdaptChangesStatsNotStartedIfVideoSuspended) {
|
||||
// Video suspended.
|
||||
statistics_proxy_->OnSuspendChange(true);
|
||||
|
||||
// Enable scaling, stats time not started when suspended.
|
||||
statistics_proxy_->SetCpuScalingStats(0);
|
||||
// Enable adaptation, stats time not started when suspended.
|
||||
ViEEncoder::AdaptCounts cpu_counts;
|
||||
ViEEncoder::AdaptCounts quality_counts;
|
||||
statistics_proxy_->SetAdaptationStats(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_->OnCpuRestrictedResolutionChanged(true);
|
||||
statistics_proxy_->OnCpuAdaptationChanged(cpu_counts, quality_counts);
|
||||
|
||||
// Adapt changes: 1, elapsed time: 10 sec => 6 per minute.
|
||||
statistics_proxy_.reset();
|
||||
@ -637,15 +688,17 @@ TEST_F(SendStatisticsProxyTest, AdaptChangesStatsNotStartedIfVideoSuspended) {
|
||||
}
|
||||
|
||||
TEST_F(SendStatisticsProxyTest, AdaptChangesStatsRestartsOnFirstSentPacket) {
|
||||
// Send first packet, scaling enabled.
|
||||
// Send first packet, adaptation enabled.
|
||||
// Elapsed time before first packet is sent should be excluded.
|
||||
statistics_proxy_->SetQualityScalingStats(0);
|
||||
ViEEncoder::AdaptCounts cpu_counts;
|
||||
ViEEncoder::AdaptCounts quality_counts;
|
||||
statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts);
|
||||
fake_clock_.AdvanceTimeMilliseconds(10000);
|
||||
UpdateDataCounters(kFirstSsrc);
|
||||
|
||||
// Adapt changes: 1, elapsed time: 10 sec.
|
||||
fake_clock_.AdvanceTimeMilliseconds(10000);
|
||||
statistics_proxy_->OnQualityRestrictedResolutionChanged(1);
|
||||
statistics_proxy_->OnQualityAdaptationChanged(cpu_counts, quality_counts);
|
||||
UpdateDataCounters(kFirstSsrc);
|
||||
|
||||
// Adapt changes: 1, elapsed time: 10 sec => 6 per minute.
|
||||
@ -657,24 +710,29 @@ TEST_F(SendStatisticsProxyTest, AdaptChangesStatsRestartsOnFirstSentPacket) {
|
||||
}
|
||||
|
||||
TEST_F(SendStatisticsProxyTest, AdaptChangesStatsStartedAfterFirstSentPacket) {
|
||||
// Enable and disable scaling.
|
||||
statistics_proxy_->SetCpuScalingStats(0);
|
||||
// Enable and disable adaptation.
|
||||
ViEEncoder::AdaptCounts cpu_counts;
|
||||
ViEEncoder::AdaptCounts quality_counts;
|
||||
statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts);
|
||||
fake_clock_.AdvanceTimeMilliseconds(60000);
|
||||
statistics_proxy_->SetCpuScalingStats(-1);
|
||||
cpu_counts.fps = -1;
|
||||
cpu_counts.resolution = -1;
|
||||
statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts);
|
||||
|
||||
// Send first packet, scaling disabled.
|
||||
// Elapsed time before first packet is sent should be excluded.
|
||||
UpdateDataCounters(kFirstSsrc);
|
||||
fake_clock_.AdvanceTimeMilliseconds(60000);
|
||||
|
||||
// Enable scaling.
|
||||
statistics_proxy_->SetCpuScalingStats(0);
|
||||
// Enable adaptation.
|
||||
cpu_counts.resolution = 0;
|
||||
statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts);
|
||||
fake_clock_.AdvanceTimeMilliseconds(10000);
|
||||
UpdateDataCounters(kFirstSsrc);
|
||||
|
||||
// Adapt changes: 1, elapsed time: 20 sec.
|
||||
fake_clock_.AdvanceTimeMilliseconds(10000);
|
||||
statistics_proxy_->OnCpuRestrictedResolutionChanged(true);
|
||||
statistics_proxy_->OnCpuAdaptationChanged(cpu_counts, quality_counts);
|
||||
|
||||
// Adapt changes: 1, elapsed time: 20 sec => 3 per minute.
|
||||
statistics_proxy_.reset();
|
||||
@ -683,14 +741,18 @@ TEST_F(SendStatisticsProxyTest, AdaptChangesStatsStartedAfterFirstSentPacket) {
|
||||
}
|
||||
|
||||
TEST_F(SendStatisticsProxyTest, AdaptChangesReportedAfterContentSwitch) {
|
||||
// First RTP packet sent, scaling enabled.
|
||||
// First RTP packet sent, cpu adaptation enabled.
|
||||
UpdateDataCounters(kFirstSsrc);
|
||||
statistics_proxy_->SetCpuScalingStats(0);
|
||||
ViEEncoder::AdaptCounts cpu_counts;
|
||||
ViEEncoder::AdaptCounts quality_counts;
|
||||
quality_counts.fps = -1;
|
||||
quality_counts.resolution = -1;
|
||||
statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts);
|
||||
|
||||
// Adapt changes: 2, elapsed time: 15 sec => 8 per minute.
|
||||
statistics_proxy_->OnCpuRestrictedResolutionChanged(true);
|
||||
statistics_proxy_->OnCpuAdaptationChanged(cpu_counts, quality_counts);
|
||||
fake_clock_.AdvanceTimeMilliseconds(6000);
|
||||
statistics_proxy_->OnCpuRestrictedResolutionChanged(true);
|
||||
statistics_proxy_->OnCpuAdaptationChanged(cpu_counts, quality_counts);
|
||||
fake_clock_.AdvanceTimeMilliseconds(9000);
|
||||
|
||||
// Switch content type, real-time stats should be updated.
|
||||
@ -704,13 +766,13 @@ TEST_F(SendStatisticsProxyTest, AdaptChangesReportedAfterContentSwitch) {
|
||||
|
||||
// First RTP packet sent, scaling enabled.
|
||||
UpdateDataCounters(kFirstSsrc);
|
||||
statistics_proxy_->SetCpuScalingStats(0);
|
||||
statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts);
|
||||
|
||||
// Adapt changes: 4, elapsed time: 120 sec => 2 per minute.
|
||||
statistics_proxy_->OnCpuRestrictedResolutionChanged(true);
|
||||
statistics_proxy_->OnCpuRestrictedResolutionChanged(true);
|
||||
statistics_proxy_->OnCpuRestrictedResolutionChanged(true);
|
||||
statistics_proxy_->OnCpuRestrictedResolutionChanged(true);
|
||||
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);
|
||||
fake_clock_.AdvanceTimeMilliseconds(120000);
|
||||
|
||||
statistics_proxy_.reset();
|
||||
@ -842,8 +904,10 @@ TEST_F(SendStatisticsProxyTest, SentFpsHistogramExcludesSuspendedTime) {
|
||||
}
|
||||
|
||||
TEST_F(SendStatisticsProxyTest, CpuLimitedHistogramNotUpdatedWhenDisabled) {
|
||||
const int kNumDownscales = -1;
|
||||
statistics_proxy_->SetQualityScalingStats(kNumDownscales);
|
||||
ViEEncoder::AdaptCounts cpu_counts;
|
||||
ViEEncoder::AdaptCounts quality_counts;
|
||||
cpu_counts.resolution = -1;
|
||||
statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts);
|
||||
|
||||
for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
|
||||
statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
|
||||
@ -854,13 +918,16 @@ TEST_F(SendStatisticsProxyTest, CpuLimitedHistogramNotUpdatedWhenDisabled) {
|
||||
}
|
||||
|
||||
TEST_F(SendStatisticsProxyTest, CpuLimitedHistogramUpdated) {
|
||||
const int kNumDownscales = 0;
|
||||
statistics_proxy_->SetCpuScalingStats(kNumDownscales);
|
||||
ViEEncoder::AdaptCounts cpu_counts;
|
||||
ViEEncoder::AdaptCounts quality_counts;
|
||||
cpu_counts.resolution = 0;
|
||||
statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts);
|
||||
|
||||
for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
|
||||
statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
|
||||
|
||||
statistics_proxy_->OnCpuRestrictedResolutionChanged(true);
|
||||
cpu_counts.resolution = 1;
|
||||
statistics_proxy_->OnCpuAdaptationChanged(cpu_counts, quality_counts);
|
||||
|
||||
for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
|
||||
statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
|
||||
@ -1149,9 +1216,11 @@ TEST_F(SendStatisticsProxyTest,
|
||||
|
||||
TEST_F(SendStatisticsProxyTest,
|
||||
QualityLimitedHistogramsNotUpdatedWhenDisabled) {
|
||||
const int kNumDownscales = -1;
|
||||
ViEEncoder::AdaptCounts cpu_counts;
|
||||
ViEEncoder::AdaptCounts quality_counts;
|
||||
quality_counts.resolution = -1;
|
||||
statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts);
|
||||
EncodedImage encoded_image;
|
||||
statistics_proxy_->SetQualityScalingStats(kNumDownscales);
|
||||
for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
|
||||
statistics_proxy_->OnSendEncodedImage(encoded_image, &kDefaultCodecInfo);
|
||||
|
||||
@ -1165,9 +1234,11 @@ TEST_F(SendStatisticsProxyTest,
|
||||
|
||||
TEST_F(SendStatisticsProxyTest,
|
||||
QualityLimitedHistogramsUpdatedWhenEnabled_NoResolutionDownscale) {
|
||||
const int kNumDownscales = 0;
|
||||
ViEEncoder::AdaptCounts cpu_counts;
|
||||
ViEEncoder::AdaptCounts quality_counts;
|
||||
quality_counts.resolution = 0;
|
||||
statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts);
|
||||
EncodedImage encoded_image;
|
||||
statistics_proxy_->SetQualityScalingStats(kNumDownscales);
|
||||
for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
|
||||
statistics_proxy_->OnSendEncodedImage(encoded_image, &kDefaultCodecInfo);
|
||||
|
||||
@ -1185,8 +1256,11 @@ TEST_F(SendStatisticsProxyTest,
|
||||
TEST_F(SendStatisticsProxyTest,
|
||||
QualityLimitedHistogramsUpdatedWhenEnabled_TwoResolutionDownscales) {
|
||||
const int kDownscales = 2;
|
||||
ViEEncoder::AdaptCounts cpu_counts;
|
||||
ViEEncoder::AdaptCounts quality_counts;
|
||||
quality_counts.resolution = kDownscales;
|
||||
statistics_proxy_->SetAdaptationStats(cpu_counts, quality_counts);
|
||||
EncodedImage encoded_image;
|
||||
statistics_proxy_->OnQualityRestrictedResolutionChanged(kDownscales);
|
||||
for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
|
||||
statistics_proxy_->OnSendEncodedImage(encoded_image, &kDefaultCodecInfo);
|
||||
// Histograms are updated when the statistics_proxy_ is deleted.
|
||||
@ -1221,7 +1295,10 @@ TEST_F(SendStatisticsProxyTest, GetStatsReportsBandwidthLimitedResolution) {
|
||||
EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
|
||||
|
||||
// Resolution scaled due to quality.
|
||||
statistics_proxy_->OnQualityRestrictedResolutionChanged(1);
|
||||
ViEEncoder::AdaptCounts cpu_counts;
|
||||
ViEEncoder::AdaptCounts quality_counts;
|
||||
quality_counts.resolution = 1;
|
||||
statistics_proxy_->OnQualityAdaptationChanged(cpu_counts, quality_counts);
|
||||
statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
|
||||
EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution);
|
||||
}
|
||||
|
||||
@ -73,6 +73,22 @@ uint32_t MaximumFrameSizeForBitrate(uint32_t kbps) {
|
||||
return std::numeric_limits<uint32_t>::max();
|
||||
}
|
||||
|
||||
bool IsResolutionScalingEnabled(
|
||||
VideoSendStream::DegradationPreference degradation_preference) {
|
||||
return degradation_preference ==
|
||||
VideoSendStream::DegradationPreference::kMaintainFramerate ||
|
||||
degradation_preference ==
|
||||
VideoSendStream::DegradationPreference::kBalanced;
|
||||
}
|
||||
|
||||
bool IsFramerateScalingEnabled(
|
||||
VideoSendStream::DegradationPreference degradation_preference) {
|
||||
return degradation_preference ==
|
||||
VideoSendStream::DegradationPreference::kMaintainResolution ||
|
||||
degradation_preference ==
|
||||
VideoSendStream::DegradationPreference::kBalanced;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
class ViEEncoder::ConfigureEncoderTask : public rtc::QueuedTask {
|
||||
@ -420,8 +436,7 @@ void ViEEncoder::SetBitrateObserver(
|
||||
|
||||
void ViEEncoder::SetSource(
|
||||
rtc::VideoSourceInterface<VideoFrame>* source,
|
||||
const VideoSendStream::VideoSendStream::DegradationPreference&
|
||||
degradation_preference) {
|
||||
const VideoSendStream::DegradationPreference& degradation_preference) {
|
||||
RTC_DCHECK_RUN_ON(&thread_checker_);
|
||||
source_proxy_->SetSource(source, degradation_preference);
|
||||
encoder_queue_.PostTask([this, degradation_preference] {
|
||||
@ -547,27 +562,24 @@ void ViEEncoder::ConfigureQualityScaler() {
|
||||
const bool quality_scaling_allowed =
|
||||
degradation_preference_allows_scaling && scaling_settings.enabled;
|
||||
|
||||
const std::vector<int>& scale_counters = GetScaleCounters();
|
||||
stats_proxy_->SetCpuScalingStats(
|
||||
degradation_preference_allows_scaling ? scale_counters[kCpu] : -1);
|
||||
stats_proxy_->SetQualityScalingStats(
|
||||
quality_scaling_allowed ? scale_counters[kQuality] : -1);
|
||||
|
||||
if (quality_scaling_allowed) {
|
||||
// Abort if quality scaler has already been configured.
|
||||
if (quality_scaler_.get() != nullptr)
|
||||
return;
|
||||
// Drop frames and scale down until desired quality is achieved.
|
||||
if (scaling_settings.thresholds) {
|
||||
quality_scaler_.reset(
|
||||
new QualityScaler(this, *(scaling_settings.thresholds)));
|
||||
} else {
|
||||
quality_scaler_.reset(new QualityScaler(this, codec_type_));
|
||||
if (quality_scaler_.get() == nullptr) {
|
||||
// Quality scaler has not already been configured.
|
||||
// Drop frames and scale down until desired quality is achieved.
|
||||
if (scaling_settings.thresholds) {
|
||||
quality_scaler_.reset(
|
||||
new QualityScaler(this, *(scaling_settings.thresholds)));
|
||||
} else {
|
||||
quality_scaler_.reset(new QualityScaler(this, codec_type_));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
quality_scaler_.reset(nullptr);
|
||||
initial_rampup_ = kMaxInitialFramedrop;
|
||||
}
|
||||
|
||||
stats_proxy_->SetAdaptationStats(GetActiveCounts(kCpu),
|
||||
GetActiveCounts(kQuality));
|
||||
}
|
||||
|
||||
void ViEEncoder::OnFrame(const VideoFrame& video_frame) {
|
||||
@ -797,6 +809,7 @@ void ViEEncoder::AdaptDown(AdaptReason reason) {
|
||||
last_frame_info_->pixel_count(),
|
||||
stats_proxy_->GetStats().input_frame_rate,
|
||||
AdaptationRequest::Mode::kAdaptDown};
|
||||
|
||||
bool downgrade_requested =
|
||||
last_adaptation_request_ &&
|
||||
last_adaptation_request_->mode_ == AdaptationRequest::Mode::kAdaptDown;
|
||||
@ -834,8 +847,7 @@ void ViEEncoder::AdaptDown(AdaptReason reason) {
|
||||
}
|
||||
|
||||
if (reason == kCpu) {
|
||||
const int cpu_scale_counter = GetScaleCounters()[reason];
|
||||
if (cpu_scale_counter >= max_downgrades)
|
||||
if (GetConstAdaptCounter().TotalCount(kCpu) >= max_downgrades)
|
||||
return;
|
||||
}
|
||||
|
||||
@ -848,11 +860,13 @@ void ViEEncoder::AdaptDown(AdaptReason reason) {
|
||||
return;
|
||||
}
|
||||
LOG(LS_INFO) << "Scaling down resolution.";
|
||||
GetAdaptCounter().IncrementResolution(reason, 1);
|
||||
break;
|
||||
case VideoSendStream::DegradationPreference::kMaintainResolution:
|
||||
source_proxy_->RequestFramerateLowerThan(
|
||||
adaptation_request.framerate_fps_);
|
||||
LOG(LS_INFO) << "Scaling down framerate.";
|
||||
GetAdaptCounter().IncrementFramerate(reason, 1);
|
||||
break;
|
||||
case VideoSendStream::DegradationPreference::kDegradationDisabled:
|
||||
RTC_NOTREACHED();
|
||||
@ -860,32 +874,20 @@ void ViEEncoder::AdaptDown(AdaptReason reason) {
|
||||
|
||||
last_adaptation_request_.emplace(adaptation_request);
|
||||
|
||||
IncrementScaleCounter(reason, 1);
|
||||
UpdateAdaptationStats(reason);
|
||||
|
||||
// Update stats.
|
||||
const std::vector<int>& scale_counters = GetScaleCounters();
|
||||
switch (reason) {
|
||||
case kQuality:
|
||||
stats_proxy_->OnQualityRestrictedResolutionChanged(
|
||||
scale_counters[reason]);
|
||||
break;
|
||||
case kCpu:
|
||||
stats_proxy_->OnCpuRestrictedResolutionChanged(true);
|
||||
break;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < kScaleReasonSize; ++i) {
|
||||
LOG(LS_INFO) << "Scaled " << scale_counters[i]
|
||||
<< " times for reason: " << (i ? "cpu" : "quality");
|
||||
}
|
||||
LOG(LS_INFO) << GetConstAdaptCounter().ToString();
|
||||
}
|
||||
|
||||
void ViEEncoder::AdaptUp(AdaptReason reason) {
|
||||
RTC_DCHECK_RUN_ON(&encoder_queue_);
|
||||
int scale_counter = GetScaleCounters()[reason];
|
||||
if (scale_counter == 0)
|
||||
|
||||
const AdaptCounter& adapt_counter = GetConstAdaptCounter();
|
||||
int num_downgrades = adapt_counter.TotalCount(reason);
|
||||
if (num_downgrades == 0)
|
||||
return;
|
||||
RTC_DCHECK_GT(scale_counter, 0);
|
||||
RTC_DCHECK_GT(num_downgrades, 0);
|
||||
|
||||
AdaptationRequest adaptation_request = {
|
||||
last_frame_info_->pixel_count(),
|
||||
stats_proxy_->GetStats().input_frame_rate,
|
||||
@ -894,6 +896,7 @@ void ViEEncoder::AdaptUp(AdaptReason reason) {
|
||||
bool adapt_up_requested =
|
||||
last_adaptation_request_ &&
|
||||
last_adaptation_request_->mode_ == AdaptationRequest::Mode::kAdaptUp;
|
||||
|
||||
switch (degradation_preference_) {
|
||||
case VideoSendStream::DegradationPreference::kBalanced:
|
||||
FALLTHROUGH();
|
||||
@ -914,20 +917,11 @@ void ViEEncoder::AdaptUp(AdaptReason reason) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Decrease counter of how many times we have scaled down, for this
|
||||
// degradation preference mode and reason.
|
||||
IncrementScaleCounter(reason, -1);
|
||||
|
||||
// Get a sum of how many times have scaled down, in total, for this
|
||||
// degradation preference mode. If it is 0, remove any restraints.
|
||||
const std::vector<int>& scale_counters = GetScaleCounters();
|
||||
const int scale_sum =
|
||||
std::accumulate(scale_counters.begin(), scale_counters.end(), 0);
|
||||
switch (degradation_preference_) {
|
||||
case VideoSendStream::DegradationPreference::kBalanced:
|
||||
FALLTHROUGH();
|
||||
case VideoSendStream::DegradationPreference::kMaintainFramerate:
|
||||
if (scale_sum == 0) {
|
||||
if (adapt_counter.TotalCount() == 1) {
|
||||
LOG(LS_INFO) << "Removing resolution down-scaling setting.";
|
||||
source_proxy_->RequestHigherResolutionThan(
|
||||
std::numeric_limits<int>::max());
|
||||
@ -936,9 +930,10 @@ void ViEEncoder::AdaptUp(AdaptReason reason) {
|
||||
adaptation_request.input_pixel_count_);
|
||||
LOG(LS_INFO) << "Scaling up resolution.";
|
||||
}
|
||||
GetAdaptCounter().IncrementResolution(reason, -1);
|
||||
break;
|
||||
case VideoSendStream::DegradationPreference::kMaintainResolution:
|
||||
if (scale_sum == 0) {
|
||||
if (adapt_counter.TotalCount() == 1) {
|
||||
LOG(LS_INFO) << "Removing framerate down-scaling setting.";
|
||||
source_proxy_->RequestHigherFramerateThan(
|
||||
std::numeric_limits<int>::max());
|
||||
@ -947,6 +942,7 @@ void ViEEncoder::AdaptUp(AdaptReason reason) {
|
||||
adaptation_request.framerate_fps_);
|
||||
LOG(LS_INFO) << "Scaling up framerate.";
|
||||
}
|
||||
GetAdaptCounter().IncrementFramerate(reason, -1);
|
||||
break;
|
||||
case VideoSendStream::DegradationPreference::kDegradationDisabled:
|
||||
RTC_NOTREACHED();
|
||||
@ -954,40 +950,120 @@ void ViEEncoder::AdaptUp(AdaptReason reason) {
|
||||
|
||||
last_adaptation_request_.emplace(adaptation_request);
|
||||
|
||||
// Update stats.
|
||||
UpdateAdaptationStats(reason);
|
||||
|
||||
LOG(LS_INFO) << adapt_counter.ToString();
|
||||
}
|
||||
|
||||
void ViEEncoder::UpdateAdaptationStats(AdaptReason reason) {
|
||||
switch (reason) {
|
||||
case kQuality:
|
||||
stats_proxy_->OnQualityRestrictedResolutionChanged(
|
||||
scale_counters[reason]);
|
||||
break;
|
||||
case kCpu:
|
||||
stats_proxy_->OnCpuRestrictedResolutionChanged(scale_counters[reason] >
|
||||
0);
|
||||
stats_proxy_->OnCpuAdaptationChanged(GetActiveCounts(kCpu),
|
||||
GetActiveCounts(kQuality));
|
||||
break;
|
||||
case kQuality:
|
||||
stats_proxy_->OnQualityAdaptationChanged(GetActiveCounts(kCpu),
|
||||
GetActiveCounts(kQuality));
|
||||
break;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < kScaleReasonSize; ++i) {
|
||||
LOG(LS_INFO) << "Scaled " << scale_counters[i]
|
||||
<< " times for reason: " << (i ? "cpu" : "quality");
|
||||
}
|
||||
}
|
||||
|
||||
const std::vector<int>& ViEEncoder::GetScaleCounters() {
|
||||
auto it = scale_counters_.find(degradation_preference_);
|
||||
if (it == scale_counters_.end()) {
|
||||
scale_counters_[degradation_preference_].resize(kScaleReasonSize);
|
||||
return scale_counters_[degradation_preference_];
|
||||
ViEEncoder::AdaptCounts ViEEncoder::GetActiveCounts(AdaptReason reason) {
|
||||
ViEEncoder::AdaptCounts counts = GetConstAdaptCounter().Counts(reason);
|
||||
switch (reason) {
|
||||
case kCpu:
|
||||
if (!IsFramerateScalingEnabled(degradation_preference_))
|
||||
counts.fps = -1;
|
||||
if (!IsResolutionScalingEnabled(degradation_preference_))
|
||||
counts.resolution = -1;
|
||||
break;
|
||||
case kQuality:
|
||||
if (!IsFramerateScalingEnabled(degradation_preference_) ||
|
||||
!quality_scaler_) {
|
||||
counts.fps = -1;
|
||||
}
|
||||
if (!IsResolutionScalingEnabled(degradation_preference_) ||
|
||||
!quality_scaler_) {
|
||||
counts.resolution = -1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return it->second;
|
||||
return counts;
|
||||
}
|
||||
|
||||
void ViEEncoder::IncrementScaleCounter(int reason, int delta) {
|
||||
// Get the counters and validate. This may also lazily initialize the state.
|
||||
const std::vector<int>& counter = GetScaleCounters();
|
||||
if (delta < 0) {
|
||||
RTC_DCHECK_GE(counter[reason], delta);
|
||||
ViEEncoder::AdaptCounter& ViEEncoder::GetAdaptCounter() {
|
||||
return adapt_counters_[degradation_preference_];
|
||||
}
|
||||
|
||||
const ViEEncoder::AdaptCounter& ViEEncoder::GetConstAdaptCounter() {
|
||||
return adapt_counters_[degradation_preference_];
|
||||
}
|
||||
|
||||
// Class holding adaptation information.
|
||||
ViEEncoder::AdaptCounter::AdaptCounter() {
|
||||
fps_counters_.resize(kScaleReasonSize);
|
||||
resolution_counters_.resize(kScaleReasonSize);
|
||||
}
|
||||
|
||||
ViEEncoder::AdaptCounter::~AdaptCounter() {}
|
||||
|
||||
std::string ViEEncoder::AdaptCounter::ToString() const {
|
||||
std::stringstream ss;
|
||||
ss << "Downgrade counts: fps: {" << ToString(fps_counters_);
|
||||
ss << "}, resolution: {" << ToString(resolution_counters_) << "}";
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
ViEEncoder::AdaptCounts ViEEncoder::AdaptCounter::Counts(int reason) const {
|
||||
AdaptCounts counts;
|
||||
counts.fps = fps_counters_[reason];
|
||||
counts.resolution = resolution_counters_[reason];
|
||||
return counts;
|
||||
}
|
||||
|
||||
void ViEEncoder::AdaptCounter::IncrementFramerate(int reason, int delta) {
|
||||
fps_counters_[reason] += delta;
|
||||
}
|
||||
|
||||
void ViEEncoder::AdaptCounter::IncrementResolution(int reason, int delta) {
|
||||
resolution_counters_[reason] += delta;
|
||||
}
|
||||
|
||||
int ViEEncoder::AdaptCounter::FramerateCount() const {
|
||||
return Count(fps_counters_);
|
||||
}
|
||||
|
||||
int ViEEncoder::AdaptCounter::ResolutionCount() const {
|
||||
return Count(resolution_counters_);
|
||||
}
|
||||
|
||||
int ViEEncoder::AdaptCounter::TotalCount() const {
|
||||
return FramerateCount() + ResolutionCount();
|
||||
}
|
||||
|
||||
int ViEEncoder::AdaptCounter::FramerateCount(int reason) const {
|
||||
return fps_counters_[reason];
|
||||
}
|
||||
|
||||
int ViEEncoder::AdaptCounter::ResolutionCount(int reason) const {
|
||||
return resolution_counters_[reason];
|
||||
}
|
||||
|
||||
int ViEEncoder::AdaptCounter::TotalCount(int reason) const {
|
||||
return FramerateCount(reason) + ResolutionCount(reason);
|
||||
}
|
||||
|
||||
int ViEEncoder::AdaptCounter::Count(const std::vector<int>& counters) const {
|
||||
return std::accumulate(counters.begin(), counters.end(), 0);
|
||||
}
|
||||
|
||||
std::string ViEEncoder::AdaptCounter::ToString(
|
||||
const std::vector<int>& counters) const {
|
||||
std::stringstream ss;
|
||||
for (size_t reason = 0; reason < kScaleReasonSize; ++reason) {
|
||||
ss << (reason ? " cpu" : "quality") << ":" << counters[reason];
|
||||
}
|
||||
scale_counters_[degradation_preference_][reason] += delta;
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
@ -62,6 +62,12 @@ class ViEEncoder : public rtc::VideoSinkInterface<VideoFrame>,
|
||||
int min_transmit_bitrate_bps) = 0;
|
||||
};
|
||||
|
||||
// Number of resolution and framerate reductions (-1: disabled).
|
||||
struct AdaptCounts {
|
||||
int resolution = 0;
|
||||
int fps = 0;
|
||||
};
|
||||
|
||||
// Downscale resolution at most 2 times for CPU reasons.
|
||||
static const int kMaxCpuResolutionDowngrades = 2;
|
||||
// Downscale framerate at most 4 times.
|
||||
@ -172,10 +178,44 @@ class ViEEncoder : public rtc::VideoSinkInterface<VideoFrame>,
|
||||
void TraceFrameDropStart();
|
||||
void TraceFrameDropEnd();
|
||||
|
||||
const std::vector<int>& GetScaleCounters()
|
||||
EXCLUSIVE_LOCKS_REQUIRED(&encoder_queue_);
|
||||
void IncrementScaleCounter(int reason, int delta)
|
||||
EXCLUSIVE_LOCKS_REQUIRED(&encoder_queue_);
|
||||
// Class holding adaptation information.
|
||||
class AdaptCounter final {
|
||||
public:
|
||||
AdaptCounter();
|
||||
~AdaptCounter();
|
||||
|
||||
// Get number of adaptation downscales for |reason|.
|
||||
AdaptCounts Counts(int reason) const;
|
||||
|
||||
std::string ToString() const;
|
||||
|
||||
void IncrementFramerate(int reason, int delta);
|
||||
void IncrementResolution(int reason, int delta);
|
||||
|
||||
// Gets the total number of downgrades (for all adapt reasons).
|
||||
int FramerateCount() const;
|
||||
int ResolutionCount() const;
|
||||
int TotalCount() const;
|
||||
|
||||
// Gets the total number of downgrades for |reason|.
|
||||
int FramerateCount(int reason) const;
|
||||
int ResolutionCount(int reason) const;
|
||||
int TotalCount(int reason) const;
|
||||
|
||||
private:
|
||||
std::string ToString(const std::vector<int>& counters) const;
|
||||
int Count(const std::vector<int>& counters) const;
|
||||
|
||||
// Degradation counters holding number of framerate/resolution reductions
|
||||
// per adapt reason.
|
||||
std::vector<int> fps_counters_;
|
||||
std::vector<int> resolution_counters_;
|
||||
};
|
||||
|
||||
AdaptCounter& GetAdaptCounter() RUN_ON(&encoder_queue_);
|
||||
const AdaptCounter& GetConstAdaptCounter() RUN_ON(&encoder_queue_);
|
||||
void UpdateAdaptationStats(AdaptReason reason) RUN_ON(&encoder_queue_);
|
||||
AdaptCounts GetActiveCounts(AdaptReason reason) RUN_ON(&encoder_queue_);
|
||||
|
||||
rtc::Event shutdown_event_;
|
||||
|
||||
@ -214,13 +254,14 @@ class ViEEncoder : public rtc::VideoSinkInterface<VideoFrame>,
|
||||
uint32_t last_observed_bitrate_bps_ ACCESS_ON(&encoder_queue_);
|
||||
bool encoder_paused_and_dropped_frame_ ACCESS_ON(&encoder_queue_);
|
||||
Clock* const clock_;
|
||||
// Counters used for deciding if the video resolution is currently
|
||||
// restricted, and if so, why, on a per degradation preference basis.
|
||||
// Counters used for deciding if the video resolution or framerate is
|
||||
// currently restricted, and if so, why, on a per degradation preference
|
||||
// basis.
|
||||
// TODO(sprang): Replace this with a state holding a relative overuse measure
|
||||
// instead, that can be translated into suitable down-scale or fps limit.
|
||||
std::map<const VideoSendStream::DegradationPreference, std::vector<int>>
|
||||
scale_counters_ ACCESS_ON(&encoder_queue_);
|
||||
// Set depending on degradation preferences
|
||||
std::map<const VideoSendStream::DegradationPreference, AdaptCounter>
|
||||
adapt_counters_ ACCESS_ON(&encoder_queue_);
|
||||
// Set depending on degradation preferences.
|
||||
VideoSendStream::DegradationPreference degradation_preference_
|
||||
ACCESS_ON(&encoder_queue_);
|
||||
|
||||
|
||||
@ -139,6 +139,11 @@ class AdaptingFrameForwarder : public test::FrameForwarder {
|
||||
return adaptation_enabled_;
|
||||
}
|
||||
|
||||
rtc::VideoSinkWants last_wants() const {
|
||||
rtc::CritScope cs(&crit_);
|
||||
return last_wants_;
|
||||
}
|
||||
|
||||
void IncomingCapturedFrame(const VideoFrame& video_frame) override {
|
||||
int cropped_width = 0;
|
||||
int cropped_height = 0;
|
||||
@ -163,14 +168,15 @@ class AdaptingFrameForwarder : public test::FrameForwarder {
|
||||
void AddOrUpdateSink(rtc::VideoSinkInterface<VideoFrame>* sink,
|
||||
const rtc::VideoSinkWants& wants) override {
|
||||
rtc::CritScope cs(&crit_);
|
||||
last_wants_ = sink_wants();
|
||||
adapter_.OnResolutionFramerateRequest(wants.target_pixel_count,
|
||||
wants.max_pixel_count,
|
||||
wants.max_framerate_fps);
|
||||
test::FrameForwarder::AddOrUpdateSink(sink, wants);
|
||||
}
|
||||
|
||||
cricket::VideoAdapter adapter_;
|
||||
bool adaptation_enabled_ GUARDED_BY(crit_);
|
||||
rtc::VideoSinkWants last_wants_ GUARDED_BY(crit_);
|
||||
};
|
||||
|
||||
class MockableSendStatisticsProxy : public SendStatisticsProxy {
|
||||
@ -281,16 +287,41 @@ class ViEEncoderTest : public ::testing::Test {
|
||||
}
|
||||
|
||||
void VerifyNoLimitation(const rtc::VideoSinkWants& wants) {
|
||||
EXPECT_FALSE(wants.target_pixel_count);
|
||||
EXPECT_EQ(std::numeric_limits<int>::max(), wants.max_pixel_count);
|
||||
EXPECT_EQ(std::numeric_limits<int>::max(), wants.max_framerate_fps);
|
||||
EXPECT_EQ(std::numeric_limits<int>::max(), wants.max_pixel_count);
|
||||
EXPECT_FALSE(wants.target_pixel_count);
|
||||
}
|
||||
|
||||
void VerifyResolutionLimitationLessThan(const rtc::VideoSinkWants& wants,
|
||||
int pixel_count) {
|
||||
void VerifyFpsEqResolutionEq(const rtc::VideoSinkWants& wants1,
|
||||
const rtc::VideoSinkWants& wants2) {
|
||||
EXPECT_EQ(wants1.max_framerate_fps, wants2.max_framerate_fps);
|
||||
EXPECT_EQ(wants1.max_pixel_count, wants2.max_pixel_count);
|
||||
}
|
||||
|
||||
void VerifyFpsMaxResolutionLt(const rtc::VideoSinkWants& wants1,
|
||||
const rtc::VideoSinkWants& wants2) {
|
||||
EXPECT_EQ(std::numeric_limits<int>::max(), wants1.max_framerate_fps);
|
||||
EXPECT_LT(wants1.max_pixel_count, wants2.max_pixel_count);
|
||||
EXPECT_GT(wants1.max_pixel_count, 0);
|
||||
}
|
||||
|
||||
void VerifyFpsMaxResolutionGt(const rtc::VideoSinkWants& wants1,
|
||||
const rtc::VideoSinkWants& wants2) {
|
||||
EXPECT_EQ(std::numeric_limits<int>::max(), wants1.max_framerate_fps);
|
||||
EXPECT_GT(wants1.max_pixel_count, wants2.max_pixel_count);
|
||||
}
|
||||
|
||||
void VerifyFpsMaxResolutionLt(const rtc::VideoSinkWants& wants,
|
||||
int pixel_count) {
|
||||
EXPECT_EQ(std::numeric_limits<int>::max(), wants.max_framerate_fps);
|
||||
EXPECT_LT(wants.max_pixel_count, pixel_count);
|
||||
EXPECT_GT(wants.max_pixel_count, 0);
|
||||
EXPECT_EQ(std::numeric_limits<int>::max(), wants.max_framerate_fps);
|
||||
}
|
||||
|
||||
void VerifyFpsLtResolutionMax(const rtc::VideoSinkWants& wants, int fps) {
|
||||
EXPECT_LT(wants.max_framerate_fps, fps);
|
||||
EXPECT_EQ(std::numeric_limits<int>::max(), wants.max_pixel_count);
|
||||
EXPECT_FALSE(wants.target_pixel_count);
|
||||
}
|
||||
|
||||
class TestEncoder : public test::FakeEncoder {
|
||||
@ -946,6 +977,7 @@ TEST_F(ViEEncoderTest, SwitchingSourceKeepsCpuAdaptation) {
|
||||
video_source_.IncomingCapturedFrame(CreateFrame(1, kWidth, kHeight));
|
||||
sink_.WaitForEncodedFrame(1);
|
||||
VideoSendStream::Stats stats = stats_proxy_->GetStats();
|
||||
EXPECT_FALSE(stats.bw_limited_resolution);
|
||||
EXPECT_FALSE(stats.cpu_limited_resolution);
|
||||
EXPECT_EQ(0, stats.number_of_cpu_adapt_changes);
|
||||
|
||||
@ -954,6 +986,7 @@ TEST_F(ViEEncoderTest, SwitchingSourceKeepsCpuAdaptation) {
|
||||
video_source_.IncomingCapturedFrame(CreateFrame(2, kWidth, kHeight));
|
||||
sink_.WaitForEncodedFrame(2);
|
||||
stats = stats_proxy_->GetStats();
|
||||
EXPECT_FALSE(stats.bw_limited_resolution);
|
||||
EXPECT_TRUE(stats.cpu_limited_resolution);
|
||||
EXPECT_EQ(1, stats.number_of_cpu_adapt_changes);
|
||||
|
||||
@ -966,6 +999,7 @@ TEST_F(ViEEncoderTest, SwitchingSourceKeepsCpuAdaptation) {
|
||||
new_video_source.IncomingCapturedFrame(CreateFrame(3, kWidth, kHeight));
|
||||
sink_.WaitForEncodedFrame(3);
|
||||
stats = stats_proxy_->GetStats();
|
||||
EXPECT_FALSE(stats.bw_limited_resolution);
|
||||
EXPECT_TRUE(stats.cpu_limited_resolution);
|
||||
EXPECT_EQ(1, stats.number_of_cpu_adapt_changes);
|
||||
|
||||
@ -977,6 +1011,7 @@ TEST_F(ViEEncoderTest, SwitchingSourceKeepsCpuAdaptation) {
|
||||
new_video_source.IncomingCapturedFrame(CreateFrame(4, kWidth, kHeight));
|
||||
sink_.WaitForEncodedFrame(4);
|
||||
stats = stats_proxy_->GetStats();
|
||||
EXPECT_FALSE(stats.bw_limited_resolution);
|
||||
EXPECT_FALSE(stats.cpu_limited_resolution);
|
||||
EXPECT_EQ(1, stats.number_of_cpu_adapt_changes);
|
||||
|
||||
@ -988,6 +1023,7 @@ TEST_F(ViEEncoderTest, SwitchingSourceKeepsCpuAdaptation) {
|
||||
new_video_source.IncomingCapturedFrame(CreateFrame(5, kWidth, kHeight));
|
||||
sink_.WaitForEncodedFrame(5);
|
||||
stats = stats_proxy_->GetStats();
|
||||
EXPECT_FALSE(stats.bw_limited_resolution);
|
||||
EXPECT_TRUE(stats.cpu_limited_resolution);
|
||||
EXPECT_EQ(1, stats.number_of_cpu_adapt_changes);
|
||||
|
||||
@ -996,6 +1032,7 @@ TEST_F(ViEEncoderTest, SwitchingSourceKeepsCpuAdaptation) {
|
||||
new_video_source.IncomingCapturedFrame(CreateFrame(6, kWidth, kHeight));
|
||||
sink_.WaitForEncodedFrame(6);
|
||||
stats = stats_proxy_->GetStats();
|
||||
EXPECT_FALSE(stats.bw_limited_resolution);
|
||||
EXPECT_FALSE(stats.cpu_limited_resolution);
|
||||
EXPECT_EQ(2, stats.number_of_cpu_adapt_changes);
|
||||
EXPECT_EQ(0, stats.number_of_quality_adapt_changes);
|
||||
@ -1138,6 +1175,7 @@ TEST_F(ViEEncoderTest, StatsTracksCpuAdaptationStatsWhenSwitchingSource) {
|
||||
sink_.WaitForEncodedFrame(sequence++);
|
||||
stats = stats_proxy_->GetStats();
|
||||
EXPECT_TRUE(stats.cpu_limited_resolution);
|
||||
EXPECT_FALSE(stats.cpu_limited_framerate);
|
||||
EXPECT_EQ(1, stats.number_of_cpu_adapt_changes);
|
||||
|
||||
// Set cpu adaptation by frame dropping.
|
||||
@ -1150,10 +1188,11 @@ TEST_F(ViEEncoderTest, StatsTracksCpuAdaptationStatsWhenSwitchingSource) {
|
||||
stats = stats_proxy_->GetStats();
|
||||
// Not adapted at first.
|
||||
EXPECT_FALSE(stats.cpu_limited_resolution);
|
||||
EXPECT_FALSE(stats.cpu_limited_framerate);
|
||||
EXPECT_EQ(1, stats.number_of_cpu_adapt_changes);
|
||||
|
||||
// Force an input frame rate to be available, or the adaptation call won't
|
||||
// know what framerate to adapt form.
|
||||
// know what framerate to adapt from.
|
||||
VideoSendStream::Stats mock_stats = stats_proxy_->GetStats();
|
||||
mock_stats.input_frame_rate = 30;
|
||||
stats_proxy_->SetMockStats(mock_stats);
|
||||
@ -1166,7 +1205,8 @@ TEST_F(ViEEncoderTest, StatsTracksCpuAdaptationStatsWhenSwitchingSource) {
|
||||
|
||||
// Framerate now adapted.
|
||||
stats = stats_proxy_->GetStats();
|
||||
EXPECT_TRUE(stats.cpu_limited_resolution);
|
||||
EXPECT_FALSE(stats.cpu_limited_resolution);
|
||||
EXPECT_TRUE(stats.cpu_limited_framerate);
|
||||
EXPECT_EQ(2, stats.number_of_cpu_adapt_changes);
|
||||
|
||||
// Disable CPU adaptation.
|
||||
@ -1314,7 +1354,7 @@ TEST_F(ViEEncoderTest, SkipsSameAdaptDownRequest_MaintainFramerateMode) {
|
||||
|
||||
// Trigger adapt down, expect scaled down resolution.
|
||||
vie_encoder_->TriggerCpuOveruse();
|
||||
VerifyResolutionLimitationLessThan(source.sink_wants(), kWidth * kHeight);
|
||||
VerifyFpsMaxResolutionLt(source.sink_wants(), kWidth * kHeight);
|
||||
const int kLastMaxPixelCount = source.sink_wants().max_pixel_count;
|
||||
EXPECT_TRUE(stats_proxy_->GetStats().cpu_limited_resolution);
|
||||
EXPECT_EQ(1, stats_proxy_->GetStats().number_of_cpu_adapt_changes);
|
||||
@ -1366,18 +1406,45 @@ TEST_F(ViEEncoderTest, NoChangeForInitialNormalUsage_MaintainResolutionMode) {
|
||||
source.IncomingCapturedFrame(CreateFrame(1, kWidth, kHeight));
|
||||
sink_.WaitForEncodedFrame(kWidth, kHeight);
|
||||
VerifyNoLimitation(source.sink_wants());
|
||||
EXPECT_FALSE(stats_proxy_->GetStats().cpu_limited_resolution);
|
||||
EXPECT_FALSE(stats_proxy_->GetStats().cpu_limited_framerate);
|
||||
EXPECT_EQ(0, stats_proxy_->GetStats().number_of_cpu_adapt_changes);
|
||||
|
||||
// Trigger adapt up, expect no change.
|
||||
vie_encoder_->TriggerCpuNormalUsage();
|
||||
VerifyNoLimitation(source.sink_wants());
|
||||
EXPECT_FALSE(stats_proxy_->GetStats().cpu_limited_resolution);
|
||||
EXPECT_FALSE(stats_proxy_->GetStats().cpu_limited_framerate);
|
||||
EXPECT_EQ(0, stats_proxy_->GetStats().number_of_cpu_adapt_changes);
|
||||
|
||||
vie_encoder_->Stop();
|
||||
}
|
||||
|
||||
TEST_F(ViEEncoderTest, NoChangeForInitialNormalUsage_DisabledMode) {
|
||||
const int kWidth = 1280;
|
||||
const int kHeight = 720;
|
||||
vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
|
||||
|
||||
// Enable kDegradationDisabled preference, no initial limitation.
|
||||
test::FrameForwarder source;
|
||||
vie_encoder_->SetSource(
|
||||
&source, VideoSendStream::DegradationPreference::kDegradationDisabled);
|
||||
|
||||
source.IncomingCapturedFrame(CreateFrame(1, kWidth, kHeight));
|
||||
sink_.WaitForEncodedFrame(kWidth, kHeight);
|
||||
VerifyNoLimitation(source.sink_wants());
|
||||
EXPECT_FALSE(stats_proxy_->GetStats().bw_limited_resolution);
|
||||
EXPECT_FALSE(stats_proxy_->GetStats().cpu_limited_framerate);
|
||||
EXPECT_EQ(0, stats_proxy_->GetStats().number_of_quality_adapt_changes);
|
||||
|
||||
// Trigger adapt up, expect no change.
|
||||
vie_encoder_->TriggerQualityHigh();
|
||||
VerifyNoLimitation(source.sink_wants());
|
||||
EXPECT_FALSE(stats_proxy_->GetStats().bw_limited_resolution);
|
||||
EXPECT_FALSE(stats_proxy_->GetStats().cpu_limited_framerate);
|
||||
EXPECT_EQ(0, stats_proxy_->GetStats().number_of_quality_adapt_changes);
|
||||
|
||||
vie_encoder_->Stop();
|
||||
}
|
||||
|
||||
TEST_F(ViEEncoderTest, AdaptsResolutionForLowQuality_MaintainFramerateMode) {
|
||||
const int kWidth = 1280;
|
||||
const int kHeight = 720;
|
||||
@ -1399,7 +1466,7 @@ TEST_F(ViEEncoderTest, AdaptsResolutionForLowQuality_MaintainFramerateMode) {
|
||||
vie_encoder_->TriggerQualityLow();
|
||||
source.IncomingCapturedFrame(CreateFrame(2, kWidth, kHeight));
|
||||
sink_.WaitForEncodedFrame(2);
|
||||
VerifyResolutionLimitationLessThan(source.sink_wants(), kWidth * kHeight);
|
||||
VerifyFpsMaxResolutionLt(source.sink_wants(), kWidth * kHeight);
|
||||
EXPECT_TRUE(stats_proxy_->GetStats().bw_limited_resolution);
|
||||
EXPECT_EQ(1, stats_proxy_->GetStats().number_of_quality_adapt_changes);
|
||||
|
||||
@ -1413,6 +1480,47 @@ TEST_F(ViEEncoderTest, AdaptsResolutionForLowQuality_MaintainFramerateMode) {
|
||||
vie_encoder_->Stop();
|
||||
}
|
||||
|
||||
TEST_F(ViEEncoderTest, AdaptsFramerateForLowQuality_MaintainResolutionMode) {
|
||||
const int kWidth = 1280;
|
||||
const int kHeight = 720;
|
||||
const int kInputFps = 30;
|
||||
vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
|
||||
|
||||
VideoSendStream::Stats stats = stats_proxy_->GetStats();
|
||||
stats.input_frame_rate = kInputFps;
|
||||
stats_proxy_->SetMockStats(stats);
|
||||
|
||||
// Expect no scaling to begin with (preference: kMaintainFramerate).
|
||||
video_source_.IncomingCapturedFrame(CreateFrame(1, kWidth, kHeight));
|
||||
sink_.WaitForEncodedFrame(1);
|
||||
VerifyNoLimitation(video_source_.sink_wants());
|
||||
|
||||
// Trigger adapt down, expect scaled down resolution.
|
||||
vie_encoder_->TriggerQualityLow();
|
||||
video_source_.IncomingCapturedFrame(CreateFrame(2, kWidth, kHeight));
|
||||
sink_.WaitForEncodedFrame(2);
|
||||
VerifyFpsMaxResolutionLt(video_source_.sink_wants(), kWidth * kHeight);
|
||||
|
||||
// Enable kMaintainResolution preference.
|
||||
test::FrameForwarder new_video_source;
|
||||
vie_encoder_->SetSource(
|
||||
&new_video_source,
|
||||
VideoSendStream::DegradationPreference::kMaintainResolution);
|
||||
VerifyNoLimitation(new_video_source.sink_wants());
|
||||
|
||||
// Trigger adapt down, expect reduced framerate.
|
||||
vie_encoder_->TriggerQualityLow();
|
||||
new_video_source.IncomingCapturedFrame(CreateFrame(3, kWidth, kHeight));
|
||||
sink_.WaitForEncodedFrame(3);
|
||||
VerifyFpsLtResolutionMax(new_video_source.sink_wants(), kInputFps);
|
||||
|
||||
// Trigger adapt up, expect no restriction.
|
||||
vie_encoder_->TriggerQualityHigh();
|
||||
VerifyNoLimitation(new_video_source.sink_wants());
|
||||
|
||||
vie_encoder_->Stop();
|
||||
}
|
||||
|
||||
TEST_F(ViEEncoderTest, DoesNotScaleBelowSetResolutionLimit) {
|
||||
const int kWidth = 1280;
|
||||
const int kHeight = 720;
|
||||
@ -1461,7 +1569,7 @@ TEST_F(ViEEncoderTest,
|
||||
&source, VideoSendStream::DegradationPreference::kMaintainFramerate);
|
||||
|
||||
source.IncomingCapturedFrame(CreateFrame(1, kWidth, kHeight));
|
||||
sink_.WaitForEncodedFrame(1);
|
||||
sink_.WaitForEncodedFrame(kWidth, kHeight);
|
||||
VerifyNoLimitation(source.sink_wants());
|
||||
EXPECT_FALSE(stats_proxy_->GetStats().cpu_limited_resolution);
|
||||
EXPECT_EQ(0, stats_proxy_->GetStats().number_of_cpu_adapt_changes);
|
||||
@ -1470,14 +1578,14 @@ TEST_F(ViEEncoderTest,
|
||||
vie_encoder_->TriggerCpuOveruse();
|
||||
source.IncomingCapturedFrame(CreateFrame(2, kWidth, kHeight));
|
||||
sink_.WaitForEncodedFrame(2);
|
||||
VerifyResolutionLimitationLessThan(source.sink_wants(), kWidth * kHeight);
|
||||
VerifyFpsMaxResolutionLt(source.sink_wants(), kWidth * kHeight);
|
||||
EXPECT_TRUE(stats_proxy_->GetStats().cpu_limited_resolution);
|
||||
EXPECT_EQ(1, stats_proxy_->GetStats().number_of_cpu_adapt_changes);
|
||||
|
||||
// Trigger adapt up, expect no restriction.
|
||||
vie_encoder_->TriggerCpuNormalUsage();
|
||||
source.IncomingCapturedFrame(CreateFrame(3, kWidth, kHeight));
|
||||
sink_.WaitForEncodedFrame(3);
|
||||
sink_.WaitForEncodedFrame(kWidth, kHeight);
|
||||
VerifyNoLimitation(source.sink_wants());
|
||||
EXPECT_FALSE(stats_proxy_->GetStats().cpu_limited_resolution);
|
||||
EXPECT_EQ(2, stats_proxy_->GetStats().number_of_cpu_adapt_changes);
|
||||
@ -1486,12 +1594,14 @@ TEST_F(ViEEncoderTest,
|
||||
vie_encoder_->TriggerCpuOveruse();
|
||||
source.IncomingCapturedFrame(CreateFrame(4, kWidth, kHeight));
|
||||
sink_.WaitForEncodedFrame(4);
|
||||
VerifyResolutionLimitationLessThan(source.sink_wants(), kWidth * kHeight);
|
||||
VerifyFpsMaxResolutionLt(source.sink_wants(), kWidth * kHeight);
|
||||
EXPECT_TRUE(stats_proxy_->GetStats().cpu_limited_resolution);
|
||||
EXPECT_EQ(3, stats_proxy_->GetStats().number_of_cpu_adapt_changes);
|
||||
|
||||
// Trigger adapt up, expect no restriction.
|
||||
vie_encoder_->TriggerCpuNormalUsage();
|
||||
source.IncomingCapturedFrame(CreateFrame(5, kWidth, kHeight));
|
||||
sink_.WaitForEncodedFrame(kWidth, kHeight);
|
||||
VerifyNoLimitation(source.sink_wants());
|
||||
EXPECT_FALSE(stats_proxy_->GetStats().cpu_limited_resolution);
|
||||
EXPECT_EQ(4, stats_proxy_->GetStats().number_of_cpu_adapt_changes);
|
||||
@ -1523,8 +1633,7 @@ TEST_F(ViEEncoderTest,
|
||||
vie_encoder_->TriggerCpuOveruse();
|
||||
source.IncomingCapturedFrame(CreateFrame(2, kWidth, kHeight));
|
||||
sink_.WaitForEncodedFrame(2);
|
||||
VerifyResolutionLimitationLessThan(source.sink_wants(), kWidth * kHeight);
|
||||
rtc::VideoSinkWants last_wants = source.sink_wants();
|
||||
VerifyFpsMaxResolutionLt(source.sink_wants(), kWidth * kHeight);
|
||||
EXPECT_TRUE(stats_proxy_->GetStats().cpu_limited_resolution);
|
||||
EXPECT_FALSE(stats_proxy_->GetStats().bw_limited_resolution);
|
||||
EXPECT_EQ(1, stats_proxy_->GetStats().number_of_cpu_adapt_changes);
|
||||
@ -1534,8 +1643,8 @@ TEST_F(ViEEncoderTest,
|
||||
vie_encoder_->TriggerCpuOveruse();
|
||||
source.IncomingCapturedFrame(CreateFrame(3, kWidth, kHeight));
|
||||
sink_.WaitForEncodedFrame(3);
|
||||
EXPECT_LT(source.sink_wants().max_pixel_count, last_wants.max_pixel_count);
|
||||
last_wants = source.sink_wants();
|
||||
VerifyFpsMaxResolutionLt(source.sink_wants(), source.last_wants());
|
||||
rtc::VideoSinkWants last_wants = source.sink_wants();
|
||||
EXPECT_TRUE(stats_proxy_->GetStats().cpu_limited_resolution);
|
||||
EXPECT_FALSE(stats_proxy_->GetStats().bw_limited_resolution);
|
||||
EXPECT_EQ(2, stats_proxy_->GetStats().number_of_cpu_adapt_changes);
|
||||
@ -1545,7 +1654,7 @@ TEST_F(ViEEncoderTest,
|
||||
vie_encoder_->TriggerCpuOveruse();
|
||||
source.IncomingCapturedFrame(CreateFrame(4, kWidth, kHeight));
|
||||
sink_.WaitForEncodedFrame(4);
|
||||
EXPECT_EQ(last_wants.max_pixel_count, source.sink_wants().max_pixel_count);
|
||||
VerifyFpsEqResolutionEq(source.sink_wants(), last_wants);
|
||||
EXPECT_TRUE(stats_proxy_->GetStats().cpu_limited_resolution);
|
||||
EXPECT_FALSE(stats_proxy_->GetStats().bw_limited_resolution);
|
||||
EXPECT_EQ(2, stats_proxy_->GetStats().number_of_cpu_adapt_changes);
|
||||
@ -1555,8 +1664,7 @@ TEST_F(ViEEncoderTest,
|
||||
vie_encoder_->TriggerQualityLow();
|
||||
source.IncomingCapturedFrame(CreateFrame(5, kWidth, kHeight));
|
||||
sink_.WaitForEncodedFrame(5);
|
||||
EXPECT_LT(source.sink_wants().max_pixel_count, last_wants.max_pixel_count);
|
||||
last_wants = source.sink_wants();
|
||||
VerifyFpsMaxResolutionLt(source.sink_wants(), source.last_wants());
|
||||
EXPECT_TRUE(stats_proxy_->GetStats().cpu_limited_resolution);
|
||||
EXPECT_TRUE(stats_proxy_->GetStats().bw_limited_resolution);
|
||||
EXPECT_EQ(2, stats_proxy_->GetStats().number_of_cpu_adapt_changes);
|
||||
@ -1566,8 +1674,7 @@ TEST_F(ViEEncoderTest,
|
||||
vie_encoder_->TriggerCpuNormalUsage();
|
||||
source.IncomingCapturedFrame(CreateFrame(6, kWidth, kHeight));
|
||||
sink_.WaitForEncodedFrame(6);
|
||||
EXPECT_GT(source.sink_wants().max_pixel_count, last_wants.max_pixel_count);
|
||||
last_wants = source.sink_wants();
|
||||
VerifyFpsMaxResolutionGt(source.sink_wants(), source.last_wants());
|
||||
EXPECT_TRUE(stats_proxy_->GetStats().cpu_limited_resolution);
|
||||
EXPECT_TRUE(stats_proxy_->GetStats().bw_limited_resolution);
|
||||
EXPECT_EQ(3, stats_proxy_->GetStats().number_of_cpu_adapt_changes);
|
||||
@ -1577,7 +1684,7 @@ TEST_F(ViEEncoderTest,
|
||||
vie_encoder_->TriggerCpuNormalUsage();
|
||||
source.IncomingCapturedFrame(CreateFrame(7, kWidth, kHeight));
|
||||
sink_.WaitForEncodedFrame(7);
|
||||
EXPECT_GT(source.sink_wants().max_pixel_count, last_wants.max_pixel_count);
|
||||
VerifyFpsMaxResolutionGt(source.sink_wants(), source.last_wants());
|
||||
last_wants = source.sink_wants();
|
||||
EXPECT_FALSE(stats_proxy_->GetStats().cpu_limited_resolution);
|
||||
EXPECT_TRUE(stats_proxy_->GetStats().bw_limited_resolution);
|
||||
@ -1588,7 +1695,7 @@ TEST_F(ViEEncoderTest,
|
||||
vie_encoder_->TriggerCpuNormalUsage();
|
||||
source.IncomingCapturedFrame(CreateFrame(8, kWidth, kHeight));
|
||||
sink_.WaitForEncodedFrame(8);
|
||||
EXPECT_EQ(last_wants.max_pixel_count, source.sink_wants().max_pixel_count);
|
||||
VerifyFpsEqResolutionEq(source.sink_wants(), last_wants);
|
||||
EXPECT_FALSE(stats_proxy_->GetStats().cpu_limited_resolution);
|
||||
EXPECT_TRUE(stats_proxy_->GetStats().bw_limited_resolution);
|
||||
EXPECT_EQ(4, stats_proxy_->GetStats().number_of_cpu_adapt_changes);
|
||||
@ -1598,7 +1705,7 @@ TEST_F(ViEEncoderTest,
|
||||
vie_encoder_->TriggerQualityHigh();
|
||||
source.IncomingCapturedFrame(CreateFrame(9, kWidth, kHeight));
|
||||
sink_.WaitForEncodedFrame(kWidth, kHeight);
|
||||
EXPECT_GT(source.sink_wants().max_pixel_count, last_wants.max_pixel_count);
|
||||
VerifyFpsMaxResolutionGt(source.sink_wants(), source.last_wants());
|
||||
VerifyNoLimitation(source.sink_wants());
|
||||
EXPECT_FALSE(stats_proxy_->GetStats().cpu_limited_resolution);
|
||||
EXPECT_FALSE(stats_proxy_->GetStats().bw_limited_resolution);
|
||||
@ -1730,7 +1837,7 @@ TEST_F(ViEEncoderTest, DropsFramesAndScalesWhenBitrateIsTooLow) {
|
||||
vie_encoder_->Stop();
|
||||
}
|
||||
|
||||
TEST_F(ViEEncoderTest, NrOfDroppedFramesLimitedWhenBitrateIsTooLow) {
|
||||
TEST_F(ViEEncoderTest, NumberOfDroppedFramesLimitedWhenBitrateIsTooLow) {
|
||||
const int kTooLowBitrateForFrameSizeBps = 10000;
|
||||
vie_encoder_->OnBitrateUpdated(kTooLowBitrateForFrameSizeBps, 0, 0);
|
||||
const int kWidth = 640;
|
||||
@ -1774,6 +1881,7 @@ TEST_F(ViEEncoderTest, InitialFrameDropOffWhenEncoderDisabledScaling) {
|
||||
const int kHeight = 360;
|
||||
fake_encoder_.SetQualityScaling(false);
|
||||
vie_encoder_->OnBitrateUpdated(kLowTargetBitrateBps, 0, 0);
|
||||
|
||||
// Force quality scaler reconfiguration by resetting the source.
|
||||
vie_encoder_->SetSource(&video_source_,
|
||||
VideoSendStream::DegradationPreference::kBalanced);
|
||||
|
||||
@ -69,6 +69,8 @@ class VideoSendStream {
|
||||
bool suspended = false;
|
||||
bool bw_limited_resolution = false;
|
||||
bool cpu_limited_resolution = false;
|
||||
bool bw_limited_framerate = false;
|
||||
bool cpu_limited_framerate = false;
|
||||
// Total number of times resolution as been requested to be changed due to
|
||||
// CPU/quality adaptation.
|
||||
int number_of_cpu_adapt_changes = 0;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user