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:
@ -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) {
|
||||
|
@ -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
|
||||
|
Reference in New Issue
Block a user