Make sure we observe enough frames before scaling.

If the encoder takes a long time to start up and emit frames the polling
interval of the quality scaler would get out of sync. This causes it to
sometimes make scaling decisions based on only a handful of frames.
This CL ensures that we have observed some minimum number of frames
before deciding to scale up or down.

BUG=b/36734056

Review-Url: https://codereview.webrtc.org/2789483002
Cr-Commit-Position: refs/heads/master@{#17523}
This commit is contained in:
kthelgason
2017-04-04 02:31:42 -07:00
committed by Commit bot
parent 751c9dc904
commit 55a0135484
2 changed files with 36 additions and 5 deletions

View File

@ -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<int> drop_rate = framedrop_percent_.GetAverage();
if (drop_rate && *drop_rate >= kFramedropPercentThreshold) {

View File

@ -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