Chromium Code Reviews| Index: webrtc/video/vie_encoder_unittest.cc |
| diff --git a/webrtc/video/vie_encoder_unittest.cc b/webrtc/video/vie_encoder_unittest.cc |
| index 79a08b354a37195d2b94c17966c09c67677b0334..085db9c941f811b992fb1b75b44420151ef3eca2 100644 |
| --- a/webrtc/video/vie_encoder_unittest.cc |
| +++ b/webrtc/video/vie_encoder_unittest.cc |
| @@ -29,13 +29,9 @@ |
| #include "webrtc/video/vie_encoder.h" |
| namespace { |
| -#if defined(WEBRTC_ANDROID) |
| // TODO(kthelgason): Lower this limit when better testing |
| // on MediaCodec and fallback implementations are in place. |
| const int kMinPixelsPerFrame = 320 * 180; |
| -#else |
| -const int kMinPixelsPerFrame = 120 * 90; |
| -#endif |
| const int kMinFramerateFps = 2; |
| const int64_t kFrameTimeoutMs = 100; |
| } // namespace |
| @@ -726,6 +722,7 @@ TEST_F(ViEEncoderTest, SinkWantsRotationApplied) { |
| } |
| TEST_F(ViEEncoderTest, SinkWantsFromOveruseDetector) { |
| + const int kMaxDowngrades = ViEEncoder::kMaxCpuResolutionDowngrades; |
| vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0); |
| VerifyNoLimitation(video_source_.sink_wants()); |
| @@ -735,7 +732,7 @@ TEST_F(ViEEncoderTest, SinkWantsFromOveruseDetector) { |
| // Trigger CPU overuse kMaxCpuDowngrades times. Every time, ViEEncoder should |
| // request lower resolution. |
| - for (int i = 1; i <= ViEEncoder::kMaxCpuResolutionDowngrades; ++i) { |
| + for (int i = 1; i <= kMaxDowngrades; ++i) { |
| video_source_.IncomingCapturedFrame( |
| CreateFrame(i, frame_width, frame_height)); |
| sink_.WaitForEncodedFrame(i); |
| @@ -745,6 +742,8 @@ TEST_F(ViEEncoderTest, SinkWantsFromOveruseDetector) { |
| EXPECT_FALSE(video_source_.sink_wants().target_pixel_count); |
| EXPECT_LT(video_source_.sink_wants().max_pixel_count, |
| frame_width * frame_height); |
| + EXPECT_TRUE(stats_proxy_->GetStats().cpu_limited_resolution); |
| + EXPECT_EQ(i, stats_proxy_->GetStats().number_of_cpu_adapt_changes); |
| frame_width /= 2; |
| frame_height /= 2; |
| @@ -753,14 +752,17 @@ TEST_F(ViEEncoderTest, SinkWantsFromOveruseDetector) { |
| // Trigger CPU overuse one more time. This should not trigger a request for |
| // lower resolution. |
| rtc::VideoSinkWants current_wants = video_source_.sink_wants(); |
| - video_source_.IncomingCapturedFrame(CreateFrame( |
| - ViEEncoder::kMaxCpuResolutionDowngrades + 1, frame_width, frame_height)); |
| - sink_.WaitForEncodedFrame(ViEEncoder::kMaxCpuResolutionDowngrades + 1); |
| + video_source_.IncomingCapturedFrame( |
| + CreateFrame(kMaxDowngrades + 1, frame_width, frame_height)); |
| + sink_.WaitForEncodedFrame(kMaxDowngrades + 1); |
| vie_encoder_->TriggerCpuOveruse(); |
| EXPECT_EQ(video_source_.sink_wants().target_pixel_count, |
| current_wants.target_pixel_count); |
| EXPECT_EQ(video_source_.sink_wants().max_pixel_count, |
| current_wants.max_pixel_count); |
| + EXPECT_TRUE(stats_proxy_->GetStats().cpu_limited_resolution); |
| + EXPECT_EQ(kMaxDowngrades, |
| + stats_proxy_->GetStats().number_of_cpu_adapt_changes); |
| // Trigger CPU normal use. |
| vie_encoder_->TriggerCpuNormalUsage(); |
| @@ -768,6 +770,9 @@ TEST_F(ViEEncoderTest, SinkWantsFromOveruseDetector) { |
| video_source_.sink_wants().target_pixel_count.value_or(0)); |
| EXPECT_EQ(frame_width * frame_height * 4, |
| video_source_.sink_wants().max_pixel_count); |
| + EXPECT_TRUE(stats_proxy_->GetStats().cpu_limited_resolution); |
| + EXPECT_EQ(kMaxDowngrades + 1, |
| + stats_proxy_->GetStats().number_of_cpu_adapt_changes); |
| vie_encoder_->Stop(); |
| } |
| @@ -1284,7 +1289,7 @@ TEST_F(ViEEncoderTest, ScalingUpAndDownDoesNothingWithMaintainResolution) { |
| new_video_source.IncomingCapturedFrame(CreateFrame(4, kWidth, kHeight)); |
| sink_.WaitForEncodedFrame(4); |
| - // Expect nothing to change, still no scaling. |
| + // Expect nothing to change, still no scaling |
|
kthelgason
2017/04/19 08:23:04
accident?
åsapersson
2017/04/20 13:44:47
yes
|
| EXPECT_EQ(std::numeric_limits<int>::max(), |
| new_video_source.sink_wants().max_pixel_count); |
| @@ -1408,19 +1413,185 @@ TEST_F(ViEEncoderTest, AdaptsResolutionForLowQuality_MaintainFramerateMode) { |
| vie_encoder_->Stop(); |
| } |
| -TEST_F(ViEEncoderTest, DoesNotScaleBelowSetLimit) { |
| - int frame_width = 1280; |
| - int frame_height = 720; |
| +TEST_F(ViEEncoderTest, DoesNotScaleBelowSetResolutionLimit) { |
| + const int kWidth = 1280; |
| + const int kHeight = 720; |
| + const size_t kNumFrames = 10; |
| + |
| vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0); |
| - for (size_t i = 1; i <= 10; i++) { |
| - video_source_.IncomingCapturedFrame( |
| - CreateFrame(i, frame_width, frame_height)); |
| + // Enable adapter, expected input resolutions when downscaling: |
| + // 1280x720 -> 960x540 -> 640x360 -> 480x270 -> 320x180 (min resolution limit) |
| + video_source_.set_adaptation_enabled(true); |
| + |
| + EXPECT_FALSE(stats_proxy_->GetStats().bw_limited_resolution); |
| + EXPECT_EQ(0, stats_proxy_->GetStats().number_of_quality_adapt_changes); |
| + |
| + int downscales = 0; |
| + for (size_t i = 1; i <= kNumFrames; i++) { |
| + video_source_.IncomingCapturedFrame(CreateFrame(i, kWidth, kHeight)); |
| sink_.WaitForEncodedFrame(i); |
| + |
| // Trigger scale down. |
| + rtc::VideoSinkWants last_wants = video_source_.sink_wants(); |
| vie_encoder_->TriggerQualityLow(); |
| EXPECT_GE(video_source_.sink_wants().max_pixel_count, kMinPixelsPerFrame); |
| + |
| + if (video_source_.sink_wants().max_pixel_count < last_wants.max_pixel_count) |
| + ++downscales; |
| + |
| + EXPECT_TRUE(stats_proxy_->GetStats().bw_limited_resolution); |
| + EXPECT_EQ(downscales, |
| + stats_proxy_->GetStats().number_of_quality_adapt_changes); |
| + EXPECT_GT(downscales, 0); |
| } |
| + vie_encoder_->Stop(); |
| +} |
| + |
| +TEST_F(ViEEncoderTest, |
| + AdaptsResolutionUpAndDownTwiceOnOveruse_MaintainFramerateMode) { |
| + const int kWidth = 1280; |
| + const int kHeight = 720; |
| + vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0); |
| + |
| + // Enable kMaintainFramerate preference, no initial limitation. |
| + AdaptingFrameForwarder source; |
| + source.set_adaptation_enabled(true); |
| + vie_encoder_->SetSource( |
| + &source, VideoSendStream::DegradationPreference::kMaintainFramerate); |
| + |
| + source.IncomingCapturedFrame(CreateFrame(1, kWidth, kHeight)); |
| + sink_.WaitForEncodedFrame(1); |
| + 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, expect scaled down resolution. |
| + vie_encoder_->TriggerCpuOveruse(); |
| + source.IncomingCapturedFrame(CreateFrame(2, kWidth, kHeight)); |
| + sink_.WaitForEncodedFrame(2); |
| + VerifyResolutionLimitationLessThan(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); |
| + VerifyNoLimitation(source.sink_wants()); |
| + EXPECT_FALSE(stats_proxy_->GetStats().cpu_limited_resolution); |
| + EXPECT_EQ(2, stats_proxy_->GetStats().number_of_cpu_adapt_changes); |
| + |
| + // Trigger adapt down, expect scaled down resolution. |
| + vie_encoder_->TriggerCpuOveruse(); |
| + source.IncomingCapturedFrame(CreateFrame(4, kWidth, kHeight)); |
| + sink_.WaitForEncodedFrame(4); |
| + VerifyResolutionLimitationLessThan(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(); |
| + VerifyNoLimitation(source.sink_wants()); |
| + EXPECT_FALSE(stats_proxy_->GetStats().cpu_limited_resolution); |
| + EXPECT_EQ(4, stats_proxy_->GetStats().number_of_cpu_adapt_changes); |
| + |
| + vie_encoder_->Stop(); |
| +} |
| + |
| +TEST_F(ViEEncoderTest, |
| + AdaptsResolutionOnOveruseAndLowQuality_MaintainFramerateMode) { |
| + const int kWidth = 1280; |
| + const int kHeight = 720; |
| + vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0); |
| + |
| + // Enable kMaintainFramerate preference, no initial limitation. |
| + AdaptingFrameForwarder source; |
| + source.set_adaptation_enabled(true); |
| + vie_encoder_->SetSource( |
| + &source, VideoSendStream::DegradationPreference::kMaintainFramerate); |
| + |
| + source.IncomingCapturedFrame(CreateFrame(1, kWidth, kHeight)); |
| + sink_.WaitForEncodedFrame(1280, 720); |
| + VerifyNoLimitation(source.sink_wants()); |
| + EXPECT_FALSE(stats_proxy_->GetStats().cpu_limited_resolution); |
| + EXPECT_FALSE(stats_proxy_->GetStats().bw_limited_resolution); |
| + 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. |
| + vie_encoder_->TriggerCpuOveruse(); |
| + source.IncomingCapturedFrame(CreateFrame(2, kWidth, kHeight)); |
| + sink_.WaitForEncodedFrame(960, 540); |
|
kthelgason
2017/04/19 08:23:04
I've tried to avoid making assumptions about the s
åsapersson
2017/04/20 13:44:47
Done.
|
| + VerifyResolutionLimitationLessThan(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); |
| + EXPECT_EQ(0, stats_proxy_->GetStats().number_of_quality_adapt_changes); |
| + |
| + // Trigger cpu adapt down, expect scaled down resolution. |
| + vie_encoder_->TriggerCpuOveruse(); |
| + source.IncomingCapturedFrame(CreateFrame(3, kWidth, kHeight)); |
| + sink_.WaitForEncodedFrame(640, 360); |
| + 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); |
| + EXPECT_EQ(0, stats_proxy_->GetStats().number_of_quality_adapt_changes); |
| + |
| + // Trigger cpu adapt down, max cpu downgrades reached, expect no change. |
| + vie_encoder_->TriggerCpuOveruse(); |
| + source.IncomingCapturedFrame(CreateFrame(4, kWidth, kHeight)); |
| + sink_.WaitForEncodedFrame(640, 360); |
| + 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); |
| + EXPECT_EQ(0, stats_proxy_->GetStats().number_of_quality_adapt_changes); |
| + |
| + // Trigger quality adapt down, expect scaled down resolution. |
| + vie_encoder_->TriggerQualityLow(); |
| + source.IncomingCapturedFrame(CreateFrame(5, kWidth, kHeight)); |
| + sink_.WaitForEncodedFrame(480, 270); |
| + 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); |
| + EXPECT_EQ(1, stats_proxy_->GetStats().number_of_quality_adapt_changes); |
| + |
| + // Trigger cpu adapt up, expect upscaled resolution. |
| + vie_encoder_->TriggerCpuNormalUsage(); |
| + source.IncomingCapturedFrame(CreateFrame(6, kWidth, kHeight)); |
| + sink_.WaitForEncodedFrame(640, 360); |
| + 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); |
| + EXPECT_EQ(1, stats_proxy_->GetStats().number_of_quality_adapt_changes); |
| + |
| + // Trigger cpu adapt up, expect upscaled resolution. |
| + vie_encoder_->TriggerCpuNormalUsage(); |
| + source.IncomingCapturedFrame(CreateFrame(7, kWidth, kHeight)); |
| + sink_.WaitForEncodedFrame(960, 540); |
| + 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); |
| + EXPECT_EQ(1, stats_proxy_->GetStats().number_of_quality_adapt_changes); |
| + |
| + // Trigger cpu adapt up, no cpu downgrades, expect no change. |
| + vie_encoder_->TriggerCpuNormalUsage(); |
| + source.IncomingCapturedFrame(CreateFrame(8, kWidth, kHeight)); |
| + sink_.WaitForEncodedFrame(960, 540); |
| + 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); |
| + EXPECT_EQ(1, stats_proxy_->GetStats().number_of_quality_adapt_changes); |
| + |
| + // Trigger quality adapt up, expect no restriction. |
| + vie_encoder_->TriggerQualityHigh(); |
| + source.IncomingCapturedFrame(CreateFrame(9, kWidth, kHeight)); |
| + sink_.WaitForEncodedFrame(1280, 720); |
| + VerifyNoLimitation(source.sink_wants()); |
| + EXPECT_FALSE(stats_proxy_->GetStats().cpu_limited_resolution); |
| + EXPECT_FALSE(stats_proxy_->GetStats().bw_limited_resolution); |
| + 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(); |
| } |
| @@ -1582,6 +1753,30 @@ TEST_F(ViEEncoderTest, InitialFrameDropOffWhenEncoderDisabledScaling) { |
| fake_encoder_.SetQualityScaling(true); |
| } |
| +TEST_F(ViEEncoderTest, |
| + ResolutionNotAdaptedForTooSmallFrame_MaintainFramerateMode) { |
| + const int kTooSmallWidth = 10; |
| + const int kTooSmallHeight = 10; |
| + vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0); |
| + |
| + // Enable kMaintainFramerate preference, no initial limitation. |
| + test::FrameForwarder source; |
| + vie_encoder_->SetSource( |
| + &source, VideoSendStream::DegradationPreference::kMaintainFramerate); |
| + VerifyNoLimitation(source.sink_wants()); |
| + EXPECT_FALSE(stats_proxy_->GetStats().cpu_limited_resolution); |
| + |
| + // Trigger adapt down, too small frame, expect no change. |
| + source.IncomingCapturedFrame(CreateFrame(1, kTooSmallWidth, kTooSmallHeight)); |
| + sink_.WaitForEncodedFrame(1); |
| + vie_encoder_->TriggerCpuOveruse(); |
| + VerifyNoLimitation(source.sink_wants()); |
| + EXPECT_FALSE(stats_proxy_->GetStats().cpu_limited_resolution); |
| + EXPECT_EQ(0, stats_proxy_->GetStats().number_of_cpu_adapt_changes); |
| + |
| + vie_encoder_->Stop(); |
| +} |
| + |
| TEST_F(ViEEncoderTest, FailingInitEncodeDoesntCauseCrash) { |
| fake_encoder_.ForceInitEncodeFailure(true); |
| vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0); |
| @@ -1595,7 +1790,7 @@ TEST_F(ViEEncoderTest, FailingInitEncodeDoesntCauseCrash) { |
| } |
| // TODO(sprang): Extend this with fps throttling and any "balanced" extensions. |
| -TEST_F(ViEEncoderTest, AdaptsResolutionOnOveruse) { |
| +TEST_F(ViEEncoderTest, AdaptsResolutionOnOveruse_MaintainFramerateMode) { |
| vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0); |
| const int kFrameWidth = 1280; |