Index: webrtc/video/vie_encoder_unittest.cc |
diff --git a/webrtc/video/vie_encoder_unittest.cc b/webrtc/video/vie_encoder_unittest.cc |
index 704f90d9a57e78358a5979b52acea07504b7812b..79a08b354a37195d2b94c17966c09c67677b0334 100644 |
--- a/webrtc/video/vie_encoder_unittest.cc |
+++ b/webrtc/video/vie_encoder_unittest.cc |
@@ -284,6 +284,19 @@ class ViEEncoderTest : public ::testing::Test { |
return frame; |
} |
+ 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); |
+ } |
+ |
+ void VerifyResolutionLimitationLessThan(const rtc::VideoSinkWants& wants, |
+ int pixel_count) { |
+ 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); |
+ } |
+ |
class TestEncoder : public test::FakeEncoder { |
public: |
TestEncoder() |
@@ -715,9 +728,7 @@ TEST_F(ViEEncoderTest, SinkWantsRotationApplied) { |
TEST_F(ViEEncoderTest, SinkWantsFromOveruseDetector) { |
vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0); |
- EXPECT_FALSE(video_source_.sink_wants().target_pixel_count); |
- EXPECT_EQ(std::numeric_limits<int>::max(), |
- video_source_.sink_wants().max_pixel_count); |
+ VerifyNoLimitation(video_source_.sink_wants()); |
int frame_width = 1280; |
int frame_height = 720; |
@@ -763,12 +774,7 @@ TEST_F(ViEEncoderTest, SinkWantsFromOveruseDetector) { |
TEST_F(ViEEncoderTest, SinkWantsStoredByDegradationPreference) { |
vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0); |
- |
- EXPECT_FALSE(video_source_.sink_wants().target_pixel_count); |
- EXPECT_EQ(std::numeric_limits<int>::max(), |
- video_source_.sink_wants().max_pixel_count); |
- EXPECT_EQ(std::numeric_limits<int>::max(), |
- video_source_.sink_wants().max_framerate_fps); |
+ VerifyNoLimitation(video_source_.sink_wants()); |
const int kFrameWidth = 1280; |
const int kFrameHeight = 720; |
@@ -803,16 +809,13 @@ TEST_F(ViEEncoderTest, SinkWantsStoredByDegradationPreference) { |
VideoSendStream::DegradationPreference::kMaintainResolution); |
// Initially no degradation registered. |
- EXPECT_FALSE(new_video_source.sink_wants().target_pixel_count); |
- EXPECT_EQ(std::numeric_limits<int>::max(), |
- new_video_source.sink_wants().max_pixel_count); |
- EXPECT_EQ(std::numeric_limits<int>::max(), |
- new_video_source.sink_wants().max_framerate_fps); |
+ VerifyNoLimitation(new_video_source.sink_wants()); |
// Force an input frame rate to be available, or the adaptation call won't |
// know what framerate to adapt form. |
+ const int kInputFps = 30; |
VideoSendStream::Stats stats = stats_proxy_->GetStats(); |
- stats.input_frame_rate = 30; |
+ stats.input_frame_rate = kInputFps; |
stats_proxy_->SetMockStats(stats); |
vie_encoder_->TriggerCpuOveruse(); |
@@ -825,19 +828,13 @@ TEST_F(ViEEncoderTest, SinkWantsStoredByDegradationPreference) { |
EXPECT_FALSE(new_video_source.sink_wants().target_pixel_count); |
EXPECT_EQ(std::numeric_limits<int>::max(), |
new_video_source.sink_wants().max_pixel_count); |
- EXPECT_TRUE(new_video_source.sink_wants().max_framerate_fps); |
+ EXPECT_LT(new_video_source.sink_wants().max_framerate_fps, kInputFps); |
- // Turn of degradation completely. |
+ // Turn off degradation completely. |
vie_encoder_->SetSource( |
&new_video_source, |
VideoSendStream::DegradationPreference::kDegradationDisabled); |
- |
- // Initially no degradation registered. |
- EXPECT_FALSE(new_video_source.sink_wants().target_pixel_count); |
- EXPECT_EQ(std::numeric_limits<int>::max(), |
- new_video_source.sink_wants().max_pixel_count); |
- EXPECT_EQ(std::numeric_limits<int>::max(), |
- new_video_source.sink_wants().max_framerate_fps); |
+ VerifyNoLimitation(new_video_source.sink_wants()); |
vie_encoder_->TriggerCpuOveruse(); |
new_video_source.IncomingCapturedFrame( |
@@ -846,11 +843,7 @@ TEST_F(ViEEncoderTest, SinkWantsStoredByDegradationPreference) { |
frame_timestamp += kFrameIntervalMs; |
// Still no degradation. |
- EXPECT_FALSE(new_video_source.sink_wants().target_pixel_count); |
- EXPECT_EQ(std::numeric_limits<int>::max(), |
- new_video_source.sink_wants().max_pixel_count); |
- EXPECT_EQ(std::numeric_limits<int>::max(), |
- new_video_source.sink_wants().max_framerate_fps); |
+ VerifyNoLimitation(new_video_source.sink_wants()); |
// Calling SetSource with resolution scaling enabled apply the old SinkWants. |
vie_encoder_->SetSource( |
@@ -869,7 +862,7 @@ TEST_F(ViEEncoderTest, SinkWantsStoredByDegradationPreference) { |
EXPECT_FALSE(new_video_source.sink_wants().target_pixel_count); |
EXPECT_EQ(std::numeric_limits<int>::max(), |
new_video_source.sink_wants().max_pixel_count); |
- EXPECT_TRUE(new_video_source.sink_wants().max_framerate_fps); |
+ EXPECT_LT(new_video_source.sink_wants().max_framerate_fps, kInputFps); |
vie_encoder_->Stop(); |
} |
@@ -879,7 +872,6 @@ TEST_F(ViEEncoderTest, StatsTracksQualityAdaptationStats) { |
const int kWidth = 1280; |
const int kHeight = 720; |
- |
video_source_.IncomingCapturedFrame(CreateFrame(1, kWidth, kHeight)); |
sink_.WaitForEncodedFrame(1); |
VideoSendStream::Stats stats = stats_proxy_->GetStats(); |
@@ -913,7 +905,6 @@ TEST_F(ViEEncoderTest, StatsTracksCpuAdaptationStats) { |
const int kWidth = 1280; |
const int kHeight = 720; |
- |
video_source_.IncomingCapturedFrame(CreateFrame(1, kWidth, kHeight)); |
sink_.WaitForEncodedFrame(1); |
VideoSendStream::Stats stats = stats_proxy_->GetStats(); |
@@ -1002,6 +993,7 @@ TEST_F(ViEEncoderTest, SwitchingSourceKeepsCpuAdaptation) { |
stats = stats_proxy_->GetStats(); |
EXPECT_FALSE(stats.cpu_limited_resolution); |
EXPECT_EQ(2, stats.number_of_cpu_adapt_changes); |
+ EXPECT_EQ(0, stats.number_of_quality_adapt_changes); |
vie_encoder_->Stop(); |
} |
@@ -1050,7 +1042,7 @@ TEST_F(ViEEncoderTest, SwitchingSourceKeepsQualityAdaptation) { |
EXPECT_TRUE(stats.bw_limited_resolution); |
EXPECT_EQ(1, stats.number_of_quality_adapt_changes); |
- // Set adaptation disabled. |
+ // Disable resolution scaling. |
vie_encoder_->SetSource( |
&new_video_source, |
VideoSendStream::DegradationPreference::kMaintainResolution); |
@@ -1109,7 +1101,7 @@ TEST_F(ViEEncoderTest, QualityAdaptationStatsAreResetWhenScalerIsDisabled) { |
vie_encoder_->Stop(); |
} |
-TEST_F(ViEEncoderTest, StatsTracksAdaptationStatsWhenSwitchingSource) { |
+TEST_F(ViEEncoderTest, StatsTracksCpuAdaptationStatsWhenSwitchingSource) { |
vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0); |
const int kWidth = 1280; |
@@ -1118,16 +1110,14 @@ TEST_F(ViEEncoderTest, StatsTracksAdaptationStatsWhenSwitchingSource) { |
video_source_.IncomingCapturedFrame(CreateFrame(sequence, kWidth, kHeight)); |
sink_.WaitForEncodedFrame(sequence++); |
- |
VideoSendStream::Stats stats = stats_proxy_->GetStats(); |
EXPECT_FALSE(stats.cpu_limited_resolution); |
EXPECT_EQ(0, stats.number_of_cpu_adapt_changes); |
- // Trigger CPU overuse again, should now adapt down. |
+ // Trigger CPU overuse, should now adapt down. |
vie_encoder_->TriggerCpuOveruse(); |
video_source_.IncomingCapturedFrame(CreateFrame(sequence, kWidth, kHeight)); |
sink_.WaitForEncodedFrame(sequence++); |
- |
stats = stats_proxy_->GetStats(); |
EXPECT_TRUE(stats.cpu_limited_resolution); |
EXPECT_EQ(1, stats.number_of_cpu_adapt_changes); |
@@ -1233,6 +1223,7 @@ TEST_F(ViEEncoderTest, StatsTracksAdaptationStatsWhenSwitchingSource) { |
stats = stats_proxy_->GetStats(); |
EXPECT_FALSE(stats.cpu_limited_resolution); |
EXPECT_EQ(4, stats.number_of_cpu_adapt_changes); |
+ EXPECT_EQ(0, stats.number_of_quality_adapt_changes); |
vie_encoder_->Stop(); |
} |
@@ -1258,9 +1249,7 @@ TEST_F(ViEEncoderTest, ScalingUpAndDownDoesNothingWithMaintainResolution) { |
vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0); |
// Expect no scaling to begin with. |
- EXPECT_FALSE(video_source_.sink_wants().target_pixel_count); |
- EXPECT_EQ(std::numeric_limits<int>::max(), |
- video_source_.sink_wants().max_pixel_count); |
+ VerifyNoLimitation(video_source_.sink_wants()); |
video_source_.IncomingCapturedFrame(CreateFrame(1, kWidth, kHeight)); |
sink_.WaitForEncodedFrame(1); |
@@ -1275,7 +1264,7 @@ TEST_F(ViEEncoderTest, ScalingUpAndDownDoesNothingWithMaintainResolution) { |
EXPECT_TRUE(video_source_.sink_wants().max_pixel_count); |
EXPECT_LT(video_source_.sink_wants().max_pixel_count, kWidth * kHeight); |
- // Set adaptation disabled. |
+ // Set resolution scaling disabled. |
test::FrameForwarder new_video_source; |
vie_encoder_->SetSource( |
&new_video_source, |
@@ -1295,13 +1284,130 @@ 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. |
EXPECT_EQ(std::numeric_limits<int>::max(), |
new_video_source.sink_wants().max_pixel_count); |
vie_encoder_->Stop(); |
} |
+TEST_F(ViEEncoderTest, SkipsSameAdaptDownRequest_MaintainFramerateMode) { |
+ const int kWidth = 1280; |
+ const int kHeight = 720; |
+ vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0); |
+ |
+ // Enable kMaintainFramerate preference, no initial limitation. |
+ test::FrameForwarder source; |
+ 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(); |
+ VerifyResolutionLimitationLessThan(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); |
+ |
+ // Trigger adapt down for same input resolution, expect no change. |
+ vie_encoder_->TriggerCpuOveruse(); |
+ EXPECT_EQ(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); |
+ |
+ vie_encoder_->Stop(); |
+} |
+ |
+TEST_F(ViEEncoderTest, NoChangeForInitialNormalUsage_MaintainFramerateMode) { |
+ const int kWidth = 1280; |
+ const int kHeight = 720; |
+ vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0); |
+ |
+ // Enable kMaintainFramerate preference, no initial limitation. |
+ test::FrameForwarder source; |
+ 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_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_EQ(0, stats_proxy_->GetStats().number_of_cpu_adapt_changes); |
+ |
+ vie_encoder_->Stop(); |
+} |
+ |
+TEST_F(ViEEncoderTest, NoChangeForInitialNormalUsage_MaintainResolutionMode) { |
+ const int kWidth = 1280; |
+ const int kHeight = 720; |
+ vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0); |
+ |
+ // Enable kMaintainResolution preference, no initial limitation. |
+ test::FrameForwarder source; |
+ vie_encoder_->SetSource( |
+ &source, VideoSendStream::DegradationPreference::kMaintainResolution); |
+ |
+ source.IncomingCapturedFrame(CreateFrame(1, kWidth, kHeight)); |
+ 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); |
+ |
+ // Trigger adapt up, expect no change. |
+ vie_encoder_->TriggerCpuNormalUsage(); |
+ 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, AdaptsResolutionForLowQuality_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().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); |
+ VerifyResolutionLimitationLessThan(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(); |
+ VerifyNoLimitation(source.sink_wants()); |
+ EXPECT_FALSE(stats_proxy_->GetStats().bw_limited_resolution); |
+ EXPECT_EQ(2, stats_proxy_->GetStats().number_of_quality_adapt_changes); |
+ EXPECT_EQ(0, stats_proxy_->GetStats().number_of_cpu_adapt_changes); |
+ |
+ vie_encoder_->Stop(); |
+} |
+ |
TEST_F(ViEEncoderTest, DoesNotScaleBelowSetLimit) { |
int frame_width = 1280; |
int frame_height = 720; |
@@ -1476,6 +1582,18 @@ TEST_F(ViEEncoderTest, InitialFrameDropOffWhenEncoderDisabledScaling) { |
fake_encoder_.SetQualityScaling(true); |
} |
+TEST_F(ViEEncoderTest, FailingInitEncodeDoesntCauseCrash) { |
+ fake_encoder_.ForceInitEncodeFailure(true); |
+ vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0); |
+ ResetEncoder("VP8", 2, 1, true); |
+ const int kFrameWidth = 1280; |
+ const int kFrameHeight = 720; |
+ video_source_.IncomingCapturedFrame( |
+ CreateFrame(1, kFrameWidth, kFrameHeight)); |
+ sink_.ExpectDroppedFrame(); |
+ vie_encoder_->Stop(); |
+} |
+ |
// TODO(sprang): Extend this with fps throttling and any "balanced" extensions. |
TEST_F(ViEEncoderTest, AdaptsResolutionOnOveruse) { |
vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0); |
@@ -1505,19 +1623,7 @@ TEST_F(ViEEncoderTest, AdaptsResolutionOnOveruse) { |
vie_encoder_->Stop(); |
} |
-TEST_F(ViEEncoderTest, FailingInitEncodeDoesntCauseCrash) { |
- fake_encoder_.ForceInitEncodeFailure(true); |
- vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0); |
- ResetEncoder("VP8", 2, 1, true); |
- const int kFrameWidth = 1280; |
- const int kFrameHeight = 720; |
- video_source_.IncomingCapturedFrame( |
- CreateFrame(1, kFrameWidth, kFrameHeight)); |
- sink_.ExpectDroppedFrame(); |
- vie_encoder_->Stop(); |
-} |
- |
-TEST_F(ViEEncoderTest, AdaptsFrameOnOveruseWithMaintainResolution) { |
+TEST_F(ViEEncoderTest, AdaptsFramerateOnOveruse_MaintainResolutionMode) { |
const int kDefaultFramerateFps = 30; |
const int kFrameIntervalMs = rtc::kNumMillisecsPerSec / kDefaultFramerateFps; |
const int kFrameWidth = 1280; |