Index: webrtc/video/vie_encoder_unittest.cc |
diff --git a/webrtc/video/vie_encoder_unittest.cc b/webrtc/video/vie_encoder_unittest.cc |
index eb39bf7c4d909b40861500c0174e7f7740ece200..778cd82e7d3de895b8ae47f9d8807120a7129c01 100644 |
--- a/webrtc/video/vie_encoder_unittest.cc |
+++ b/webrtc/video/vie_encoder_unittest.cc |
@@ -34,6 +34,9 @@ namespace { |
const int kMinPixelsPerFrame = 320 * 180; |
const int kMinFramerateFps = 2; |
const int64_t kFrameTimeoutMs = 100; |
+const int kBpsLimitFor15Fps = 500000; |
+const int kBpsLimitFor10Fps = 130000; |
+const int kBpsLimitFor7Fps = 60000; |
} // namespace |
namespace webrtc { |
@@ -311,6 +314,37 @@ class ViEEncoderTest : public ::testing::Test { |
EXPECT_GT(wants1.max_pixel_count, wants2.max_pixel_count); |
} |
+ void VerifyFpsMaxResolutionEq(const rtc::VideoSinkWants& wants1, |
+ const rtc::VideoSinkWants& wants2) { |
+ EXPECT_EQ(std::numeric_limits<int>::max(), wants1.max_framerate_fps); |
+ EXPECT_EQ(wants1.max_pixel_count, wants2.max_pixel_count); |
+ } |
+ |
+ void VerifyFpsLtResolutionEq(const rtc::VideoSinkWants& wants1, |
+ const rtc::VideoSinkWants& wants2) { |
+ EXPECT_LT(wants1.max_framerate_fps, wants2.max_framerate_fps); |
+ EXPECT_EQ(wants1.max_pixel_count, wants2.max_pixel_count); |
+ } |
+ |
+ void VerifyFpsGtResolutionEq(const rtc::VideoSinkWants& wants1, |
+ const rtc::VideoSinkWants& wants2) { |
+ EXPECT_GT(wants1.max_framerate_fps, wants2.max_framerate_fps); |
+ EXPECT_EQ(wants1.max_pixel_count, wants2.max_pixel_count); |
+ } |
+ |
+ void VerifyFpsEqResolutionLt(const rtc::VideoSinkWants& wants1, |
+ const rtc::VideoSinkWants& wants2) { |
+ EXPECT_EQ(wants1.max_framerate_fps, wants2.max_framerate_fps); |
+ EXPECT_LT(wants1.max_pixel_count, wants2.max_pixel_count); |
+ EXPECT_GT(wants1.max_pixel_count, 0); |
+ } |
+ |
+ void VerifyFpsEqResolutionGt(const rtc::VideoSinkWants& wants1, |
+ const rtc::VideoSinkWants& wants2) { |
+ EXPECT_EQ(wants1.max_framerate_fps, wants2.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); |
@@ -324,6 +358,13 @@ class ViEEncoderTest : public ::testing::Test { |
EXPECT_FALSE(wants.target_pixel_count); |
} |
+ void VerifyFpsEqResolutionMax(const rtc::VideoSinkWants& wants, |
+ int expected_fps) { |
+ EXPECT_EQ(expected_fps, wants.max_framerate_fps); |
+ EXPECT_EQ(std::numeric_limits<int>::max(), wants.max_pixel_count); |
+ EXPECT_FALSE(wants.target_pixel_count); |
+ } |
+ |
class TestEncoder : public test::FakeEncoder { |
public: |
TestEncoder() |
@@ -808,6 +849,59 @@ TEST_F(ViEEncoderTest, SinkWantsFromOveruseDetector) { |
vie_encoder_->Stop(); |
} |
+TEST_F(ViEEncoderTest, TestMaxCpuResolutionDowngrades_BalancedMode_NoFpsLimit) { |
+ const int kMaxDowngrades = ViEEncoder::kMaxCpuResolutionDowngrades; |
+ const int kWidth = 1280; |
+ const int kHeight = 720; |
+ vie_encoder_->OnBitrateUpdated(kBpsLimitFor15Fps + 1, 0, 0); |
+ |
+ // Enable kBalanced preference, no initial limitation. |
+ AdaptingFrameForwarder source; |
+ source.set_adaptation_enabled(true); |
+ vie_encoder_->SetSource(&source, |
+ VideoSendStream::DegradationPreference::kBalanced); |
+ VerifyNoLimitation(source.sink_wants()); |
+ EXPECT_FALSE(stats_proxy_->GetStats().cpu_limited_resolution); |
+ EXPECT_EQ(0, stats_proxy_->GetStats().number_of_cpu_adapt_changes); |
+ |
+ // Trigger adapt down kMaxCpuDowngrades times. |
+ int t = 1; |
+ for (int i = 1; i <= kMaxDowngrades; ++i) { |
+ source.IncomingCapturedFrame(CreateFrame(t, kWidth, kHeight)); |
+ sink_.WaitForEncodedFrame(t++); |
+ vie_encoder_->TriggerCpuOveruse(); |
+ VerifyFpsMaxResolutionLt(source.sink_wants(), source.last_wants()); |
+ EXPECT_TRUE(stats_proxy_->GetStats().cpu_limited_resolution); |
+ EXPECT_EQ(i, stats_proxy_->GetStats().number_of_cpu_adapt_changes); |
+ } |
+ |
+ // Trigger adapt down, max cpu downgrades reach, expect no change. |
+ rtc::VideoSinkWants last_wants = source.sink_wants(); |
+ source.IncomingCapturedFrame(CreateFrame(t, kWidth, kHeight)); |
+ sink_.WaitForEncodedFrame(t++); |
+ vie_encoder_->TriggerCpuOveruse(); |
+ VerifyFpsEqResolutionEq(source.sink_wants(), last_wants); |
+ EXPECT_EQ(last_wants.max_pixel_count, source.sink_wants().max_pixel_count); |
+ EXPECT_TRUE(stats_proxy_->GetStats().cpu_limited_resolution); |
+ EXPECT_EQ(kMaxDowngrades, |
+ stats_proxy_->GetStats().number_of_cpu_adapt_changes); |
+ |
+ // Trigger adapt up kMaxCpuDowngrades times. |
+ for (int i = 1; i <= kMaxDowngrades; ++i) { |
+ source.IncomingCapturedFrame(CreateFrame(t, kWidth, kHeight)); |
+ sink_.WaitForEncodedFrame(t++); |
+ vie_encoder_->TriggerCpuNormalUsage(); |
+ VerifyFpsMaxResolutionGt(source.sink_wants(), source.last_wants()); |
+ EXPECT_GT(source.sink_wants().max_pixel_count, last_wants.max_pixel_count); |
+ EXPECT_EQ(kMaxDowngrades + i, |
+ stats_proxy_->GetStats().number_of_cpu_adapt_changes); |
+ } |
+ |
+ VerifyNoLimitation(source.sink_wants()); |
+ EXPECT_FALSE(stats_proxy_->GetStats().cpu_limited_resolution); |
+ |
+ vie_encoder_->Stop(); |
+} |
TEST_F(ViEEncoderTest, SinkWantsStoredByDegradationPreference) { |
vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0); |
VerifyNoLimitation(video_source_.sink_wants()); |
@@ -1048,8 +1142,8 @@ TEST_F(ViEEncoderTest, SwitchingSourceKeepsQualityAdaptation) { |
video_source_.IncomingCapturedFrame(CreateFrame(1, kWidth, kHeight)); |
sink_.WaitForEncodedFrame(1); |
VideoSendStream::Stats stats = stats_proxy_->GetStats(); |
- EXPECT_FALSE(stats.cpu_limited_resolution); |
EXPECT_FALSE(stats.bw_limited_resolution); |
+ EXPECT_FALSE(stats.bw_limited_framerate); |
EXPECT_EQ(0, stats.number_of_quality_adapt_changes); |
// Set new source with adaptation still enabled. |
@@ -1060,8 +1154,8 @@ TEST_F(ViEEncoderTest, SwitchingSourceKeepsQualityAdaptation) { |
new_video_source.IncomingCapturedFrame(CreateFrame(2, kWidth, kHeight)); |
sink_.WaitForEncodedFrame(2); |
stats = stats_proxy_->GetStats(); |
- EXPECT_FALSE(stats.cpu_limited_resolution); |
EXPECT_FALSE(stats.bw_limited_resolution); |
+ EXPECT_FALSE(stats.bw_limited_framerate); |
EXPECT_EQ(0, stats.number_of_quality_adapt_changes); |
// Trigger adapt down. |
@@ -1069,8 +1163,8 @@ TEST_F(ViEEncoderTest, SwitchingSourceKeepsQualityAdaptation) { |
new_video_source.IncomingCapturedFrame(CreateFrame(3, kWidth, kHeight)); |
sink_.WaitForEncodedFrame(3); |
stats = stats_proxy_->GetStats(); |
- EXPECT_FALSE(stats.cpu_limited_resolution); |
EXPECT_TRUE(stats.bw_limited_resolution); |
+ EXPECT_FALSE(stats.bw_limited_framerate); |
EXPECT_EQ(1, stats.number_of_quality_adapt_changes); |
// Set new source with adaptation still enabled. |
@@ -1080,8 +1174,8 @@ TEST_F(ViEEncoderTest, SwitchingSourceKeepsQualityAdaptation) { |
new_video_source.IncomingCapturedFrame(CreateFrame(4, kWidth, kHeight)); |
sink_.WaitForEncodedFrame(4); |
stats = stats_proxy_->GetStats(); |
- EXPECT_FALSE(stats.cpu_limited_resolution); |
EXPECT_TRUE(stats.bw_limited_resolution); |
+ EXPECT_FALSE(stats.bw_limited_framerate); |
EXPECT_EQ(1, stats.number_of_quality_adapt_changes); |
// Disable resolution scaling. |
@@ -1092,8 +1186,8 @@ TEST_F(ViEEncoderTest, SwitchingSourceKeepsQualityAdaptation) { |
new_video_source.IncomingCapturedFrame(CreateFrame(5, kWidth, kHeight)); |
sink_.WaitForEncodedFrame(5); |
stats = stats_proxy_->GetStats(); |
- EXPECT_FALSE(stats.cpu_limited_resolution); |
EXPECT_FALSE(stats.bw_limited_resolution); |
+ EXPECT_FALSE(stats.bw_limited_framerate); |
EXPECT_EQ(1, stats.number_of_quality_adapt_changes); |
EXPECT_EQ(0, stats.number_of_cpu_adapt_changes); |
@@ -1154,6 +1248,7 @@ TEST_F(ViEEncoderTest, StatsTracksCpuAdaptationStatsWhenSwitchingSource) { |
sink_.WaitForEncodedFrame(sequence++); |
VideoSendStream::Stats stats = stats_proxy_->GetStats(); |
EXPECT_FALSE(stats.cpu_limited_resolution); |
+ EXPECT_FALSE(stats.cpu_limited_framerate); |
EXPECT_EQ(0, stats.number_of_cpu_adapt_changes); |
// Trigger CPU overuse, should now adapt down. |
@@ -1162,6 +1257,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 new source with adaptation still enabled. |
@@ -1219,6 +1315,7 @@ TEST_F(ViEEncoderTest, StatsTracksCpuAdaptationStatsWhenSwitchingSource) { |
stats = stats_proxy_->GetStats(); |
EXPECT_FALSE(stats.cpu_limited_resolution); |
+ EXPECT_FALSE(stats.cpu_limited_framerate); |
EXPECT_EQ(2, stats.number_of_cpu_adapt_changes); |
// Try to trigger overuse. Should not succeed. |
@@ -1228,6 +1325,7 @@ TEST_F(ViEEncoderTest, StatsTracksCpuAdaptationStatsWhenSwitchingSource) { |
stats = stats_proxy_->GetStats(); |
EXPECT_FALSE(stats.cpu_limited_resolution); |
+ EXPECT_FALSE(stats.cpu_limited_framerate); |
EXPECT_EQ(2, stats.number_of_cpu_adapt_changes); |
// Switch back the source with resolution adaptation enabled. |
@@ -1238,6 +1336,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(2, stats.number_of_cpu_adapt_changes); |
// Trigger CPU normal usage. |
@@ -1246,6 +1345,7 @@ TEST_F(ViEEncoderTest, StatsTracksCpuAdaptationStatsWhenSwitchingSource) { |
sink_.WaitForEncodedFrame(sequence++); |
stats = stats_proxy_->GetStats(); |
EXPECT_FALSE(stats.cpu_limited_resolution); |
+ EXPECT_FALSE(stats.cpu_limited_framerate); |
EXPECT_EQ(3, stats.number_of_cpu_adapt_changes); |
// Back to the source with adaptation off, set it back to maintain-resolution. |
@@ -1256,8 +1356,9 @@ TEST_F(ViEEncoderTest, StatsTracksCpuAdaptationStatsWhenSwitchingSource) { |
CreateFrame(sequence, kWidth, kHeight)); |
sink_.WaitForEncodedFrame(sequence++); |
stats = stats_proxy_->GetStats(); |
- // Disabled, since we previously switched the source too disabled. |
+ // Disabled, since we previously switched the source to disabled. |
EXPECT_FALSE(stats.cpu_limited_resolution); |
+ EXPECT_TRUE(stats.cpu_limited_framerate); |
EXPECT_EQ(3, stats.number_of_cpu_adapt_changes); |
// Trigger CPU normal usage. |
@@ -1267,6 +1368,7 @@ TEST_F(ViEEncoderTest, StatsTracksCpuAdaptationStatsWhenSwitchingSource) { |
sink_.WaitForEncodedFrame(sequence++); |
stats = stats_proxy_->GetStats(); |
EXPECT_FALSE(stats.cpu_limited_resolution); |
+ EXPECT_FALSE(stats.cpu_limited_framerate); |
EXPECT_EQ(4, stats.number_of_cpu_adapt_changes); |
EXPECT_EQ(0, stats.number_of_quality_adapt_changes); |
@@ -1368,6 +1470,45 @@ TEST_F(ViEEncoderTest, SkipsSameAdaptDownRequest_MaintainFramerateMode) { |
vie_encoder_->Stop(); |
} |
+TEST_F(ViEEncoderTest, SkipsSameOrLargerAdaptDownRequest_BalancedMode) { |
+ const int kWidth = 1280; |
+ const int kHeight = 720; |
+ vie_encoder_->OnBitrateUpdated(kBpsLimitFor15Fps + 1, 0, 0); |
+ |
+ // Enable kBalanced preference, no initial limitation. |
+ test::FrameForwarder source; |
+ vie_encoder_->SetSource(&source, |
+ VideoSendStream::DegradationPreference::kBalanced); |
+ source.IncomingCapturedFrame(CreateFrame(1, kWidth, kHeight)); |
+ sink_.WaitForEncodedFrame(1); |
+ VerifyNoLimitation(source.sink_wants()); |
+ |
+ // Trigger adapt down, expect scaled down resolution. |
+ vie_encoder_->TriggerQualityLow(); |
+ 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); |
+ const int kLastMaxPixelCount = source.sink_wants().max_pixel_count; |
+ |
+ // Trigger adapt down for same input resolution, expect no change. |
+ source.IncomingCapturedFrame(CreateFrame(2, kWidth, kHeight)); |
+ sink_.WaitForEncodedFrame(2); |
+ vie_encoder_->TriggerQualityLow(); |
+ EXPECT_EQ(kLastMaxPixelCount, source.sink_wants().max_pixel_count); |
+ EXPECT_TRUE(stats_proxy_->GetStats().bw_limited_resolution); |
+ EXPECT_EQ(1, stats_proxy_->GetStats().number_of_quality_adapt_changes); |
+ |
+ // Trigger adapt down for larger input resolution, expect no change. |
+ source.IncomingCapturedFrame(CreateFrame(3, kWidth + 1, kHeight + 1)); |
+ sink_.WaitForEncodedFrame(3); |
+ vie_encoder_->TriggerQualityLow(); |
+ EXPECT_EQ(kLastMaxPixelCount, source.sink_wants().max_pixel_count); |
+ EXPECT_TRUE(stats_proxy_->GetStats().bw_limited_resolution); |
+ EXPECT_EQ(1, stats_proxy_->GetStats().number_of_quality_adapt_changes); |
+ |
+ vie_encoder_->Stop(); |
+} |
+ |
TEST_F(ViEEncoderTest, NoChangeForInitialNormalUsage_MaintainFramerateMode) { |
const int kWidth = 1280; |
const int kHeight = 720; |
@@ -1418,6 +1559,33 @@ TEST_F(ViEEncoderTest, NoChangeForInitialNormalUsage_MaintainResolutionMode) { |
vie_encoder_->Stop(); |
} |
+TEST_F(ViEEncoderTest, NoChangeForInitialNormalUsage_BalancedMode) { |
+ const int kWidth = 1280; |
+ const int kHeight = 720; |
+ vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0); |
+ |
+ // Enable kBalanced preference, no initial limitation. |
+ test::FrameForwarder source; |
+ vie_encoder_->SetSource(&source, |
+ VideoSendStream::DegradationPreference::kBalanced); |
+ |
+ 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, NoChangeForInitialNormalUsage_DisabledMode) { |
const int kWidth = 1280; |
const int kHeight = 720; |
@@ -1610,6 +1778,59 @@ TEST_F(ViEEncoderTest, |
} |
TEST_F(ViEEncoderTest, |
+ AdaptsResolutionUpAndDownTwiceForLowQuality_BalancedMode_NoFpsLimit) { |
+ const int kWidth = 1280; |
+ const int kHeight = 720; |
+ vie_encoder_->OnBitrateUpdated(kBpsLimitFor15Fps + 1, 0, 0); |
+ |
+ // Enable kBalanced preference, no initial limitation. |
+ AdaptingFrameForwarder source; |
+ source.set_adaptation_enabled(true); |
+ vie_encoder_->SetSource(&source, |
+ VideoSendStream::DegradationPreference::kBalanced); |
+ |
+ source.IncomingCapturedFrame(CreateFrame(1, kWidth, kHeight)); |
+ sink_.WaitForEncodedFrame(kWidth, kHeight); |
+ VerifyNoLimitation(source.sink_wants()); |
+ EXPECT_FALSE(stats_proxy_->GetStats().bw_limited_resolution); |
+ EXPECT_EQ(0, stats_proxy_->GetStats().number_of_quality_adapt_changes); |
+ |
+ // Trigger adapt down, expect scaled down resolution. |
+ vie_encoder_->TriggerQualityLow(); |
+ source.IncomingCapturedFrame(CreateFrame(2, kWidth, kHeight)); |
+ sink_.WaitForEncodedFrame(2); |
+ 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); |
+ |
+ // Trigger adapt up, expect no restriction. |
+ vie_encoder_->TriggerQualityHigh(); |
+ source.IncomingCapturedFrame(CreateFrame(3, kWidth, kHeight)); |
+ sink_.WaitForEncodedFrame(kWidth, kHeight); |
+ VerifyNoLimitation(source.sink_wants()); |
+ EXPECT_FALSE(stats_proxy_->GetStats().bw_limited_resolution); |
+ EXPECT_EQ(2, stats_proxy_->GetStats().number_of_quality_adapt_changes); |
+ |
+ // Trigger adapt down, expect scaled down resolution. |
+ vie_encoder_->TriggerQualityLow(); |
+ source.IncomingCapturedFrame(CreateFrame(4, kWidth, kHeight)); |
+ sink_.WaitForEncodedFrame(4); |
+ VerifyFpsMaxResolutionLt(source.sink_wants(), kWidth * kHeight); |
+ EXPECT_TRUE(stats_proxy_->GetStats().bw_limited_resolution); |
+ EXPECT_EQ(3, stats_proxy_->GetStats().number_of_quality_adapt_changes); |
+ |
+ // Trigger adapt up, expect no restriction. |
+ vie_encoder_->TriggerQualityHigh(); |
+ source.IncomingCapturedFrame(CreateFrame(5, kWidth, kHeight)); |
+ sink_.WaitForEncodedFrame(kWidth, kHeight); |
+ VerifyNoLimitation(source.sink_wants()); |
+ EXPECT_FALSE(stats_proxy_->GetStats().bw_limited_resolution); |
+ EXPECT_EQ(4, stats_proxy_->GetStats().number_of_quality_adapt_changes); |
+ |
+ vie_encoder_->Stop(); |
+} |
+ |
+TEST_F(ViEEncoderTest, |
AdaptsResolutionOnOveruseAndLowQuality_MaintainFramerateMode) { |
const int kWidth = 1280; |
const int kHeight = 720; |
@@ -1918,6 +2139,41 @@ TEST_F(ViEEncoderTest, |
vie_encoder_->Stop(); |
} |
+TEST_F(ViEEncoderTest, ResolutionNotAdaptedForTooSmallFrame_BalancedMode) { |
+ const int kTooSmallWidth = 10; |
+ const int kTooSmallHeight = 10; |
+ const int kFpsLimit = 7; |
+ vie_encoder_->OnBitrateUpdated(kBpsLimitFor7Fps, 0, 0); |
+ |
+ // Enable kBalanced preference, no initial limitation. |
+ test::FrameForwarder source; |
+ vie_encoder_->SetSource(&source, |
+ VideoSendStream::DegradationPreference::kBalanced); |
+ VerifyNoLimitation(source.sink_wants()); |
+ EXPECT_FALSE(stats_proxy_->GetStats().bw_limited_resolution); |
+ EXPECT_FALSE(stats_proxy_->GetStats().bw_limited_framerate); |
+ |
+ // Trigger adapt down, expect limited framerate. |
+ source.IncomingCapturedFrame(CreateFrame(1, kTooSmallWidth, kTooSmallHeight)); |
+ sink_.WaitForEncodedFrame(1); |
+ vie_encoder_->TriggerQualityLow(); |
+ VerifyFpsEqResolutionMax(source.sink_wants(), kFpsLimit); |
+ EXPECT_FALSE(stats_proxy_->GetStats().bw_limited_resolution); |
+ EXPECT_TRUE(stats_proxy_->GetStats().bw_limited_framerate); |
+ EXPECT_EQ(1, stats_proxy_->GetStats().number_of_quality_adapt_changes); |
+ |
+ // Trigger adapt down, too small frame, expect no change. |
+ source.IncomingCapturedFrame(CreateFrame(2, kTooSmallWidth, kTooSmallHeight)); |
+ sink_.WaitForEncodedFrame(2); |
+ vie_encoder_->TriggerQualityLow(); |
+ VerifyFpsEqResolutionMax(source.sink_wants(), kFpsLimit); |
+ EXPECT_FALSE(stats_proxy_->GetStats().bw_limited_resolution); |
+ EXPECT_TRUE(stats_proxy_->GetStats().bw_limited_framerate); |
+ EXPECT_EQ(1, stats_proxy_->GetStats().number_of_quality_adapt_changes); |
+ |
+ vie_encoder_->Stop(); |
+} |
+ |
TEST_F(ViEEncoderTest, FailingInitEncodeDoesntCauseCrash) { |
fake_encoder_.ForceInitEncodeFailure(true); |
vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0); |
@@ -2112,4 +2368,363 @@ TEST_F(ViEEncoderTest, DoesntAdaptDownPastMinFramerate) { |
} |
vie_encoder_->Stop(); |
} |
+ |
+TEST_F(ViEEncoderTest, AdaptsResolutionAndFramerateForLowQuality_BalancedMode) { |
+ const int kWidth = 1280; |
+ const int kHeight = 720; |
+ const int64_t kFrameIntervalMs = 150; |
+ int64_t timestamp_ms = kFrameIntervalMs; |
+ vie_encoder_->OnBitrateUpdated(kBpsLimitFor15Fps, 0, 0); |
+ |
+ // Enable kBalanced preference, no initial limitation. |
+ AdaptingFrameForwarder source; |
+ source.set_adaptation_enabled(true); |
+ vie_encoder_->SetSource(&source, |
+ VideoSendStream::DegradationPreference::kBalanced); |
+ timestamp_ms += kFrameIntervalMs; |
+ source.IncomingCapturedFrame(CreateFrame(timestamp_ms, kWidth, kHeight)); |
+ sink_.WaitForEncodedFrame(kWidth, kHeight); |
+ VerifyNoLimitation(source.sink_wants()); |
+ EXPECT_FALSE(stats_proxy_->GetStats().bw_limited_resolution); |
+ EXPECT_FALSE(stats_proxy_->GetStats().bw_limited_framerate); |
+ EXPECT_EQ(0, stats_proxy_->GetStats().number_of_quality_adapt_changes); |
+ |
+ // Trigger adapt down, expect scaled down resolution (960x540@30fps). |
+ vie_encoder_->TriggerQualityLow(); |
+ timestamp_ms += kFrameIntervalMs; |
+ source.IncomingCapturedFrame(CreateFrame(timestamp_ms, kWidth, kHeight)); |
+ sink_.WaitForEncodedFrame(timestamp_ms); |
+ VerifyFpsMaxResolutionLt(source.sink_wants(), kWidth * kHeight); |
+ EXPECT_TRUE(stats_proxy_->GetStats().bw_limited_resolution); |
+ EXPECT_FALSE(stats_proxy_->GetStats().bw_limited_framerate); |
+ EXPECT_EQ(1, stats_proxy_->GetStats().number_of_quality_adapt_changes); |
+ |
+ // Trigger adapt down, expect scaled down resolution (640x360@30fps). |
+ vie_encoder_->TriggerQualityLow(); |
+ timestamp_ms += kFrameIntervalMs; |
+ source.IncomingCapturedFrame(CreateFrame(timestamp_ms, kWidth, kHeight)); |
+ sink_.WaitForEncodedFrame(timestamp_ms); |
+ VerifyFpsMaxResolutionLt(source.sink_wants(), source.last_wants()); |
+ EXPECT_TRUE(stats_proxy_->GetStats().bw_limited_resolution); |
+ EXPECT_FALSE(stats_proxy_->GetStats().bw_limited_framerate); |
+ EXPECT_EQ(2, stats_proxy_->GetStats().number_of_quality_adapt_changes); |
+ |
+ // Trigger adapt down, expect reduced fps (640x360@15fps). |
+ vie_encoder_->TriggerQualityLow(); |
+ timestamp_ms += kFrameIntervalMs; |
+ source.IncomingCapturedFrame(CreateFrame(timestamp_ms, kWidth, kHeight)); |
+ sink_.WaitForEncodedFrame(timestamp_ms); |
+ VerifyFpsLtResolutionEq(source.sink_wants(), source.last_wants()); |
+ EXPECT_TRUE(stats_proxy_->GetStats().bw_limited_resolution); |
+ EXPECT_TRUE(stats_proxy_->GetStats().bw_limited_framerate); |
+ EXPECT_EQ(3, stats_proxy_->GetStats().number_of_quality_adapt_changes); |
+ |
+ // Trigger adapt down, expect scaled down resolution (480x270@15fps). |
+ vie_encoder_->OnBitrateUpdated(kBpsLimitFor10Fps, 0, 0); |
+ vie_encoder_->TriggerQualityLow(); |
+ timestamp_ms += kFrameIntervalMs; |
+ source.IncomingCapturedFrame(CreateFrame(timestamp_ms, kWidth, kHeight)); |
+ sink_.WaitForEncodedFrame(timestamp_ms); |
+ VerifyFpsEqResolutionLt(source.sink_wants(), source.last_wants()); |
+ EXPECT_TRUE(stats_proxy_->GetStats().bw_limited_resolution); |
+ EXPECT_TRUE(stats_proxy_->GetStats().bw_limited_framerate); |
+ EXPECT_EQ(4, stats_proxy_->GetStats().number_of_quality_adapt_changes); |
+ |
+ // Restrict bitrate, trigger adapt down, expect reduced fps (480x270@10fps). |
+ vie_encoder_->TriggerQualityLow(); |
+ timestamp_ms += kFrameIntervalMs; |
+ source.IncomingCapturedFrame(CreateFrame(timestamp_ms, kWidth, kHeight)); |
+ sink_.WaitForEncodedFrame(timestamp_ms); |
+ VerifyFpsLtResolutionEq(source.sink_wants(), source.last_wants()); |
+ EXPECT_TRUE(stats_proxy_->GetStats().bw_limited_resolution); |
+ EXPECT_TRUE(stats_proxy_->GetStats().bw_limited_framerate); |
+ EXPECT_EQ(5, stats_proxy_->GetStats().number_of_quality_adapt_changes); |
+ |
+ // Trigger adapt down, expect scaled down resolution (320x180@10fps). |
+ vie_encoder_->TriggerQualityLow(); |
+ timestamp_ms += kFrameIntervalMs; |
+ source.IncomingCapturedFrame(CreateFrame(timestamp_ms, kWidth, kHeight)); |
+ sink_.WaitForEncodedFrame(timestamp_ms); |
+ VerifyFpsEqResolutionLt(source.sink_wants(), source.last_wants()); |
+ rtc::VideoSinkWants last_wants = source.sink_wants(); |
+ EXPECT_TRUE(stats_proxy_->GetStats().bw_limited_resolution); |
+ EXPECT_TRUE(stats_proxy_->GetStats().bw_limited_framerate); |
+ EXPECT_EQ(6, stats_proxy_->GetStats().number_of_quality_adapt_changes); |
+ |
+ // Trigger adapt down, min resolution reached, expect no change. |
+ vie_encoder_->TriggerQualityLow(); |
+ timestamp_ms += kFrameIntervalMs; |
+ source.IncomingCapturedFrame(CreateFrame(timestamp_ms, kWidth, kHeight)); |
+ sink_.WaitForEncodedFrame(timestamp_ms); |
+ VerifyFpsEqResolutionEq(source.sink_wants(), last_wants); |
+ EXPECT_TRUE(stats_proxy_->GetStats().bw_limited_resolution); |
+ EXPECT_TRUE(stats_proxy_->GetStats().bw_limited_framerate); |
+ EXPECT_EQ(6, stats_proxy_->GetStats().number_of_quality_adapt_changes); |
+ |
+ // Trigger adapt up, expect upscaled resolution (480x270@10fps). |
+ vie_encoder_->TriggerQualityHigh(); |
+ timestamp_ms += kFrameIntervalMs; |
+ source.IncomingCapturedFrame(CreateFrame(timestamp_ms, kWidth, kHeight)); |
+ sink_.WaitForEncodedFrame(timestamp_ms); |
+ VerifyFpsEqResolutionGt(source.sink_wants(), source.last_wants()); |
+ EXPECT_TRUE(stats_proxy_->GetStats().bw_limited_resolution); |
+ EXPECT_TRUE(stats_proxy_->GetStats().bw_limited_framerate); |
+ EXPECT_EQ(7, stats_proxy_->GetStats().number_of_quality_adapt_changes); |
+ |
+ // Increase bitrate, trigger adapt up, expect increased fps (480x270@15fps). |
+ vie_encoder_->OnBitrateUpdated(kBpsLimitFor15Fps + 1, 0, 0); |
+ vie_encoder_->TriggerQualityHigh(); |
+ timestamp_ms += kFrameIntervalMs; |
+ source.IncomingCapturedFrame(CreateFrame(timestamp_ms, kWidth, kHeight)); |
+ sink_.WaitForEncodedFrame(timestamp_ms); |
+ VerifyFpsGtResolutionEq(source.sink_wants(), source.last_wants()); |
+ EXPECT_TRUE(stats_proxy_->GetStats().bw_limited_resolution); |
+ EXPECT_TRUE(stats_proxy_->GetStats().bw_limited_framerate); |
+ EXPECT_EQ(8, stats_proxy_->GetStats().number_of_quality_adapt_changes); |
+ |
+ // Trigger adapt up, expect upscaled resolution (640x360@15fps). |
+ vie_encoder_->TriggerQualityHigh(); |
+ timestamp_ms += kFrameIntervalMs; |
+ source.IncomingCapturedFrame(CreateFrame(timestamp_ms, kWidth, kHeight)); |
+ sink_.WaitForEncodedFrame(timestamp_ms); |
+ VerifyFpsEqResolutionGt(source.sink_wants(), source.last_wants()); |
+ EXPECT_TRUE(stats_proxy_->GetStats().bw_limited_resolution); |
+ EXPECT_TRUE(stats_proxy_->GetStats().bw_limited_framerate); |
+ EXPECT_EQ(9, stats_proxy_->GetStats().number_of_quality_adapt_changes); |
+ |
+ // Trigger adapt up, expect increased fps (640x360@30fps). |
+ vie_encoder_->TriggerQualityHigh(); |
+ timestamp_ms += kFrameIntervalMs; |
+ source.IncomingCapturedFrame(CreateFrame(timestamp_ms, kWidth, kHeight)); |
+ sink_.WaitForEncodedFrame(timestamp_ms); |
+ VerifyFpsMaxResolutionEq(source.sink_wants(), source.last_wants()); |
+ EXPECT_TRUE(stats_proxy_->GetStats().bw_limited_resolution); |
+ EXPECT_FALSE(stats_proxy_->GetStats().bw_limited_framerate); |
+ EXPECT_EQ(10, stats_proxy_->GetStats().number_of_quality_adapt_changes); |
+ |
+ // Trigger adapt up, expect upscaled resolution (960x540@30fps). |
+ vie_encoder_->TriggerQualityHigh(); |
+ timestamp_ms += kFrameIntervalMs; |
+ source.IncomingCapturedFrame(CreateFrame(timestamp_ms, kWidth, kHeight)); |
+ sink_.WaitForEncodedFrame(timestamp_ms); |
+ VerifyFpsMaxResolutionGt(source.sink_wants(), source.last_wants()); |
+ EXPECT_TRUE(stats_proxy_->GetStats().bw_limited_resolution); |
+ EXPECT_FALSE(stats_proxy_->GetStats().bw_limited_framerate); |
+ EXPECT_EQ(11, stats_proxy_->GetStats().number_of_quality_adapt_changes); |
+ |
+ // Trigger adapt up, expect no restriction (1280x720fps@30fps). |
+ vie_encoder_->TriggerQualityHigh(); |
+ timestamp_ms += kFrameIntervalMs; |
+ source.IncomingCapturedFrame(CreateFrame(timestamp_ms, kWidth, kHeight)); |
+ sink_.WaitForEncodedFrame(kWidth, kHeight); |
+ VerifyFpsMaxResolutionGt(source.sink_wants(), source.last_wants()); |
+ VerifyNoLimitation(source.sink_wants()); |
+ EXPECT_FALSE(stats_proxy_->GetStats().bw_limited_resolution); |
+ EXPECT_FALSE(stats_proxy_->GetStats().bw_limited_framerate); |
+ EXPECT_EQ(12, stats_proxy_->GetStats().number_of_quality_adapt_changes); |
+ |
+ // Trigger adapt up, expect no change. |
+ vie_encoder_->TriggerQualityHigh(); |
+ VerifyNoLimitation(source.sink_wants()); |
+ EXPECT_EQ(12, stats_proxy_->GetStats().number_of_quality_adapt_changes); |
+ |
+ vie_encoder_->Stop(); |
+} |
+ |
+TEST_F(ViEEncoderTest, AdaptWithTwoReasonsAndDifferentOrder_Framerate) { |
+ const int kWidth = 1280; |
+ const int kHeight = 720; |
+ const int64_t kFrameIntervalMs = 150; |
+ int64_t timestamp_ms = kFrameIntervalMs; |
+ vie_encoder_->OnBitrateUpdated(kBpsLimitFor15Fps, 0, 0); |
+ |
+ // Enable kBalanced preference, no initial limitation. |
+ AdaptingFrameForwarder source; |
+ source.set_adaptation_enabled(true); |
+ vie_encoder_->SetSource(&source, |
+ VideoSendStream::DegradationPreference::kBalanced); |
+ timestamp_ms += kFrameIntervalMs; |
+ source.IncomingCapturedFrame(CreateFrame(timestamp_ms, kWidth, kHeight)); |
+ sink_.WaitForEncodedFrame(kWidth, kHeight); |
+ VerifyNoLimitation(source.sink_wants()); |
+ EXPECT_FALSE(stats_proxy_->GetStats().bw_limited_resolution); |
+ EXPECT_FALSE(stats_proxy_->GetStats().bw_limited_framerate); |
+ 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); |
+ EXPECT_EQ(0, stats_proxy_->GetStats().number_of_quality_adapt_changes); |
+ |
+ // Trigger cpu adapt down, expect scaled down resolution (960x540@30fps). |
+ vie_encoder_->TriggerCpuOveruse(); |
+ timestamp_ms += kFrameIntervalMs; |
+ source.IncomingCapturedFrame(CreateFrame(timestamp_ms, kWidth, kHeight)); |
+ sink_.WaitForEncodedFrame(timestamp_ms); |
+ VerifyFpsMaxResolutionLt(source.sink_wants(), kWidth * kHeight); |
+ EXPECT_FALSE(stats_proxy_->GetStats().bw_limited_resolution); |
+ EXPECT_FALSE(stats_proxy_->GetStats().bw_limited_framerate); |
+ EXPECT_TRUE(stats_proxy_->GetStats().cpu_limited_resolution); |
+ EXPECT_FALSE(stats_proxy_->GetStats().cpu_limited_framerate); |
+ EXPECT_EQ(1, stats_proxy_->GetStats().number_of_cpu_adapt_changes); |
+ EXPECT_EQ(0, stats_proxy_->GetStats().number_of_quality_adapt_changes); |
+ |
+ // Trigger cpu adapt down, expect scaled down resolution (640x360@30fps). |
+ vie_encoder_->TriggerCpuOveruse(); |
+ timestamp_ms += kFrameIntervalMs; |
+ source.IncomingCapturedFrame(CreateFrame(timestamp_ms, kWidth, kHeight)); |
+ sink_.WaitForEncodedFrame(timestamp_ms); |
+ VerifyFpsMaxResolutionLt(source.sink_wants(), source.last_wants()); |
+ EXPECT_FALSE(stats_proxy_->GetStats().bw_limited_resolution); |
+ EXPECT_FALSE(stats_proxy_->GetStats().bw_limited_framerate); |
+ EXPECT_TRUE(stats_proxy_->GetStats().cpu_limited_resolution); |
+ EXPECT_FALSE(stats_proxy_->GetStats().cpu_limited_framerate); |
+ EXPECT_EQ(2, stats_proxy_->GetStats().number_of_cpu_adapt_changes); |
+ EXPECT_EQ(0, stats_proxy_->GetStats().number_of_quality_adapt_changes); |
+ |
+ // Trigger quality adapt down, expect reduced fps (640x360@15fps). |
+ vie_encoder_->TriggerQualityLow(); |
+ timestamp_ms += kFrameIntervalMs; |
+ source.IncomingCapturedFrame(CreateFrame(timestamp_ms, kWidth, kHeight)); |
+ sink_.WaitForEncodedFrame(timestamp_ms); |
+ VerifyFpsLtResolutionEq(source.sink_wants(), source.last_wants()); |
+ EXPECT_FALSE(stats_proxy_->GetStats().bw_limited_resolution); |
+ EXPECT_TRUE(stats_proxy_->GetStats().bw_limited_framerate); |
+ EXPECT_TRUE(stats_proxy_->GetStats().cpu_limited_resolution); |
+ EXPECT_FALSE(stats_proxy_->GetStats().cpu_limited_framerate); |
+ EXPECT_EQ(2, stats_proxy_->GetStats().number_of_cpu_adapt_changes); |
+ EXPECT_EQ(1, stats_proxy_->GetStats().number_of_quality_adapt_changes); |
+ |
+ // Trigger cpu adapt up, expect increased fps (640x360@30fps). |
+ vie_encoder_->TriggerCpuNormalUsage(); |
+ timestamp_ms += kFrameIntervalMs; |
+ source.IncomingCapturedFrame(CreateFrame(timestamp_ms, kWidth, kHeight)); |
+ sink_.WaitForEncodedFrame(timestamp_ms); |
+ VerifyFpsMaxResolutionEq(source.sink_wants(), source.last_wants()); |
+ EXPECT_TRUE(stats_proxy_->GetStats().bw_limited_resolution); |
+ EXPECT_FALSE(stats_proxy_->GetStats().bw_limited_framerate); |
+ EXPECT_TRUE(stats_proxy_->GetStats().cpu_limited_resolution); |
+ EXPECT_FALSE(stats_proxy_->GetStats().cpu_limited_framerate); |
+ EXPECT_EQ(3, stats_proxy_->GetStats().number_of_cpu_adapt_changes); |
+ EXPECT_EQ(1, stats_proxy_->GetStats().number_of_quality_adapt_changes); |
+ |
+ // Trigger quality adapt up, expect upscaled resolution (960x540@30fps). |
+ vie_encoder_->TriggerQualityHigh(); |
+ timestamp_ms += kFrameIntervalMs; |
+ source.IncomingCapturedFrame(CreateFrame(timestamp_ms, kWidth, kHeight)); |
+ sink_.WaitForEncodedFrame(timestamp_ms); |
+ VerifyFpsMaxResolutionGt(source.sink_wants(), source.last_wants()); |
+ EXPECT_FALSE(stats_proxy_->GetStats().bw_limited_resolution); |
+ EXPECT_FALSE(stats_proxy_->GetStats().bw_limited_framerate); |
+ EXPECT_TRUE(stats_proxy_->GetStats().cpu_limited_resolution); |
+ EXPECT_FALSE(stats_proxy_->GetStats().cpu_limited_framerate); |
+ EXPECT_EQ(3, stats_proxy_->GetStats().number_of_cpu_adapt_changes); |
+ EXPECT_EQ(2, stats_proxy_->GetStats().number_of_quality_adapt_changes); |
+ |
+ // Trigger cpu adapt up, expect no restriction (1280x720fps@30fps). |
+ vie_encoder_->TriggerCpuNormalUsage(); |
+ timestamp_ms += kFrameIntervalMs; |
+ source.IncomingCapturedFrame(CreateFrame(timestamp_ms, kWidth, kHeight)); |
+ sink_.WaitForEncodedFrame(kWidth, kHeight); |
+ VerifyFpsMaxResolutionGt(source.sink_wants(), source.last_wants()); |
+ VerifyNoLimitation(source.sink_wants()); |
+ EXPECT_FALSE(stats_proxy_->GetStats().bw_limited_resolution); |
+ EXPECT_FALSE(stats_proxy_->GetStats().bw_limited_framerate); |
+ EXPECT_FALSE(stats_proxy_->GetStats().cpu_limited_resolution); |
+ EXPECT_FALSE(stats_proxy_->GetStats().cpu_limited_framerate); |
+ EXPECT_EQ(4, stats_proxy_->GetStats().number_of_cpu_adapt_changes); |
+ EXPECT_EQ(2, stats_proxy_->GetStats().number_of_quality_adapt_changes); |
+ |
+ // Trigger adapt up, expect no change. |
+ vie_encoder_->TriggerQualityHigh(); |
+ VerifyNoLimitation(source.sink_wants()); |
+ EXPECT_EQ(4, stats_proxy_->GetStats().number_of_cpu_adapt_changes); |
+ EXPECT_EQ(2, stats_proxy_->GetStats().number_of_quality_adapt_changes); |
+ |
+ vie_encoder_->Stop(); |
+} |
+ |
+TEST_F(ViEEncoderTest, AdaptWithTwoReasonsAndDifferentOrder_Resolution) { |
+ const int kWidth = 640; |
+ const int kHeight = 360; |
+ const int kFpsLimit = 15; |
+ const int64_t kFrameIntervalMs = 150; |
+ int64_t timestamp_ms = kFrameIntervalMs; |
+ vie_encoder_->OnBitrateUpdated(kBpsLimitFor15Fps, 0, 0); |
+ |
+ // Enable kBalanced preference, no initial limitation. |
+ AdaptingFrameForwarder source; |
+ source.set_adaptation_enabled(true); |
+ vie_encoder_->SetSource(&source, |
+ VideoSendStream::DegradationPreference::kBalanced); |
+ timestamp_ms += kFrameIntervalMs; |
+ source.IncomingCapturedFrame(CreateFrame(timestamp_ms, kWidth, kHeight)); |
+ sink_.WaitForEncodedFrame(kWidth, kHeight); |
+ VerifyNoLimitation(source.sink_wants()); |
+ EXPECT_FALSE(stats_proxy_->GetStats().bw_limited_resolution); |
+ EXPECT_FALSE(stats_proxy_->GetStats().bw_limited_framerate); |
+ 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); |
+ EXPECT_EQ(0, stats_proxy_->GetStats().number_of_quality_adapt_changes); |
+ |
+ // Trigger cpu adapt down, expect scaled down framerate (640x360@15fps). |
+ vie_encoder_->TriggerCpuOveruse(); |
+ timestamp_ms += kFrameIntervalMs; |
+ source.IncomingCapturedFrame(CreateFrame(timestamp_ms, kWidth, kHeight)); |
+ sink_.WaitForEncodedFrame(timestamp_ms); |
+ VerifyFpsEqResolutionMax(source.sink_wants(), kFpsLimit); |
+ EXPECT_FALSE(stats_proxy_->GetStats().bw_limited_resolution); |
+ EXPECT_FALSE(stats_proxy_->GetStats().bw_limited_framerate); |
+ EXPECT_FALSE(stats_proxy_->GetStats().cpu_limited_resolution); |
+ EXPECT_TRUE(stats_proxy_->GetStats().cpu_limited_framerate); |
+ EXPECT_EQ(1, stats_proxy_->GetStats().number_of_cpu_adapt_changes); |
+ EXPECT_EQ(0, stats_proxy_->GetStats().number_of_quality_adapt_changes); |
+ |
+ // Trigger quality adapt down, expect scaled down resolution (480x270@15fps). |
+ vie_encoder_->TriggerQualityLow(); |
+ timestamp_ms += kFrameIntervalMs; |
+ source.IncomingCapturedFrame(CreateFrame(timestamp_ms, kWidth, kHeight)); |
+ sink_.WaitForEncodedFrame(timestamp_ms); |
+ VerifyFpsEqResolutionLt(source.sink_wants(), source.last_wants()); |
+ EXPECT_TRUE(stats_proxy_->GetStats().bw_limited_resolution); |
+ EXPECT_FALSE(stats_proxy_->GetStats().bw_limited_framerate); |
+ EXPECT_FALSE(stats_proxy_->GetStats().cpu_limited_resolution); |
+ EXPECT_TRUE(stats_proxy_->GetStats().cpu_limited_framerate); |
+ EXPECT_EQ(1, stats_proxy_->GetStats().number_of_cpu_adapt_changes); |
+ EXPECT_EQ(1, stats_proxy_->GetStats().number_of_quality_adapt_changes); |
+ |
+ // Trigger cpu adapt up, expect upscaled resolution (640x360@15fps). |
+ vie_encoder_->TriggerCpuNormalUsage(); |
+ timestamp_ms += kFrameIntervalMs; |
+ source.IncomingCapturedFrame(CreateFrame(timestamp_ms, kWidth, kHeight)); |
+ sink_.WaitForEncodedFrame(timestamp_ms); |
+ VerifyFpsEqResolutionGt(source.sink_wants(), source.last_wants()); |
+ EXPECT_FALSE(stats_proxy_->GetStats().bw_limited_resolution); |
+ EXPECT_TRUE(stats_proxy_->GetStats().bw_limited_framerate); |
+ EXPECT_FALSE(stats_proxy_->GetStats().cpu_limited_resolution); |
+ EXPECT_FALSE(stats_proxy_->GetStats().cpu_limited_framerate); |
+ EXPECT_EQ(2, stats_proxy_->GetStats().number_of_cpu_adapt_changes); |
+ EXPECT_EQ(1, stats_proxy_->GetStats().number_of_quality_adapt_changes); |
+ |
+ // Trigger quality adapt up, expect increased fps (640x360@30fps). |
+ vie_encoder_->TriggerQualityHigh(); |
+ timestamp_ms += kFrameIntervalMs; |
+ source.IncomingCapturedFrame(CreateFrame(timestamp_ms, kWidth, kHeight)); |
+ sink_.WaitForEncodedFrame(timestamp_ms); |
+ VerifyNoLimitation(source.sink_wants()); |
+ EXPECT_FALSE(stats_proxy_->GetStats().bw_limited_resolution); |
+ EXPECT_FALSE(stats_proxy_->GetStats().bw_limited_framerate); |
+ EXPECT_FALSE(stats_proxy_->GetStats().cpu_limited_resolution); |
+ EXPECT_FALSE(stats_proxy_->GetStats().cpu_limited_framerate); |
+ EXPECT_EQ(2, stats_proxy_->GetStats().number_of_cpu_adapt_changes); |
+ EXPECT_EQ(2, stats_proxy_->GetStats().number_of_quality_adapt_changes); |
+ |
+ // Trigger adapt up, expect no change. |
+ vie_encoder_->TriggerQualityHigh(); |
+ VerifyNoLimitation(source.sink_wants()); |
+ EXPECT_EQ(2, stats_proxy_->GetStats().number_of_cpu_adapt_changes); |
+ EXPECT_EQ(2, stats_proxy_->GetStats().number_of_quality_adapt_changes); |
+ |
+ vie_encoder_->Stop(); |
+} |
+ |
} // namespace webrtc |