Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(13)

Unified Diff: webrtc/modules/video_coding/utility/quality_scaler_unittest.cc

Issue 2398963003: Move usage of QualityScaler to ViEEncoder. (Closed)
Patch Set: rebase Created 4 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: webrtc/modules/video_coding/utility/quality_scaler_unittest.cc
diff --git a/webrtc/modules/video_coding/utility/quality_scaler_unittest.cc b/webrtc/modules/video_coding/utility/quality_scaler_unittest.cc
index 24d5c48d38a3fe2b6424832a99daee1c0c041f65..babe14e002e43d46a84ead63f58562d14b1e9a0a 100644
--- a/webrtc/modules/video_coding/utility/quality_scaler_unittest.cc
+++ b/webrtc/modules/video_coding/utility/quality_scaler_unittest.cc
@@ -10,28 +10,49 @@
#include "webrtc/modules/video_coding/utility/quality_scaler.h"
+#include <memory>
+
+#include "webrtc/base/event.h"
+#include "webrtc/base/task_queue.h"
+#include "webrtc/test/gmock.h"
#include "webrtc/test/gtest.h"
namespace webrtc {
namespace {
-static const int kNumSeconds = 10;
-static const int kWidth = 1920;
-static const int kHeight = 1080;
static const int kFramerate = 30;
static const int kLowQp = 15;
-static const int kNormalQp = 30;
static const int kLowQpThreshold = 18;
static const int kHighQp = 40;
-static const int kDisabledBadQpThreshold = 64;
-static const int kLowInitialBitrateKbps = 300;
-// These values need to be in sync with corresponding constants
-// in quality_scaler.cc
-static const int kMeasureSecondsFastUpscale = 2;
-static const int kMeasureSecondsUpscale = 5;
-static const int kMeasureSecondsDownscale = 5;
-static const int kMinDownscaleDimension = 140;
+static const size_t kDefaultTimeoutMs = 1000;
} // namespace
+class MockScaleObserver : public ScalingObserverInterface {
+ public:
+ MockScaleObserver() : event(false, false) {}
+ virtual ~MockScaleObserver() {}
+
+ void ScaleUp(ScaleReason r) override {
+ scaled_up++;
+ event.Set();
+ }
+ void ScaleDown(ScaleReason r) override {
+ scaled_down++;
+ event.Set();
+ }
+
+ rtc::Event event;
+ int scaled_up = 0;
+ int scaled_down = 0;
+};
+
+// Pass a lower sampling period to speed up the tests.
+class QualityScalerUnderTest : public QualityScaler {
+ public:
+ explicit QualityScalerUnderTest(ScalingObserverInterface* observer,
+ VideoEncoder::QpThresholds thresholds)
+ : QualityScaler(observer, thresholds, 5) {}
+};
+
class QualityScalerTest : public ::testing::Test {
protected:
enum ScaleDirection {
@@ -41,346 +62,116 @@ class QualityScalerTest : public ::testing::Test {
kScaleUp
};
- QualityScalerTest() {
- input_frame_ = I420Buffer::Create(kWidth, kHeight);
- qs_.Init(kLowQpThreshold, kHighQp, 0, kWidth, kHeight, kFramerate);
- qs_.OnEncodeFrame(input_frame_->width(), input_frame_->height());
+ QualityScalerTest()
+ : q_(new rtc::TaskQueue("QualityScalerTestQueue")),
+ observer_(new MockScaleObserver()) {
+ rtc::Event event(false, false);
+ q_->PostTask([this, &event] {
+ qs_ = std::unique_ptr<QualityScaler>(new QualityScalerUnderTest(
+ observer_.get(),
+ VideoEncoder::QpThresholds(kLowQpThreshold, kHighQp)));
+ event.Set();
+ });
+ EXPECT_TRUE(event.Wait(kDefaultTimeoutMs));
+ }
+
+ ~QualityScalerTest() {
+ rtc::Event event(false, false);
+ q_->PostTask([this, &event] {
+ qs_.reset(nullptr);
+ event.Set();
+ });
+ EXPECT_TRUE(event.Wait(kDefaultTimeoutMs));
}
- bool TriggerScale(ScaleDirection scale_direction) {
- qs_.OnEncodeFrame(input_frame_->width(), input_frame_->height());
- int initial_width = qs_.GetScaledResolution().width;
- for (int i = 0; i < kFramerate * kNumSeconds; ++i) {
+ void TriggerScale(ScaleDirection scale_direction) {
+ for (int i = 0; i < kFramerate * 5; ++i) {
switch (scale_direction) {
case kScaleUp:
- qs_.ReportQP(kLowQp);
+ qs_->ReportQP(kLowQp);
break;
case kScaleDown:
- qs_.ReportDroppedFrame();
+ qs_->ReportDroppedFrame();
break;
case kKeepScaleAtHighQp:
- qs_.ReportQP(kHighQp);
+ qs_->ReportQP(kHighQp);
break;
case kScaleDownAboveHighQp:
- qs_.ReportQP(kHighQp + 1);
+ qs_->ReportQP(kHighQp + 1);
break;
}
- qs_.OnEncodeFrame(input_frame_->width(), input_frame_->height());
- if (qs_.GetScaledResolution().width != initial_width)
- return true;
}
-
- return false;
- }
-
- void ExpectOriginalFrame() {
- EXPECT_EQ(input_frame_, qs_.GetScaledBuffer(input_frame_))
- << "Using scaled frame instead of original input.";
- }
-
- void ExpectScaleUsingReportedResolution() {
- qs_.OnEncodeFrame(input_frame_->width(), input_frame_->height());
- QualityScaler::Resolution res = qs_.GetScaledResolution();
- rtc::scoped_refptr<VideoFrameBuffer> scaled_frame =
- qs_.GetScaledBuffer(input_frame_);
- EXPECT_EQ(res.width, scaled_frame->width());
- EXPECT_EQ(res.height, scaled_frame->height());
}
- void ContinuouslyDownscalesByHalfDimensionsAndBackUp();
-
- void DoesNotDownscaleFrameDimensions(int width, int height);
-
- void DownscaleEndsAt(int input_width,
- int input_height,
- int end_width,
- int end_height);
-
- QualityScaler qs_;
- rtc::scoped_refptr<VideoFrameBuffer> input_frame_;
+ std::unique_ptr<rtc::TaskQueue> q_;
+ std::unique_ptr<QualityScaler> qs_;
+ std::unique_ptr<MockScaleObserver> observer_;
};
-TEST_F(QualityScalerTest, UsesOriginalFrameInitially) {
- ExpectOriginalFrame();
-}
-
-TEST_F(QualityScalerTest, ReportsOriginalResolutionInitially) {
- qs_.OnEncodeFrame(input_frame_->width(), input_frame_->height());
- QualityScaler::Resolution res = qs_.GetScaledResolution();
- EXPECT_EQ(input_frame_->width(), res.width);
- EXPECT_EQ(input_frame_->height(), res.height);
-}
-
TEST_F(QualityScalerTest, DownscalesAfterContinuousFramedrop) {
- EXPECT_TRUE(TriggerScale(kScaleDown)) << "No downscale within " << kNumSeconds
- << " seconds.";
- QualityScaler::Resolution res = qs_.GetScaledResolution();
- EXPECT_LT(res.width, input_frame_->width());
- EXPECT_LT(res.height, input_frame_->height());
+ q_->PostTask([this] { TriggerScale(kScaleDown); });
+ EXPECT_TRUE(observer_->event.Wait(50));
+ EXPECT_EQ(1, observer_->scaled_down);
}
TEST_F(QualityScalerTest, KeepsScaleAtHighQp) {
- EXPECT_FALSE(TriggerScale(kKeepScaleAtHighQp))
- << "Downscale at high threshold which should keep scale.";
- QualityScaler::Resolution res = qs_.GetScaledResolution();
- EXPECT_EQ(res.width, input_frame_->width());
- EXPECT_EQ(res.height, input_frame_->height());
+ q_->PostTask([this] { TriggerScale(kKeepScaleAtHighQp); });
+ EXPECT_FALSE(observer_->event.Wait(50));
+ EXPECT_EQ(0, observer_->scaled_down);
+ EXPECT_EQ(0, observer_->scaled_up);
}
TEST_F(QualityScalerTest, DownscalesAboveHighQp) {
- EXPECT_TRUE(TriggerScale(kScaleDownAboveHighQp))
- << "No downscale within " << kNumSeconds << " seconds.";
- QualityScaler::Resolution res = qs_.GetScaledResolution();
- EXPECT_LT(res.width, input_frame_->width());
- EXPECT_LT(res.height, input_frame_->height());
+ q_->PostTask([this] { TriggerScale(kScaleDownAboveHighQp); });
+ EXPECT_TRUE(observer_->event.Wait(50));
+ EXPECT_EQ(1, observer_->scaled_down);
+ EXPECT_EQ(0, observer_->scaled_up);
}
TEST_F(QualityScalerTest, DownscalesAfterTwoThirdsFramedrop) {
- for (int i = 0; i < kFramerate * kNumSeconds / 3; ++i) {
- qs_.ReportQP(kNormalQp);
- qs_.ReportDroppedFrame();
- qs_.ReportDroppedFrame();
- qs_.OnEncodeFrame(input_frame_->width(), input_frame_->height());
- if (qs_.GetScaledResolution().width < input_frame_->width())
- return;
- }
-
- FAIL() << "No downscale within " << kNumSeconds << " seconds.";
+ q_->PostTask([this] {
+ qs_->ReportDroppedFrame();
+ qs_->ReportDroppedFrame();
+ qs_->ReportQP(kHighQp);
+ });
+ EXPECT_TRUE(observer_->event.Wait(50));
+ EXPECT_EQ(1, observer_->scaled_down);
+ EXPECT_EQ(0, observer_->scaled_up);
}
TEST_F(QualityScalerTest, DoesNotDownscaleOnNormalQp) {
- for (int i = 0; i < kFramerate * kNumSeconds; ++i) {
- qs_.ReportQP(kNormalQp);
- qs_.OnEncodeFrame(input_frame_->width(), input_frame_->height());
- ASSERT_EQ(input_frame_->width(), qs_.GetScaledResolution().width)
- << "Unexpected scale on half framedrop.";
- }
+ q_->PostTask([this] { TriggerScale(kScaleDownAboveHighQp); });
+ EXPECT_TRUE(observer_->event.Wait(50));
+ EXPECT_EQ(1, observer_->scaled_down);
+ EXPECT_EQ(0, observer_->scaled_up);
}
TEST_F(QualityScalerTest, DoesNotDownscaleAfterHalfFramedrop) {
- for (int i = 0; i < kFramerate * kNumSeconds / 2; ++i) {
- qs_.ReportQP(kNormalQp);
- qs_.OnEncodeFrame(input_frame_->width(), input_frame_->height());
- ASSERT_EQ(input_frame_->width(), qs_.GetScaledResolution().width)
- << "Unexpected scale on half framedrop.";
-
- qs_.ReportDroppedFrame();
- qs_.OnEncodeFrame(input_frame_->width(), input_frame_->height());
- ASSERT_EQ(input_frame_->width(), qs_.GetScaledResolution().width)
- << "Unexpected scale on half framedrop.";
- }
-}
-
-void QualityScalerTest::ContinuouslyDownscalesByHalfDimensionsAndBackUp() {
- const int initial_min_dimension =
- input_frame_->width() < input_frame_->height() ? input_frame_->width()
- : input_frame_->height();
- int min_dimension = initial_min_dimension;
- int current_shift = 0;
- // Drop all frames to force-trigger downscaling.
- while (min_dimension >= 2 * kMinDownscaleDimension) {
- EXPECT_TRUE(TriggerScale(kScaleDown)) << "No downscale within "
- << kNumSeconds << " seconds.";
- qs_.OnEncodeFrame(input_frame_->width(), input_frame_->height());
- QualityScaler::Resolution res = qs_.GetScaledResolution();
- min_dimension = res.width < res.height ? res.width : res.height;
- ++current_shift;
- ASSERT_EQ(input_frame_->width() >> current_shift, res.width);
- ASSERT_EQ(input_frame_->height() >> current_shift, res.height);
- ExpectScaleUsingReportedResolution();
- }
-
- // Make sure we can scale back with good-quality frames.
- while (min_dimension < initial_min_dimension) {
- EXPECT_TRUE(TriggerScale(kScaleUp)) << "No upscale within " << kNumSeconds
- << " seconds.";
- qs_.OnEncodeFrame(input_frame_->width(), input_frame_->height());
- QualityScaler::Resolution res = qs_.GetScaledResolution();
- min_dimension = res.width < res.height ? res.width : res.height;
- --current_shift;
- ASSERT_EQ(input_frame_->width() >> current_shift, res.width);
- ASSERT_EQ(input_frame_->height() >> current_shift, res.height);
- ExpectScaleUsingReportedResolution();
- }
-
- // Verify we don't start upscaling after further low use.
- for (int i = 0; i < kFramerate * kNumSeconds; ++i) {
- qs_.ReportQP(kLowQp);
- ExpectOriginalFrame();
- }
-}
-
-TEST_F(QualityScalerTest, ContinuouslyDownscalesByHalfDimensionsAndBackUp) {
- ContinuouslyDownscalesByHalfDimensionsAndBackUp();
-}
-
-TEST_F(QualityScalerTest,
- ContinuouslyDownscalesOddResolutionsByHalfDimensionsAndBackUp) {
- const int kOddWidth = 517;
- const int kOddHeight = 1239;
- input_frame_ = I420Buffer::Create(kOddWidth, kOddHeight);
- ContinuouslyDownscalesByHalfDimensionsAndBackUp();
-}
-
-void QualityScalerTest::DoesNotDownscaleFrameDimensions(int width, int height) {
- input_frame_ = I420Buffer::Create(width, height);
-
- for (int i = 0; i < kFramerate * kNumSeconds; ++i) {
- qs_.ReportDroppedFrame();
- qs_.OnEncodeFrame(input_frame_->width(), input_frame_->height());
- ASSERT_EQ(input_frame_->width(), qs_.GetScaledResolution().width)
- << "Unexpected scale of minimal-size frame.";
- }
-}
-
-TEST_F(QualityScalerTest, DoesNotDownscaleFrom1PxWidth) {
- DoesNotDownscaleFrameDimensions(1, kHeight);
-}
-
-TEST_F(QualityScalerTest, DoesNotDownscaleFrom1PxHeight) {
- DoesNotDownscaleFrameDimensions(kWidth, 1);
-}
-
-TEST_F(QualityScalerTest, DoesNotDownscaleFrom1Px) {
- DoesNotDownscaleFrameDimensions(1, 1);
-}
-
-TEST_F(QualityScalerTest, DoesNotDownscaleBelow2xDefaultMinDimensionsWidth) {
- DoesNotDownscaleFrameDimensions(
- 2 * kMinDownscaleDimension - 1, 1000);
-}
-
-TEST_F(QualityScalerTest, DoesNotDownscaleBelow2xDefaultMinDimensionsHeight) {
- DoesNotDownscaleFrameDimensions(
- 1000, 2 * kMinDownscaleDimension - 1);
-}
-
-TEST_F(QualityScalerTest, DownscaleToVgaOnLowInitialBitrate) {
- static const int kWidth720p = 1280;
- static const int kHeight720p = 720;
- static const int kInitialBitrateKbps = 300;
- input_frame_ = I420Buffer::Create(kWidth720p, kHeight720p);
- qs_.Init(kLowQpThreshold, kDisabledBadQpThreshold, kInitialBitrateKbps,
- kWidth720p, kHeight720p, kFramerate);
- qs_.OnEncodeFrame(input_frame_->width(), input_frame_->height());
- int init_width = qs_.GetScaledResolution().width;
- int init_height = qs_.GetScaledResolution().height;
- EXPECT_EQ(640, init_width);
- EXPECT_EQ(360, init_height);
-}
-
-TEST_F(QualityScalerTest, DownscaleToQvgaOnLowerInitialBitrate) {
- static const int kWidth720p = 1280;
- static const int kHeight720p = 720;
- static const int kInitialBitrateKbps = 200;
- input_frame_ = I420Buffer::Create(kWidth720p, kHeight720p);
- qs_.Init(kLowQpThreshold, kDisabledBadQpThreshold, kInitialBitrateKbps,
- kWidth720p, kHeight720p, kFramerate);
- qs_.OnEncodeFrame(input_frame_->width(), input_frame_->height());
- int init_width = qs_.GetScaledResolution().width;
- int init_height = qs_.GetScaledResolution().height;
- EXPECT_EQ(320, init_width);
- EXPECT_EQ(180, init_height);
-}
-
-TEST_F(QualityScalerTest, DownscaleAfterMeasuredSecondsThenSlowerBackUp) {
- qs_.Init(kLowQpThreshold, kHighQp, 0, kWidth, kHeight, kFramerate);
- qs_.OnEncodeFrame(input_frame_->width(), input_frame_->height());
- QualityScaler::Resolution initial_res = qs_.GetScaledResolution();
-
- // Should not downscale if less than kMeasureSecondsDownscale seconds passed.
- for (int i = 0; i < kFramerate * kMeasureSecondsDownscale - 1; ++i) {
- qs_.ReportQP(kHighQp + 1);
- qs_.OnEncodeFrame(input_frame_->width(), input_frame_->height());
- }
- EXPECT_EQ(initial_res.width, qs_.GetScaledResolution().width);
- EXPECT_EQ(initial_res.height, qs_.GetScaledResolution().height);
-
- // Should downscale if more than kMeasureSecondsDownscale seconds passed (add
- // last frame).
- qs_.ReportQP(kHighQp + 1);
- qs_.OnEncodeFrame(input_frame_->width(), input_frame_->height());
- EXPECT_GT(initial_res.width, qs_.GetScaledResolution().width);
- EXPECT_GT(initial_res.height, qs_.GetScaledResolution().height);
-
- // Should not upscale if less than kMeasureSecondsUpscale seconds passed since
- // we saw issues initially (have already gone down).
- for (int i = 0; i < kFramerate * kMeasureSecondsUpscale - 1; ++i) {
- qs_.ReportQP(kLowQp);
- qs_.OnEncodeFrame(input_frame_->width(), input_frame_->height());
- }
- EXPECT_GT(initial_res.width, qs_.GetScaledResolution().width);
- EXPECT_GT(initial_res.height, qs_.GetScaledResolution().height);
-
- // Should upscale (back to initial) if kMeasureSecondsUpscale seconds passed
- // (add last frame).
- qs_.ReportQP(kLowQp);
- qs_.OnEncodeFrame(input_frame_->width(), input_frame_->height());
- EXPECT_EQ(initial_res.width, qs_.GetScaledResolution().width);
- EXPECT_EQ(initial_res.height, qs_.GetScaledResolution().height);
-}
-
-TEST_F(QualityScalerTest, UpscaleQuicklyInitiallyAfterMeasuredSeconds) {
- qs_.Init(kLowQpThreshold, kHighQp, kLowInitialBitrateKbps, kWidth, kHeight,
- kFramerate);
- qs_.OnEncodeFrame(input_frame_->width(), input_frame_->height());
- QualityScaler::Resolution initial_res = qs_.GetScaledResolution();
-
- // Should not upscale if less than kMeasureSecondsFastUpscale seconds passed.
- for (int i = 0; i < kFramerate * kMeasureSecondsFastUpscale - 1; ++i) {
- qs_.ReportQP(kLowQp);
- qs_.OnEncodeFrame(input_frame_->width(), input_frame_->height());
- }
- EXPECT_EQ(initial_res.width, qs_.GetScaledResolution().width);
- EXPECT_EQ(initial_res.height, qs_.GetScaledResolution().height);
-
- // Should upscale if kMeasureSecondsFastUpscale seconds passed (add last
- // frame).
- qs_.ReportQP(kLowQp);
- qs_.OnEncodeFrame(input_frame_->width(), input_frame_->height());
- EXPECT_LT(initial_res.width, qs_.GetScaledResolution().width);
- EXPECT_LT(initial_res.height, qs_.GetScaledResolution().height);
-}
-
-void QualityScalerTest::DownscaleEndsAt(int input_width,
- int input_height,
- int end_width,
- int end_height) {
- // Create a frame with 2x expected end width/height to verify that we can
- // scale down to expected end width/height.
- input_frame_ = I420Buffer::Create(input_width, input_height);
-
- int last_width = input_width;
- int last_height = input_height;
- // Drop all frames to force-trigger downscaling.
- while (true) {
- TriggerScale(kScaleDown);
- QualityScaler::Resolution res = qs_.GetScaledResolution();
- if (last_width == res.width) {
- EXPECT_EQ(last_height, res.height);
- EXPECT_EQ(end_width, res.width);
- EXPECT_EQ(end_height, res.height);
- break;
- }
- last_width = res.width;
- last_height = res.height;
- }
-}
-
-TEST_F(QualityScalerTest, DownscalesTo320x180) {
- DownscaleEndsAt(640, 360, 320, 180);
-}
-
-TEST_F(QualityScalerTest, DownscalesTo180x320) {
- DownscaleEndsAt(360, 640, 180, 320);
-}
-
-TEST_F(QualityScalerTest, DownscalesFrom1280x720To320x180) {
- DownscaleEndsAt(1280, 720, 320, 180);
-}
-
-TEST_F(QualityScalerTest, DoesntDownscaleInitialQvga) {
- DownscaleEndsAt(320, 180, 320, 180);
+ q_->PostTask([this] {
+ qs_->ReportDroppedFrame();
+ qs_->ReportQP(kHighQp);
+ });
+ EXPECT_FALSE(observer_->event.Wait(50));
+ EXPECT_EQ(0, observer_->scaled_down);
+ EXPECT_EQ(0, observer_->scaled_up);
+}
+
+TEST_F(QualityScalerTest, UpscalesAfterLowQp) {
+ q_->PostTask([this] { TriggerScale(kScaleUp); });
+ EXPECT_TRUE(observer_->event.Wait(50));
+ EXPECT_EQ(0, observer_->scaled_down);
+ EXPECT_EQ(1, observer_->scaled_up);
+}
+
+TEST_F(QualityScalerTest, ScalesDownAndBackUp) {
+ q_->PostTask([this] { TriggerScale(kScaleDown); });
+ EXPECT_TRUE(observer_->event.Wait(50));
+ EXPECT_EQ(1, observer_->scaled_down);
+ EXPECT_EQ(0, observer_->scaled_up);
+ q_->PostTask([this] { TriggerScale(kScaleUp); });
+ EXPECT_TRUE(observer_->event.Wait(50));
+ EXPECT_EQ(1, observer_->scaled_down);
+ EXPECT_EQ(1, observer_->scaled_up);
}
} // namespace webrtc
« no previous file with comments | « webrtc/modules/video_coding/utility/quality_scaler.cc ('k') | webrtc/modules/video_coding/video_coding_impl.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698