Index: webrtc/video/vie_encoder_unittest.cc |
diff --git a/webrtc/video/vie_encoder_unittest.cc b/webrtc/video/vie_encoder_unittest.cc |
index 71e68d3ae584e81e097d79e3c9b64a64b30a26c8..6cc25cfb80e925946ec1a897f915b6169fecbdf4 100644 |
--- a/webrtc/video/vie_encoder_unittest.cc |
+++ b/webrtc/video/vie_encoder_unittest.cc |
@@ -22,6 +22,9 @@ |
namespace webrtc { |
+using DegredationPreference = VideoSendStream::DegradationPreference; |
+using ScaleReason = ScalingObserverInterface::ScaleReason; |
+ |
namespace { |
const size_t kMaxPayloadLength = 1440; |
const int kTargetBitrateBps = 100000; |
@@ -42,32 +45,30 @@ class TestBuffer : public webrtc::I420Buffer { |
class ViEEncoderUnderTest : public ViEEncoder { |
public: |
- ViEEncoderUnderTest( |
- SendStatisticsProxy* stats_proxy, |
- const webrtc::VideoSendStream::Config::EncoderSettings& settings) |
+ ViEEncoderUnderTest(SendStatisticsProxy* stats_proxy, |
+ const VideoSendStream::Config::EncoderSettings& settings) |
: ViEEncoder(1 /* number_of_cores */, |
stats_proxy, |
settings, |
nullptr /* pre_encode_callback */, |
nullptr /* encoder_timing */) {} |
- void TriggerCpuOveruse() { |
+ void PostTaskAndWait(bool down, ScaleReason reason) { |
rtc::Event event(false, false); |
- encoder_queue()->PostTask([this, &event] { |
- OveruseDetected(); |
+ encoder_queue()->PostTask([this, &event, reason, down] { |
+ down ? ScaleDown(reason) : ScaleUp(reason); |
event.Set(); |
}); |
- event.Wait(rtc::Event::kForever); |
+ RTC_DCHECK(event.Wait(5000)); |
} |
- void TriggerCpuNormalUsage() { |
- rtc::Event event(false, false); |
- encoder_queue()->PostTask([this, &event] { |
- NormalUsage(); |
- event.Set(); |
- }); |
- event.Wait(rtc::Event::kForever); |
- } |
+ void TriggerCpuOveruse() { PostTaskAndWait(true, ScaleReason::kCpu); } |
+ |
+ void TriggerCpuNormalUsage() { PostTaskAndWait(false, ScaleReason::kCpu); } |
+ |
+ void TriggerQualityLow() { PostTaskAndWait(true, ScaleReason::kQuality); } |
+ |
+ void TriggerQualityHigh() { PostTaskAndWait(false, ScaleReason::kQuality); } |
}; |
class VideoStreamFactory |
@@ -183,6 +184,10 @@ class ViEEncoderTest : public ::testing::Test { |
block_next_encode_ = true; |
} |
+ VideoEncoder::ScalingSettings GetScalingSettings() const override { |
+ return VideoEncoder::ScalingSettings(true, 1, 2); |
+ } |
+ |
void ContinueEncode() { continue_encode_event_.Set(); } |
void CheckLastTimeStampsMatch(int64_t ntp_time_ms, |
@@ -549,7 +554,7 @@ TEST_F(ViEEncoderTest, SinkWantsFromOveruseDetector) { |
frame_height /= 2; |
} |
- // Trigger CPU overuse a one more time. This should not trigger request for |
+ // 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( |
@@ -653,6 +658,138 @@ TEST_F(ViEEncoderTest, StatsTracksAdaptationStats) { |
vie_encoder_->Stop(); |
} |
+TEST_F(ViEEncoderTest, SwitchingSourceKeepsCpuAdaptation) { |
+ const int kTargetBitrateBps = 100000; |
+ vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0); |
+ |
+ int frame_width = 1280; |
+ int frame_height = 720; |
+ video_source_.IncomingCapturedFrame( |
+ CreateFrame(1, frame_width, frame_height)); |
+ sink_.WaitForEncodedFrame(1); |
+ |
+ VideoSendStream::Stats stats = stats_proxy_->GetStats(); |
+ EXPECT_FALSE(stats.cpu_limited_resolution); |
+ EXPECT_EQ(0, stats.number_of_cpu_adapt_changes); |
+ |
+ vie_encoder_->TriggerCpuOveruse(); |
+ |
+ video_source_.IncomingCapturedFrame( |
+ CreateFrame(2, frame_width, frame_height)); |
+ sink_.WaitForEncodedFrame(2); |
+ stats = stats_proxy_->GetStats(); |
+ EXPECT_TRUE(stats.cpu_limited_resolution); |
+ EXPECT_EQ(1, stats.number_of_cpu_adapt_changes); |
+ |
+ // Set new source with adaptation still enabled. |
+ test::FrameForwarder new_video_source; |
+ vie_encoder_->SetSource(&new_video_source, |
+ VideoSendStream::DegradationPreference::kBalanced); |
+ |
+ new_video_source.IncomingCapturedFrame( |
+ CreateFrame(3, frame_width, frame_height)); |
+ sink_.WaitForEncodedFrame(3); |
+ stats = stats_proxy_->GetStats(); |
+ EXPECT_TRUE(stats.cpu_limited_resolution); |
+ EXPECT_EQ(1, stats.number_of_cpu_adapt_changes); |
+ |
+ // Set adaptation disabled. |
+ vie_encoder_->SetSource( |
+ &new_video_source, |
+ VideoSendStream::DegradationPreference::kMaintainResolution); |
+ |
+ new_video_source.IncomingCapturedFrame( |
+ CreateFrame(4, frame_width, frame_height)); |
+ sink_.WaitForEncodedFrame(4); |
+ stats = stats_proxy_->GetStats(); |
+ EXPECT_FALSE(stats.cpu_limited_resolution); |
+ EXPECT_EQ(1, stats.number_of_cpu_adapt_changes); |
+ |
+ // Set adaptation back to enabled. |
+ vie_encoder_->SetSource(&new_video_source, |
+ VideoSendStream::DegradationPreference::kBalanced); |
+ |
+ new_video_source.IncomingCapturedFrame( |
+ CreateFrame(5, frame_width, frame_height)); |
+ sink_.WaitForEncodedFrame(5); |
+ stats = stats_proxy_->GetStats(); |
+ EXPECT_TRUE(stats.cpu_limited_resolution); |
+ EXPECT_EQ(1, stats.number_of_cpu_adapt_changes); |
+ |
+ vie_encoder_->TriggerCpuNormalUsage(); |
+ |
+ new_video_source.IncomingCapturedFrame( |
+ CreateFrame(6, frame_width, frame_height)); |
+ sink_.WaitForEncodedFrame(6); |
+ stats = stats_proxy_->GetStats(); |
+ EXPECT_FALSE(stats.cpu_limited_resolution); |
+ EXPECT_EQ(2, stats.number_of_cpu_adapt_changes); |
+ |
+ vie_encoder_->Stop(); |
+} |
+ |
+TEST_F(ViEEncoderTest, SwitchingSourceKeepsQualityAdaptation) { |
+ const int kTargetBitrateBps = 100000; |
+ vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0); |
+ |
+ int frame_width = 1280; |
+ int frame_height = 720; |
+ video_source_.IncomingCapturedFrame( |
+ CreateFrame(1, frame_width, frame_height)); |
+ sink_.WaitForEncodedFrame(1); |
+ |
+ VideoSendStream::Stats stats = stats_proxy_->GetStats(); |
+ EXPECT_FALSE(stats.cpu_limited_resolution); |
+ EXPECT_FALSE(stats.bw_limited_resolution); |
+ EXPECT_EQ(0, stats.number_of_cpu_adapt_changes); |
+ |
+ // Set new source with adaptation still enabled. |
+ test::FrameForwarder new_video_source; |
+ vie_encoder_->SetSource(&new_video_source, |
+ VideoSendStream::DegradationPreference::kBalanced); |
+ |
+ new_video_source.IncomingCapturedFrame( |
+ CreateFrame(2, frame_width, frame_height)); |
+ sink_.WaitForEncodedFrame(2); |
+ stats = stats_proxy_->GetStats(); |
+ EXPECT_FALSE(stats.cpu_limited_resolution); |
+ EXPECT_FALSE(stats.bw_limited_resolution); |
+ EXPECT_EQ(0, stats.number_of_cpu_adapt_changes); |
+ |
+ vie_encoder_->TriggerQualityLow(); |
+ |
+ new_video_source.IncomingCapturedFrame( |
+ CreateFrame(3, frame_width, frame_height)); |
+ sink_.WaitForEncodedFrame(3); |
+ stats = stats_proxy_->GetStats(); |
+ EXPECT_FALSE(stats.cpu_limited_resolution); |
+ EXPECT_TRUE(stats.bw_limited_resolution); |
+ |
+ vie_encoder_->SetSource(&new_video_source, |
+ VideoSendStream::DegradationPreference::kBalanced); |
+ |
+ new_video_source.IncomingCapturedFrame( |
+ CreateFrame(4, frame_width, frame_height)); |
+ sink_.WaitForEncodedFrame(4); |
+ stats = stats_proxy_->GetStats(); |
+ EXPECT_FALSE(stats.cpu_limited_resolution); |
+ EXPECT_TRUE(stats.bw_limited_resolution); |
+ |
+ // Set adaptation disabled. |
+ vie_encoder_->SetSource( |
+ &new_video_source, |
+ VideoSendStream::DegradationPreference::kMaintainResolution); |
+ |
+ new_video_source.IncomingCapturedFrame( |
+ CreateFrame(5, frame_width, frame_height)); |
+ sink_.WaitForEncodedFrame(5); |
+ stats = stats_proxy_->GetStats(); |
+ EXPECT_FALSE(stats.cpu_limited_resolution); |
+ EXPECT_FALSE(stats.bw_limited_resolution); |
+ |
+ vie_encoder_->Stop(); |
+} |
+ |
TEST_F(ViEEncoderTest, StatsTracksAdaptationStatsWhenSwitchingSource) { |
vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0); |
@@ -727,6 +864,54 @@ TEST_F(ViEEncoderTest, StatsTracksPreferredBitrate) { |
vie_encoder_->Stop(); |
} |
+TEST_F(ViEEncoderTest, ScalingUpAndDownDoesNothingWithMaintainResolution) { |
+ const int kTargetBitrateBps = 100000; |
+ int frame_width = 1280; |
+ int frame_height = 720; |
+ vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0); |
+ |
+ // Expect no scaling to begin with |
+ EXPECT_FALSE(video_source_.sink_wants().max_pixel_count); |
+ EXPECT_FALSE(video_source_.sink_wants().max_pixel_count_step_up); |
+ |
+ // Trigger scale down |
+ vie_encoder_->TriggerQualityLow(); |
+ video_source_.IncomingCapturedFrame( |
+ CreateFrame(1, frame_width, frame_height)); |
+ sink_.WaitForEncodedFrame(1); |
+ |
+ // Expect a scale down. |
+ EXPECT_TRUE(video_source_.sink_wants().max_pixel_count); |
+ EXPECT_LT(*video_source_.sink_wants().max_pixel_count, |
+ frame_width * frame_height); |
+ |
+ // Set adaptation disabled. |
+ test::FrameForwarder new_video_source; |
+ vie_encoder_->SetSource( |
+ &new_video_source, |
+ VideoSendStream::DegradationPreference::kMaintainResolution); |
+ |
+ // Trigger scale down |
+ vie_encoder_->TriggerQualityLow(); |
+ new_video_source.IncomingCapturedFrame( |
+ CreateFrame(2, frame_width, frame_height)); |
+ sink_.WaitForEncodedFrame(2); |
+ |
+ // Expect no scaling |
+ EXPECT_FALSE(new_video_source.sink_wants().max_pixel_count); |
+ |
+ // Trigger scale up |
+ vie_encoder_->TriggerQualityHigh(); |
+ new_video_source.IncomingCapturedFrame( |
+ CreateFrame(3, frame_width, frame_height)); |
+ sink_.WaitForEncodedFrame(3); |
+ |
+ // Expect nothing to change, still no scaling |
+ EXPECT_FALSE(new_video_source.sink_wants().max_pixel_count); |
+ |
+ vie_encoder_->Stop(); |
+} |
+ |
TEST_F(ViEEncoderTest, UMACpuLimitedResolutionInPercent) { |
vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0); |