Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(884)

Unified Diff: webrtc/video/vie_encoder_unittest.cc

Issue 2918143003: Set overuse detector max frame interval based on target frame rate. (Closed)
Patch Set: Rebase Created 3 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « webrtc/video/vie_encoder.cc ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: webrtc/video/vie_encoder_unittest.cc
diff --git a/webrtc/video/vie_encoder_unittest.cc b/webrtc/video/vie_encoder_unittest.cc
index a016fa9313aac60cddc2f6c7a55df4245aac9b71..b143e4d54624b405419fd42bc22cf97d66d10590 100644
--- a/webrtc/video/vie_encoder_unittest.cc
+++ b/webrtc/video/vie_encoder_unittest.cc
@@ -48,6 +48,7 @@ const size_t kMaxPayloadLength = 1440;
const int kTargetBitrateBps = 1000000;
const int kLowTargetBitrateBps = kTargetBitrateBps / 10;
const int kMaxInitialFramedrop = 4;
+const int kDefaultFramerate = 30;
class TestBuffer : public webrtc::I420Buffer {
public:
@@ -63,6 +64,35 @@ class TestBuffer : public webrtc::I420Buffer {
rtc::Event* const event_;
};
+class CpuOveruseDetectorProxy : public OveruseFrameDetector {
+ public:
+ CpuOveruseDetectorProxy(const CpuOveruseOptions& options,
+ AdaptationObserverInterface* overuse_observer,
+ EncodedFrameObserver* encoder_timing_,
+ CpuOveruseMetricsObserver* metrics_observer)
+ : OveruseFrameDetector(options,
+ overuse_observer,
+ encoder_timing_,
+ metrics_observer),
+ last_target_framerate_fps_(-1) {}
+ virtual ~CpuOveruseDetectorProxy() {}
+
+ void OnTargetFramerateUpdated(int framerate_fps) override {
+ rtc::CritScope cs(&lock_);
+ last_target_framerate_fps_ = framerate_fps;
+ OveruseFrameDetector::OnTargetFramerateUpdated(framerate_fps);
+ }
+
+ int GetLastTargetFramerate() {
+ rtc::CritScope cs(&lock_);
+ return last_target_framerate_fps_;
+ }
+
+ private:
+ rtc::CriticalSection lock_;
+ int last_target_framerate_fps_ GUARDED_BY(lock_);
+};
+
class ViEEncoderUnderTest : public ViEEncoder {
public:
ViEEncoderUnderTest(SendStatisticsProxy* stats_proxy,
@@ -71,7 +101,13 @@ class ViEEncoderUnderTest : public ViEEncoder {
stats_proxy,
settings,
nullptr /* pre_encode_callback */,
- nullptr /* encoder_timing */) {}
+ nullptr /* encoder_timing */,
+ std::unique_ptr<OveruseFrameDetector>(
+ overuse_detector_proxy_ = new CpuOveruseDetectorProxy(
+ GetCpuOveruseOptions(settings.full_overuse_time),
+ this,
+ nullptr,
+ stats_proxy))) {}
void PostTaskAndWait(bool down, AdaptReason reason) {
rtc::Event event(false, false);
@@ -99,14 +135,17 @@ class ViEEncoderUnderTest : public ViEEncoder {
void TriggerQualityLow() { PostTaskAndWait(true, AdaptReason::kQuality); }
void TriggerQualityHigh() { PostTaskAndWait(false, AdaptReason::kQuality); }
+
+ CpuOveruseDetectorProxy* overuse_detector_proxy_;
};
class VideoStreamFactory
: public VideoEncoderConfig::VideoStreamFactoryInterface {
public:
- explicit VideoStreamFactory(size_t num_temporal_layers)
- : num_temporal_layers_(num_temporal_layers) {
+ explicit VideoStreamFactory(size_t num_temporal_layers, int framerate)
+ : num_temporal_layers_(num_temporal_layers), framerate_(framerate) {
EXPECT_GT(num_temporal_layers, 0u);
+ EXPECT_GT(framerate, 0);
}
private:
@@ -118,10 +157,13 @@ class VideoStreamFactory
test::CreateVideoStreams(width, height, encoder_config);
for (VideoStream& stream : streams) {
stream.temporal_layer_thresholds_bps.resize(num_temporal_layers_ - 1);
+ stream.max_framerate = framerate_;
}
return streams;
}
+
const size_t num_temporal_layers_;
+ const int framerate_;
};
class AdaptingFrameForwarder : public test::FrameForwarder {
@@ -264,7 +306,8 @@ class ViEEncoderTest : public ::testing::Test {
video_encoder_config.number_of_streams = num_streams;
video_encoder_config.max_bitrate_bps = kTargetBitrateBps;
video_encoder_config.video_stream_factory =
- new rtc::RefCountedObject<VideoStreamFactory>(num_temporal_layers);
+ new rtc::RefCountedObject<VideoStreamFactory>(num_temporal_layers,
+ kDefaultFramerate);
ConfigureEncoder(std::move(video_encoder_config), nack_enabled);
}
@@ -2027,6 +2070,164 @@ TEST_F(ViEEncoderTest, CallsBitrateObserver) {
vie_encoder_->Stop();
}
+TEST_F(ViEEncoderTest, OveruseDetectorUpdatedOnReconfigureAndAdaption) {
+ const int kFrameWidth = 1280;
+ const int kFrameHeight = 720;
+ const int kFramerate = 24;
+
+ vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
+ test::FrameForwarder source;
+ vie_encoder_->SetSource(
+ &source, VideoSendStream::DegradationPreference::kMaintainResolution);
+
+ // Insert a single frame, triggering initial configuration.
+ source.IncomingCapturedFrame(CreateFrame(1, kFrameWidth, kFrameHeight));
+ vie_encoder_->WaitUntilTaskQueueIsIdle();
+
+ EXPECT_EQ(vie_encoder_->overuse_detector_proxy_->GetLastTargetFramerate(),
+ kDefaultFramerate);
+
+ // Trigger reconfigure encoder (without resetting the entire instance).
+ VideoEncoderConfig video_encoder_config;
+ video_encoder_config.max_bitrate_bps = kTargetBitrateBps;
+ video_encoder_config.number_of_streams = 1;
+ video_encoder_config.video_stream_factory =
+ new rtc::RefCountedObject<VideoStreamFactory>(1, kFramerate);
+ vie_encoder_->ConfigureEncoder(std::move(video_encoder_config),
+ kMaxPayloadLength, false);
+ vie_encoder_->WaitUntilTaskQueueIsIdle();
+
+ // Detector should be updated with fps limit from codec config.
+ EXPECT_EQ(vie_encoder_->overuse_detector_proxy_->GetLastTargetFramerate(),
+ kFramerate);
+
+ // Trigger overuse, max framerate should be reduced.
+ VideoSendStream::Stats stats = stats_proxy_->GetStats();
+ stats.input_frame_rate = kFramerate;
+ stats_proxy_->SetMockStats(stats);
+ vie_encoder_->TriggerCpuOveruse();
+ vie_encoder_->WaitUntilTaskQueueIsIdle();
+ int adapted_framerate =
+ vie_encoder_->overuse_detector_proxy_->GetLastTargetFramerate();
+ EXPECT_LT(adapted_framerate, kFramerate);
+
+ // Trigger underuse, max framerate should go back to codec configured fps.
+ // Set extra low fps, to make sure it's actually reset, not just incremented.
+ stats = stats_proxy_->GetStats();
+ stats.input_frame_rate = adapted_framerate / 2;
+ stats_proxy_->SetMockStats(stats);
+ vie_encoder_->TriggerCpuNormalUsage();
+ vie_encoder_->WaitUntilTaskQueueIsIdle();
+ EXPECT_EQ(vie_encoder_->overuse_detector_proxy_->GetLastTargetFramerate(),
+ kFramerate);
+
+ vie_encoder_->Stop();
+}
+
+TEST_F(ViEEncoderTest, OveruseDetectorUpdatedRespectsFramerateAfterUnderuse) {
+ const int kFrameWidth = 1280;
+ const int kFrameHeight = 720;
+ const int kLowFramerate = 15;
+ const int kHighFramerate = 25;
+
+ vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
+ test::FrameForwarder source;
+ vie_encoder_->SetSource(
+ &source, VideoSendStream::DegradationPreference::kMaintainResolution);
+
+ // Trigger initial configuration.
+ VideoEncoderConfig video_encoder_config;
+ video_encoder_config.max_bitrate_bps = kTargetBitrateBps;
+ video_encoder_config.number_of_streams = 1;
+ video_encoder_config.video_stream_factory =
+ new rtc::RefCountedObject<VideoStreamFactory>(1, kLowFramerate);
+ source.IncomingCapturedFrame(CreateFrame(1, kFrameWidth, kFrameHeight));
+ vie_encoder_->ConfigureEncoder(std::move(video_encoder_config),
+ kMaxPayloadLength, false);
+ vie_encoder_->WaitUntilTaskQueueIsIdle();
+
+ EXPECT_EQ(vie_encoder_->overuse_detector_proxy_->GetLastTargetFramerate(),
+ kLowFramerate);
+
+ // Trigger overuse, max framerate should be reduced.
+ VideoSendStream::Stats stats = stats_proxy_->GetStats();
+ stats.input_frame_rate = kLowFramerate;
+ stats_proxy_->SetMockStats(stats);
+ vie_encoder_->TriggerCpuOveruse();
+ vie_encoder_->WaitUntilTaskQueueIsIdle();
+ int adapted_framerate =
+ vie_encoder_->overuse_detector_proxy_->GetLastTargetFramerate();
+ EXPECT_LT(adapted_framerate, kLowFramerate);
+
+ // Reconfigure the encoder with a new (higher max framerate), max fps should
+ // still respect the adaptation.
+ video_encoder_config.video_stream_factory =
+ new rtc::RefCountedObject<VideoStreamFactory>(1, kHighFramerate);
+ source.IncomingCapturedFrame(CreateFrame(1, kFrameWidth, kFrameHeight));
+ vie_encoder_->ConfigureEncoder(std::move(video_encoder_config),
+ kMaxPayloadLength, false);
+ vie_encoder_->WaitUntilTaskQueueIsIdle();
+
+ EXPECT_EQ(vie_encoder_->overuse_detector_proxy_->GetLastTargetFramerate(),
+ adapted_framerate);
+
+ // Trigger underuse, max framerate should go back to codec configured fps.
+ stats = stats_proxy_->GetStats();
+ stats.input_frame_rate = adapted_framerate;
+ stats_proxy_->SetMockStats(stats);
+ vie_encoder_->TriggerCpuNormalUsage();
+ vie_encoder_->WaitUntilTaskQueueIsIdle();
+ EXPECT_EQ(vie_encoder_->overuse_detector_proxy_->GetLastTargetFramerate(),
+ kHighFramerate);
+
+ vie_encoder_->Stop();
+}
+
+TEST_F(ViEEncoderTest, OveruseDetectorUpdatedOnDegradationPreferenceChange) {
+ const int kFrameWidth = 1280;
+ const int kFrameHeight = 720;
+ const int kFramerate = 24;
+
+ vie_encoder_->OnBitrateUpdated(kTargetBitrateBps, 0, 0);
+ test::FrameForwarder source;
+ vie_encoder_->SetSource(
+ &source, VideoSendStream::DegradationPreference::kMaintainResolution);
+
+ // Trigger initial configuration.
+ VideoEncoderConfig video_encoder_config;
+ video_encoder_config.max_bitrate_bps = kTargetBitrateBps;
+ video_encoder_config.number_of_streams = 1;
+ video_encoder_config.video_stream_factory =
+ new rtc::RefCountedObject<VideoStreamFactory>(1, kFramerate);
+ source.IncomingCapturedFrame(CreateFrame(1, kFrameWidth, kFrameHeight));
+ vie_encoder_->ConfigureEncoder(std::move(video_encoder_config),
+ kMaxPayloadLength, false);
+ vie_encoder_->WaitUntilTaskQueueIsIdle();
+
+ EXPECT_EQ(vie_encoder_->overuse_detector_proxy_->GetLastTargetFramerate(),
+ kFramerate);
+
+ // Trigger overuse, max framerate should be reduced.
+ VideoSendStream::Stats stats = stats_proxy_->GetStats();
+ stats.input_frame_rate = kFramerate;
+ stats_proxy_->SetMockStats(stats);
+ vie_encoder_->TriggerCpuOveruse();
+ vie_encoder_->WaitUntilTaskQueueIsIdle();
+ int adapted_framerate =
+ vie_encoder_->overuse_detector_proxy_->GetLastTargetFramerate();
+ EXPECT_LT(adapted_framerate, kFramerate);
+
+ // Change degradation preference to not enable framerate scaling. Target
+ // framerate should be changed to codec defined limit.
+ vie_encoder_->SetSource(
+ &source, VideoSendStream::DegradationPreference::kMaintainFramerate);
+ vie_encoder_->WaitUntilTaskQueueIsIdle();
+ EXPECT_EQ(vie_encoder_->overuse_detector_proxy_->GetLastTargetFramerate(),
+ kFramerate);
+
+ vie_encoder_->Stop();
+}
+
TEST_F(ViEEncoderTest, DropsFramesAndScalesWhenBitrateIsTooLow) {
const int kTooLowBitrateForFrameSizeBps = 10000;
vie_encoder_->OnBitrateUpdated(kTooLowBitrateForFrameSizeBps, 0, 0);
« no previous file with comments | « webrtc/video/vie_encoder.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698