diff --git a/webrtc/modules/video_coding/utility/quality_scaler.cc b/webrtc/modules/video_coding/utility/quality_scaler.cc index ff22862bb5..f1623cb6e9 100644 --- a/webrtc/modules/video_coding/utility/quality_scaler.cc +++ b/webrtc/modules/video_coding/utility/quality_scaler.cc @@ -39,6 +39,7 @@ static const int kHighH264QpThreshold = 37; // bitstream range of [0, 127] and not the user-level range of [0,63]. static const int kLowVp8QpThreshold = 29; static const int kHighVp8QpThreshold = 95; +static const int kMinFramesNeededToScale = 2 * 30; static VideoEncoder::QpThresholds CodecTypeToDefaultThresholds( VideoCodecType codec_type) { @@ -142,6 +143,12 @@ void QualityScaler::CheckQP() { RTC_DCHECK_CALLED_SEQUENTIALLY(&task_checker_); // Should be set through InitEncode -> Should be set by now. RTC_DCHECK_GE(thresholds_.low, 0); + + // If we have not observed at least this many frames we can't + // make a good scaling decision. + if (framedrop_percent_.size() < kMinFramesNeededToScale) + return; + // Check if we should scale down due to high frame drop. const rtc::Optional drop_rate = framedrop_percent_.GetAverage(); if (drop_rate && *drop_rate >= kFramedropPercentThreshold) { diff --git a/webrtc/modules/video_coding/utility/quality_scaler_unittest.cc b/webrtc/modules/video_coding/utility/quality_scaler_unittest.cc index 32d0aa9aea..93b5fcd431 100644 --- a/webrtc/modules/video_coding/utility/quality_scaler_unittest.cc +++ b/webrtc/modules/video_coding/utility/quality_scaler_unittest.cc @@ -131,9 +131,11 @@ TEST_F(QualityScalerTest, DownscalesAboveHighQp) { TEST_F(QualityScalerTest, DownscalesAfterTwoThirdsFramedrop) { DO_SYNC(q_, { - qs_->ReportDroppedFrame(); - qs_->ReportDroppedFrame(); - qs_->ReportQP(kHighQp); + for (int i = 0; i < kFramerate * 5; ++i) { + qs_->ReportDroppedFrame(); + qs_->ReportDroppedFrame(); + qs_->ReportQP(kHighQp); + } }); EXPECT_TRUE(observer_->event.Wait(kDefaultTimeoutMs)); EXPECT_EQ(1, observer_->adapt_down_events_); @@ -149,8 +151,10 @@ TEST_F(QualityScalerTest, DoesNotDownscaleOnNormalQp) { TEST_F(QualityScalerTest, DoesNotDownscaleAfterHalfFramedrop) { DO_SYNC(q_, { - qs_->ReportDroppedFrame(); - qs_->ReportQP(kHighQp); + for (int i = 0; i < kFramerate * 5; ++i) { + qs_->ReportDroppedFrame(); + qs_->ReportQP(kHighQp); + } }); EXPECT_FALSE(observer_->event.Wait(kDefaultTimeoutMs)); EXPECT_EQ(0, observer_->adapt_down_events_); @@ -174,5 +178,25 @@ TEST_F(QualityScalerTest, ScalesDownAndBackUp) { EXPECT_EQ(1, observer_->adapt_down_events_); EXPECT_EQ(1, observer_->adapt_up_events_); } + +TEST_F(QualityScalerTest, DoesNotScaleUntilEnoughFramesObserved) { + DO_SYNC(q_, { + // Send 30 frames. This should not be enough to make a decision. + for (int i = 0; i < kFramerate; ++i) { + qs_->ReportQP(kLowQp); + } + }); + EXPECT_FALSE(observer_->event.Wait(kDefaultTimeoutMs)); + DO_SYNC(q_, { + // Send 30 more. This should result in an adapt request as + // enough frames have now been observed. + for (int i = 0; i < kFramerate; ++i) { + qs_->ReportQP(kLowQp); + } + }); + EXPECT_TRUE(observer_->event.Wait(kDefaultTimeoutMs)); + EXPECT_EQ(0, observer_->adapt_down_events_); + EXPECT_EQ(1, observer_->adapt_up_events_); +} } // namespace webrtc #undef DO_SYNC