| 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..d6d4d07ac4f688fbcf95a459a7d245fa8fd1e448 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();
|
| }
|
| @@ -1408,19 +1413,197 @@ 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(kWidth, kHeight);
|
| + 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 (960x540).
|
| + 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();
|
| + 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 (640x360).
|
| + 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();
|
| + 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(4);
|
| + EXPECT_EQ(last_wants.max_pixel_count, source.sink_wants().max_pixel_count);
|
| + 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 (480x270).
|
| + 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();
|
| + 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 (640x360).
|
| + 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();
|
| + 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 (960x540).
|
| + 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);
|
| + last_wants = source.sink_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);
|
| + EXPECT_EQ(1, stats_proxy_->GetStats().number_of_quality_adapt_changes);
|
| +
|
| + // Trigger cpu adapt up, no cpu downgrades, expect no change (960x540).
|
| + 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);
|
| + 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 (1280x720).
|
| + 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);
|
| + 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 +1765,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 +1802,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;
|
|
|