Rename adaptation api methods, extended vie_encoder unit test.
Use AdaptDown/AdaptUp instead of ScaleDown/ScaleUp, since we may want to adapt using other means than resolution. Also, extend vie_encoder with unit test that actually uses frames scaled to resolution as determined by VideoAdapter, since that seems to be the default implementation. BUG=webrtc:4172 Review-Url: https://codereview.webrtc.org/2652893015 Cr-Commit-Position: refs/heads/master@{#16402}
This commit is contained in:
@ -39,8 +39,6 @@ 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;
|
||||
const ScalingObserverInterface::ScaleReason scale_reason_ =
|
||||
ScalingObserverInterface::ScaleReason::kQuality;
|
||||
|
||||
static VideoEncoder::QpThresholds CodecTypeToDefaultThresholds(
|
||||
VideoCodecType codec_type) {
|
||||
@ -91,16 +89,16 @@ class QualityScaler::CheckQPTask : public rtc::QueuedTask {
|
||||
rtc::SequencedTaskChecker task_checker_;
|
||||
};
|
||||
|
||||
QualityScaler::QualityScaler(ScalingObserverInterface* observer,
|
||||
QualityScaler::QualityScaler(AdaptationObserverInterface* observer,
|
||||
VideoCodecType codec_type)
|
||||
: QualityScaler(observer, CodecTypeToDefaultThresholds(codec_type)) {}
|
||||
|
||||
QualityScaler::QualityScaler(ScalingObserverInterface* observer,
|
||||
QualityScaler::QualityScaler(AdaptationObserverInterface* observer,
|
||||
VideoEncoder::QpThresholds thresholds)
|
||||
: QualityScaler(observer, thresholds, kMeasureMs) {}
|
||||
|
||||
// Protected ctor, should not be called directly.
|
||||
QualityScaler::QualityScaler(ScalingObserverInterface* observer,
|
||||
QualityScaler::QualityScaler(AdaptationObserverInterface* observer,
|
||||
VideoEncoder::QpThresholds thresholds,
|
||||
int64_t sampling_period)
|
||||
: check_qp_task_(nullptr),
|
||||
@ -167,14 +165,14 @@ void QualityScaler::ReportQPLow() {
|
||||
RTC_DCHECK_CALLED_SEQUENTIALLY(&task_checker_);
|
||||
LOG(LS_INFO) << "QP has been low, asking for higher resolution.";
|
||||
ClearSamples();
|
||||
observer_->ScaleUp(scale_reason_);
|
||||
observer_->AdaptUp(AdaptationObserverInterface::AdaptReason::kQuality);
|
||||
}
|
||||
|
||||
void QualityScaler::ReportQPHigh() {
|
||||
RTC_DCHECK_CALLED_SEQUENTIALLY(&task_checker_);
|
||||
LOG(LS_INFO) << "QP has been high , asking for lower resolution.";
|
||||
ClearSamples();
|
||||
observer_->ScaleDown(scale_reason_);
|
||||
observer_->AdaptDown(AdaptationObserverInterface::AdaptReason::kQuality);
|
||||
// If we've scaled down, wait longer before scaling up again.
|
||||
if (fast_rampup_) {
|
||||
fast_rampup_ = false;
|
||||
|
||||
@ -21,18 +21,21 @@
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
// An interface for a class that receives scale up/down requests.
|
||||
class ScalingObserverInterface {
|
||||
// An interface for signaling requests to limit or increase the resolution or
|
||||
// framerate of the captured video stream.
|
||||
class AdaptationObserverInterface {
|
||||
public:
|
||||
enum ScaleReason : size_t { kQuality = 0, kCpu = 1 };
|
||||
// Indicates if the adaptation is due to overuse of the CPU resources, or if
|
||||
// the quality of the encoded frames have dropped too low.
|
||||
enum AdaptReason : size_t { kQuality = 0, kCpu = 1 };
|
||||
static const size_t kScaleReasonSize = 2;
|
||||
// Called to signal that we can handle larger frames.
|
||||
virtual void ScaleUp(ScaleReason reason) = 0;
|
||||
// Called to signal that encoder to scale down.
|
||||
virtual void ScaleDown(ScaleReason reason) = 0;
|
||||
// Called to signal that we can handle larger or more frequent frames.
|
||||
virtual void AdaptUp(AdaptReason reason) = 0;
|
||||
// Called to signal that the source should reduce the resolution or framerate.
|
||||
virtual void AdaptDown(AdaptReason reason) = 0;
|
||||
|
||||
protected:
|
||||
virtual ~ScalingObserverInterface() {}
|
||||
virtual ~AdaptationObserverInterface() {}
|
||||
};
|
||||
|
||||
// QualityScaler runs asynchronously and monitors QP values of encoded frames.
|
||||
@ -43,9 +46,10 @@ class QualityScaler {
|
||||
// Construct a QualityScaler with a given |observer|.
|
||||
// This starts the quality scaler periodically checking what the average QP
|
||||
// has been recently.
|
||||
QualityScaler(ScalingObserverInterface* observer, VideoCodecType codec_type);
|
||||
QualityScaler(AdaptationObserverInterface* observer,
|
||||
VideoCodecType codec_type);
|
||||
// If specific thresholds are desired these can be supplied as |thresholds|.
|
||||
QualityScaler(ScalingObserverInterface* observer,
|
||||
QualityScaler(AdaptationObserverInterface* observer,
|
||||
VideoEncoder::QpThresholds thresholds);
|
||||
virtual ~QualityScaler();
|
||||
// Should be called each time the encoder drops a frame
|
||||
@ -55,7 +59,7 @@ class QualityScaler {
|
||||
|
||||
// The following members declared protected for testing purposes
|
||||
protected:
|
||||
QualityScaler(ScalingObserverInterface* observer,
|
||||
QualityScaler(AdaptationObserverInterface* observer,
|
||||
VideoEncoder::QpThresholds thresholds,
|
||||
int64_t sampling_period);
|
||||
|
||||
@ -68,7 +72,7 @@ class QualityScaler {
|
||||
int64_t GetSamplingPeriodMs() const;
|
||||
|
||||
CheckQPTask* check_qp_task_ GUARDED_BY(&task_checker_);
|
||||
ScalingObserverInterface* const observer_ GUARDED_BY(&task_checker_);
|
||||
AdaptationObserverInterface* const observer_ GUARDED_BY(&task_checker_);
|
||||
rtc::SequencedTaskChecker task_checker_;
|
||||
|
||||
const int64_t sampling_period_ms_;
|
||||
|
||||
@ -26,29 +26,29 @@ static const int kHighQp = 40;
|
||||
static const size_t kDefaultTimeoutMs = 150;
|
||||
} // namespace
|
||||
|
||||
class MockScaleObserver : public ScalingObserverInterface {
|
||||
class MockAdaptationObserver : public AdaptationObserverInterface {
|
||||
public:
|
||||
MockScaleObserver() : event(false, false) {}
|
||||
virtual ~MockScaleObserver() {}
|
||||
MockAdaptationObserver() : event(false, false) {}
|
||||
virtual ~MockAdaptationObserver() {}
|
||||
|
||||
void ScaleUp(ScaleReason r) override {
|
||||
scaled_up++;
|
||||
void AdaptUp(AdaptReason r) override {
|
||||
adapt_up_events_++;
|
||||
event.Set();
|
||||
}
|
||||
void ScaleDown(ScaleReason r) override {
|
||||
scaled_down++;
|
||||
void AdaptDown(AdaptReason r) override {
|
||||
adapt_down_events_++;
|
||||
event.Set();
|
||||
}
|
||||
|
||||
rtc::Event event;
|
||||
int scaled_up = 0;
|
||||
int scaled_down = 0;
|
||||
int adapt_up_events_ = 0;
|
||||
int adapt_down_events_ = 0;
|
||||
};
|
||||
|
||||
// Pass a lower sampling period to speed up the tests.
|
||||
class QualityScalerUnderTest : public QualityScaler {
|
||||
public:
|
||||
explicit QualityScalerUnderTest(ScalingObserverInterface* observer,
|
||||
explicit QualityScalerUnderTest(AdaptationObserverInterface* observer,
|
||||
VideoEncoder::QpThresholds thresholds)
|
||||
: QualityScaler(observer, thresholds, 5) {}
|
||||
};
|
||||
@ -64,7 +64,7 @@ class QualityScalerTest : public ::testing::Test {
|
||||
|
||||
QualityScalerTest()
|
||||
: q_(new rtc::TaskQueue("QualityScalerTestQueue")),
|
||||
observer_(new MockScaleObserver()) {
|
||||
observer_(new MockAdaptationObserver()) {
|
||||
rtc::Event event(false, false);
|
||||
q_->PostTask([this, &event] {
|
||||
qs_ = std::unique_ptr<QualityScaler>(new QualityScalerUnderTest(
|
||||
@ -105,28 +105,28 @@ class QualityScalerTest : public ::testing::Test {
|
||||
|
||||
std::unique_ptr<rtc::TaskQueue> q_;
|
||||
std::unique_ptr<QualityScaler> qs_;
|
||||
std::unique_ptr<MockScaleObserver> observer_;
|
||||
std::unique_ptr<MockAdaptationObserver> observer_;
|
||||
};
|
||||
|
||||
#define DISABLED_TEST(basename, test) TEST_F(basename, DISABLED_##test)
|
||||
DISABLED_TEST(QualityScalerTest, DownscalesAfterContinuousFramedrop) {
|
||||
q_->PostTask([this] { TriggerScale(kScaleDown); });
|
||||
EXPECT_TRUE(observer_->event.Wait(kDefaultTimeoutMs));
|
||||
EXPECT_EQ(1, observer_->scaled_down);
|
||||
EXPECT_EQ(1, observer_->adapt_down_events_);
|
||||
}
|
||||
|
||||
DISABLED_TEST(QualityScalerTest, KeepsScaleAtHighQp) {
|
||||
q_->PostTask([this] { TriggerScale(kKeepScaleAtHighQp); });
|
||||
EXPECT_FALSE(observer_->event.Wait(kDefaultTimeoutMs));
|
||||
EXPECT_EQ(0, observer_->scaled_down);
|
||||
EXPECT_EQ(0, observer_->scaled_up);
|
||||
EXPECT_EQ(0, observer_->adapt_down_events_);
|
||||
EXPECT_EQ(0, observer_->adapt_up_events_);
|
||||
}
|
||||
|
||||
DISABLED_TEST(QualityScalerTest, DownscalesAboveHighQp) {
|
||||
q_->PostTask([this] { TriggerScale(kScaleDownAboveHighQp); });
|
||||
EXPECT_TRUE(observer_->event.Wait(kDefaultTimeoutMs));
|
||||
EXPECT_EQ(1, observer_->scaled_down);
|
||||
EXPECT_EQ(0, observer_->scaled_up);
|
||||
EXPECT_EQ(1, observer_->adapt_down_events_);
|
||||
EXPECT_EQ(0, observer_->adapt_up_events_);
|
||||
}
|
||||
|
||||
DISABLED_TEST(QualityScalerTest, DownscalesAfterTwoThirdsFramedrop) {
|
||||
@ -136,15 +136,15 @@ DISABLED_TEST(QualityScalerTest, DownscalesAfterTwoThirdsFramedrop) {
|
||||
qs_->ReportQP(kHighQp);
|
||||
});
|
||||
EXPECT_TRUE(observer_->event.Wait(kDefaultTimeoutMs));
|
||||
EXPECT_EQ(1, observer_->scaled_down);
|
||||
EXPECT_EQ(0, observer_->scaled_up);
|
||||
EXPECT_EQ(1, observer_->adapt_down_events_);
|
||||
EXPECT_EQ(0, observer_->adapt_up_events_);
|
||||
}
|
||||
|
||||
DISABLED_TEST(QualityScalerTest, DoesNotDownscaleOnNormalQp) {
|
||||
q_->PostTask([this] { TriggerScale(kScaleDownAboveHighQp); });
|
||||
EXPECT_TRUE(observer_->event.Wait(kDefaultTimeoutMs));
|
||||
EXPECT_EQ(1, observer_->scaled_down);
|
||||
EXPECT_EQ(0, observer_->scaled_up);
|
||||
EXPECT_EQ(1, observer_->adapt_down_events_);
|
||||
EXPECT_EQ(0, observer_->adapt_up_events_);
|
||||
}
|
||||
|
||||
DISABLED_TEST(QualityScalerTest, DoesNotDownscaleAfterHalfFramedrop) {
|
||||
@ -153,26 +153,26 @@ DISABLED_TEST(QualityScalerTest, DoesNotDownscaleAfterHalfFramedrop) {
|
||||
qs_->ReportQP(kHighQp);
|
||||
});
|
||||
EXPECT_FALSE(observer_->event.Wait(kDefaultTimeoutMs));
|
||||
EXPECT_EQ(0, observer_->scaled_down);
|
||||
EXPECT_EQ(0, observer_->scaled_up);
|
||||
EXPECT_EQ(0, observer_->adapt_down_events_);
|
||||
EXPECT_EQ(0, observer_->adapt_up_events_);
|
||||
}
|
||||
|
||||
DISABLED_TEST(QualityScalerTest, UpscalesAfterLowQp) {
|
||||
q_->PostTask([this] { TriggerScale(kScaleUp); });
|
||||
EXPECT_TRUE(observer_->event.Wait(kDefaultTimeoutMs));
|
||||
EXPECT_EQ(0, observer_->scaled_down);
|
||||
EXPECT_EQ(1, observer_->scaled_up);
|
||||
EXPECT_EQ(0, observer_->adapt_down_events_);
|
||||
EXPECT_EQ(1, observer_->adapt_up_events_);
|
||||
}
|
||||
|
||||
DISABLED_TEST(QualityScalerTest, ScalesDownAndBackUp) {
|
||||
q_->PostTask([this] { TriggerScale(kScaleDown); });
|
||||
EXPECT_TRUE(observer_->event.Wait(kDefaultTimeoutMs));
|
||||
EXPECT_EQ(1, observer_->scaled_down);
|
||||
EXPECT_EQ(0, observer_->scaled_up);
|
||||
EXPECT_EQ(1, observer_->adapt_down_events_);
|
||||
EXPECT_EQ(0, observer_->adapt_up_events_);
|
||||
q_->PostTask([this] { TriggerScale(kScaleUp); });
|
||||
EXPECT_TRUE(observer_->event.Wait(kDefaultTimeoutMs));
|
||||
EXPECT_EQ(1, observer_->scaled_down);
|
||||
EXPECT_EQ(1, observer_->scaled_up);
|
||||
EXPECT_EQ(1, observer_->adapt_down_events_);
|
||||
EXPECT_EQ(1, observer_->adapt_up_events_);
|
||||
}
|
||||
#undef DISABLED_TEST
|
||||
} // namespace webrtc
|
||||
|
||||
Reference in New Issue
Block a user