Minor changes to QualityScaler.
- remove duplicated test, DoesNotDownscaleOnNormalQp - add test, KeepsScaleOnNormalQp - make member const Bug: none Change-Id: I6599e5eb0d59b67b0af55701accea25a80c7c875 Reviewed-on: https://webrtc-review.googlesource.com/70203 Commit-Queue: Åsa Persson <asapersson@webrtc.org> Reviewed-by: Rasmus Brandt <brandtr@webrtc.org> Cr-Commit-Position: refs/heads/master@{#22935}
This commit is contained in:
@ -73,15 +73,15 @@ QualityScaler::QualityScaler(AdaptationObserverInterface* observer,
|
||||
// Protected ctor, should not be called directly.
|
||||
QualityScaler::QualityScaler(AdaptationObserverInterface* observer,
|
||||
VideoEncoder::QpThresholds thresholds,
|
||||
int64_t sampling_period)
|
||||
int64_t sampling_period_ms)
|
||||
: check_qp_task_(nullptr),
|
||||
observer_(observer),
|
||||
sampling_period_ms_(sampling_period),
|
||||
thresholds_(thresholds),
|
||||
sampling_period_ms_(sampling_period_ms),
|
||||
fast_rampup_(true),
|
||||
// Arbitrarily choose size based on 30 fps for 5 seconds.
|
||||
average_qp_(5 * 30),
|
||||
framedrop_percent_(5 * 30),
|
||||
thresholds_(thresholds) {
|
||||
framedrop_percent_(5 * 30) {
|
||||
RTC_DCHECK_CALLED_SEQUENTIALLY(&task_checker_);
|
||||
RTC_DCHECK(observer_ != nullptr);
|
||||
check_qp_task_ = new CheckQPTask(this);
|
||||
@ -116,14 +116,15 @@ void QualityScaler::CheckQP() {
|
||||
// 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 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) {
|
||||
RTC_LOG(LS_INFO) << "Reporting high QP, framedrop percent " << *drop_rate;
|
||||
ReportQPHigh();
|
||||
return;
|
||||
}
|
||||
|
||||
@ -49,16 +49,16 @@ class QualityScaler {
|
||||
QualityScaler(AdaptationObserverInterface* observer,
|
||||
VideoEncoder::QpThresholds thresholds);
|
||||
virtual ~QualityScaler();
|
||||
// Should be called each time the encoder drops a frame
|
||||
// Should be called each time the encoder drops a frame.
|
||||
void ReportDroppedFrame();
|
||||
// Inform the QualityScaler of the last seen QP.
|
||||
void ReportQP(int qp);
|
||||
|
||||
// The following members declared protected for testing purposes
|
||||
// The following members declared protected for testing purposes.
|
||||
protected:
|
||||
QualityScaler(AdaptationObserverInterface* observer,
|
||||
VideoEncoder::QpThresholds thresholds,
|
||||
int64_t sampling_period);
|
||||
int64_t sampling_period_ms);
|
||||
|
||||
private:
|
||||
class CheckQPTask;
|
||||
@ -72,12 +72,11 @@ class QualityScaler {
|
||||
AdaptationObserverInterface* const observer_ RTC_GUARDED_BY(&task_checker_);
|
||||
rtc::SequencedTaskChecker task_checker_;
|
||||
|
||||
const VideoEncoder::QpThresholds thresholds_;
|
||||
const int64_t sampling_period_ms_;
|
||||
bool fast_rampup_ RTC_GUARDED_BY(&task_checker_);
|
||||
MovingAverage average_qp_ RTC_GUARDED_BY(&task_checker_);
|
||||
MovingAverage framedrop_percent_ RTC_GUARDED_BY(&task_checker_);
|
||||
|
||||
VideoEncoder::QpThresholds thresholds_ RTC_GUARDED_BY(&task_checker_);
|
||||
};
|
||||
} // namespace webrtc
|
||||
|
||||
|
||||
@ -21,8 +21,8 @@ namespace webrtc {
|
||||
namespace {
|
||||
static const int kFramerate = 30;
|
||||
static const int kLowQp = 15;
|
||||
static const int kLowQpThreshold = 18;
|
||||
static const int kHighQp = 40;
|
||||
static const int kMinFramesNeededToScale = 60; // From quality_scaler.cc.
|
||||
static const size_t kDefaultTimeoutMs = 150;
|
||||
} // namespace
|
||||
|
||||
@ -66,6 +66,7 @@ class QualityScalerUnderTest : public QualityScaler {
|
||||
class QualityScalerTest : public ::testing::Test {
|
||||
protected:
|
||||
enum ScaleDirection {
|
||||
kKeepScaleAboveLowQp,
|
||||
kKeepScaleAtHighQp,
|
||||
kScaleDown,
|
||||
kScaleDownAboveHighQp,
|
||||
@ -77,8 +78,8 @@ class QualityScalerTest : public ::testing::Test {
|
||||
observer_(new MockAdaptationObserver()) {
|
||||
DO_SYNC(q_, {
|
||||
qs_ = std::unique_ptr<QualityScaler>(new QualityScalerUnderTest(
|
||||
observer_.get(),
|
||||
VideoEncoder::QpThresholds(kLowQpThreshold, kHighQp)));});
|
||||
observer_.get(), VideoEncoder::QpThresholds(kLowQp, kHighQp)));
|
||||
});
|
||||
}
|
||||
|
||||
~QualityScalerTest() {
|
||||
@ -88,6 +89,9 @@ class QualityScalerTest : public ::testing::Test {
|
||||
void TriggerScale(ScaleDirection scale_direction) {
|
||||
for (int i = 0; i < kFramerate * 5; ++i) {
|
||||
switch (scale_direction) {
|
||||
case kKeepScaleAboveLowQp:
|
||||
qs_->ReportQP(kLowQp + 1);
|
||||
break;
|
||||
case kScaleUp:
|
||||
qs_->ReportQP(kLowQp);
|
||||
break;
|
||||
@ -113,6 +117,7 @@ TEST_F(QualityScalerTest, DownscalesAfterContinuousFramedrop) {
|
||||
DO_SYNC(q_, { TriggerScale(kScaleDown); });
|
||||
EXPECT_TRUE(observer_->event.Wait(kDefaultTimeoutMs));
|
||||
EXPECT_EQ(1, observer_->adapt_down_events_);
|
||||
EXPECT_EQ(0, observer_->adapt_up_events_);
|
||||
}
|
||||
|
||||
TEST_F(QualityScalerTest, KeepsScaleAtHighQp) {
|
||||
@ -142,13 +147,6 @@ TEST_F(QualityScalerTest, DownscalesAfterTwoThirdsFramedrop) {
|
||||
EXPECT_EQ(0, observer_->adapt_up_events_);
|
||||
}
|
||||
|
||||
TEST_F(QualityScalerTest, DoesNotDownscaleOnNormalQp) {
|
||||
DO_SYNC(q_, { TriggerScale(kScaleDownAboveHighQp); });
|
||||
EXPECT_TRUE(observer_->event.Wait(kDefaultTimeoutMs));
|
||||
EXPECT_EQ(1, observer_->adapt_down_events_);
|
||||
EXPECT_EQ(0, observer_->adapt_up_events_);
|
||||
}
|
||||
|
||||
TEST_F(QualityScalerTest, DoesNotDownscaleAfterHalfFramedrop) {
|
||||
DO_SYNC(q_, {
|
||||
for (int i = 0; i < kFramerate * 5; ++i) {
|
||||
@ -161,6 +159,13 @@ TEST_F(QualityScalerTest, DoesNotDownscaleAfterHalfFramedrop) {
|
||||
EXPECT_EQ(0, observer_->adapt_up_events_);
|
||||
}
|
||||
|
||||
TEST_F(QualityScalerTest, KeepsScaleOnNormalQp) {
|
||||
DO_SYNC(q_, { TriggerScale(kKeepScaleAboveLowQp); });
|
||||
EXPECT_FALSE(observer_->event.Wait(kDefaultTimeoutMs));
|
||||
EXPECT_EQ(0, observer_->adapt_down_events_);
|
||||
EXPECT_EQ(0, observer_->adapt_up_events_);
|
||||
}
|
||||
|
||||
TEST_F(QualityScalerTest, UpscalesAfterLowQp) {
|
||||
DO_SYNC(q_, { TriggerScale(kScaleUp); });
|
||||
EXPECT_TRUE(observer_->event.Wait(kDefaultTimeoutMs));
|
||||
@ -181,22 +186,49 @@ TEST_F(QualityScalerTest, ScalesDownAndBackUp) {
|
||||
|
||||
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);
|
||||
}
|
||||
});
|
||||
// Not enough frames to make a decision.
|
||||
for (int i = 0; i < kMinFramesNeededToScale - 1; ++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);
|
||||
}
|
||||
});
|
||||
// Send 1 more. Enough frames observed, should result in an adapt request.
|
||||
qs_->ReportQP(kLowQp);
|
||||
});
|
||||
EXPECT_TRUE(observer_->event.Wait(kDefaultTimeoutMs));
|
||||
EXPECT_EQ(0, observer_->adapt_down_events_);
|
||||
EXPECT_EQ(1, observer_->adapt_up_events_);
|
||||
|
||||
// Samples should be cleared after an adapt request.
|
||||
DO_SYNC(q_, {
|
||||
// Not enough frames to make a decision.
|
||||
qs_->ReportQP(kLowQp);
|
||||
});
|
||||
EXPECT_FALSE(observer_->event.Wait(kDefaultTimeoutMs));
|
||||
EXPECT_EQ(0, observer_->adapt_down_events_);
|
||||
EXPECT_EQ(1, observer_->adapt_up_events_);
|
||||
}
|
||||
|
||||
TEST_F(QualityScalerTest, ScalesDownAndBackUpWithMinFramesNeeded) {
|
||||
DO_SYNC(q_, {
|
||||
for (int i = 0; i < kMinFramesNeededToScale; ++i) {
|
||||
qs_->ReportQP(kHighQp + 1);
|
||||
}
|
||||
});
|
||||
EXPECT_TRUE(observer_->event.Wait(kDefaultTimeoutMs));
|
||||
EXPECT_EQ(1, observer_->adapt_down_events_);
|
||||
EXPECT_EQ(0, observer_->adapt_up_events_);
|
||||
// Samples cleared.
|
||||
DO_SYNC(q_, {
|
||||
for (int i = 0; i < kMinFramesNeededToScale; ++i) {
|
||||
qs_->ReportQP(kLowQp);
|
||||
}
|
||||
});
|
||||
EXPECT_TRUE(observer_->event.Wait(kDefaultTimeoutMs));
|
||||
EXPECT_EQ(1, observer_->adapt_down_events_);
|
||||
EXPECT_EQ(1, observer_->adapt_up_events_);
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
||||
#undef DO_SYNC
|
||||
|
||||
Reference in New Issue
Block a user