Index: webrtc/video/vie_encoder_unittest.cc |
diff --git a/webrtc/video/vie_encoder_unittest.cc b/webrtc/video/vie_encoder_unittest.cc |
index 9f4fdc47e33094d3577dbe4f05eb226bfb37a173..8ba8a011c4c8889da0aa84d05ec4fa5678780fb4 100644 |
--- a/webrtc/video/vie_encoder_unittest.cc |
+++ b/webrtc/video/vie_encoder_unittest.cc |
@@ -22,7 +22,12 @@ |
namespace webrtc { |
+using DegredationPreference = VideoSendStream::DegradationPreference; |
+ |
namespace { |
+// Copied from vie_encoder.cc. Must be kept in sync. |
+static const int kMaxCpuDowngrades = 2; |
+ |
class TestBuffer : public webrtc::I420Buffer { |
public: |
TestBuffer(rtc::Event* event, int width, int height) |
@@ -39,32 +44,31 @@ class TestBuffer : public webrtc::I420Buffer { |
class ViEEncoderUnderTest : public ViEEncoder { |
public: |
- ViEEncoderUnderTest( |
- SendStatisticsProxy* stats_proxy, |
- const webrtc::VideoSendStream::Config::EncoderSettings& settings) |
+ using ScalingObserverInterface::ScaleReason; |
+ 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, kCpu); } |
+ |
+ void TriggerCpuNormalUsage() { PostTaskAndWait(false, kCpu); } |
+ |
+ void TriggerQualityLow() { PostTaskAndWait(true, kQuality); } |
+ |
+ void TriggerQualityHigh() { PostTaskAndWait(false, kQuality); } |
}; |
} // namespace |
@@ -134,6 +138,10 @@ class ViEEncoderTest : public ::testing::Test { |
block_next_encode_ = true; |
} |
+ QualityScaler::Settings GetQPThresholds() const override { |
+ return QualityScaler::Settings(true, 1, 2); |
+ } |
+ |
void ContinueEncode() { continue_encode_event_.Set(); } |
void CheckLastTimeStampsMatch(int64_t ntp_time_ms, |
@@ -411,7 +419,7 @@ TEST_F(ViEEncoderTest, SinkWantsFromOveruseDetector) { |
// Trigger CPU overuse kMaxCpuDowngrades times. Every time, ViEEncoder should |
// request lower resolution. |
- for (int i = 1; i <= ViEEncoder::kMaxCpuDowngrades; ++i) { |
+ for (int i = 1; i <= kMaxCpuDowngrades; ++i) { |
video_source_.IncomingCapturedFrame( |
CreateFrame(i, frame_width, frame_height)); |
sink_.WaitForEncodedFrame(i); |
@@ -427,12 +435,12 @@ 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( |
- ViEEncoder::kMaxCpuDowngrades + 1, frame_width, frame_height)); |
- sink_.WaitForEncodedFrame(ViEEncoder::kMaxCpuDowngrades + 1); |
+ video_source_.IncomingCapturedFrame( |
+ CreateFrame(kMaxCpuDowngrades + 1, frame_width, frame_height)); |
+ sink_.WaitForEncodedFrame(kMaxCpuDowngrades + 1); |
vie_encoder_->TriggerCpuOveruse(); |
EXPECT_EQ(video_source_.sink_wants().max_pixel_count, |
current_wants.max_pixel_count); |
@@ -533,6 +541,68 @@ TEST_F(ViEEncoderTest, StatsTracksAdaptationStats) { |
vie_encoder_->Stop(); |
} |
+TEST_F(ViEEncoderTest, SwitchingSourceKeepsAdaptation) { |
+ 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) { |
const int kTargetBitrateBps = 100000; |
vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0); |
@@ -595,6 +665,64 @@ TEST_F(ViEEncoderTest, StatsTracksAdaptationStatsWhenSwitchingSource) { |
vie_encoder_->Stop(); |
} |
+TEST_F(ViEEncoderTest, StatsTracksQualityAdaptationStatsWhenSwitchingSource) { |
+ const int kTargetBitrateBps = 100000; |
+ vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0); |
+ |
+ // Trigger CPU overuse. |
+ vie_encoder_->TriggerQualityLow(); |
+ 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_TRUE(stats.bw_limited_resolution); |
+ |
+ // 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_TRUE(stats.bw_limited_resolution); |
+ |
+ // Set adaptation disabled. |
+ vie_encoder_->SetSource( |
+ &new_video_source, |
+ VideoSendStream::DegradationPreference::kMaintainResolution); |
+ |
+ new_video_source.IncomingCapturedFrame( |
+ CreateFrame(3, frame_width, frame_height)); |
+ sink_.WaitForEncodedFrame(3); |
+ stats = stats_proxy_->GetStats(); |
+ EXPECT_FALSE(stats.bw_limited_resolution); |
+ |
+ // Switch back the source with adaptation enabled. |
+ vie_encoder_->SetSource(&video_source_, |
+ VideoSendStream::DegradationPreference::kBalanced); |
+ video_source_.IncomingCapturedFrame( |
+ CreateFrame(4, frame_width, frame_height)); |
+ sink_.WaitForEncodedFrame(4); |
+ stats = stats_proxy_->GetStats(); |
+ EXPECT_TRUE(stats.bw_limited_resolution); |
+ |
+ // Trigger CPU normal usage. |
+ vie_encoder_->TriggerQualityHigh(); |
+ video_source_.IncomingCapturedFrame( |
+ CreateFrame(5, frame_width, frame_height)); |
+ sink_.WaitForEncodedFrame(5); |
+ stats = stats_proxy_->GetStats(); |
+ EXPECT_FALSE(stats.bw_limited_resolution); |
+ |
+ vie_encoder_->Stop(); |
+} |
+ |
TEST_F(ViEEncoderTest, UMACpuLimitedResolutionInPercent) { |
const int kTargetBitrateBps = 100000; |
vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0); |