Chromium Code Reviews| 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..2544bcee4cbf6a6ee1591c375c1adcb8c0dcf6fd 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 kDefaultTimeout = 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; |
| +}; |
| + |
| +// Override GetSamplingPeriodMs to speed up the tests. |
|
magjed_webrtc
2016/11/10 13:07:00
Update comment, you pass it in the ctor instead.
kthelgason
2016/11/10 15:38:28
Done.
|
| +class QualityScalerUnderTest : public QualityScaler { |
| + public: |
| + explicit QualityScalerUnderTest(ScalingObserverInterface* observer, |
| + 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(), |
| + QualityScaler::QPThresholds(kLowQpThreshold, kHighQp))); |
| + event.Set(); |
| + }); |
| + EXPECT_TRUE(event.Wait(kDefaultTimeout)); |
| + } |
| + |
| + ~QualityScalerTest() { |
| + rtc::Event event(false, false); |
| + q->PostTask([this, &event] { |
| + qs_.reset(nullptr); |
| + event.Set(); |
| + }); |
| + EXPECT_TRUE(event.Wait(kDefaultTimeout)); |
| } |
| - 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; |
|
magjed_webrtc
2016/11/10 13:07:00
Can't this be a 'rtc::TaskQueue q;' instead? I.e.
magjed_webrtc
2016/11/10 13:07:00
nit: I guess this should be called 'q_'.
kthelgason
2016/11/10 15:38:27
Sure, Just done for symmetry with other ivars.
kthelgason
2016/11/10 15:38:27
Done.
|
| + 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(observer_->scaled_down, 1); |
|
magjed_webrtc
2016/11/10 13:07:00
It should be the expected value first when using E
kthelgason
2016/11/10 15:38:27
😫
|
| } |
| 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(observer_->scaled_down, 0); |
| + EXPECT_EQ(observer_->scaled_up, 0); |
| } |
| 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(observer_->scaled_down, 1); |
| + EXPECT_EQ(observer_->scaled_up, 0); |
| } |
| 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(observer_->scaled_down, 1); |
| + EXPECT_EQ(observer_->scaled_up, 0); |
| } |
| 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(observer_->scaled_down, 1); |
| + EXPECT_EQ(observer_->scaled_up, 0); |
| } |
| 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(observer_->scaled_down, 0); |
| + EXPECT_EQ(observer_->scaled_up, 0); |
| +} |
| + |
| +TEST_F(QualityScalerTest, UpscalesAfterLowQp) { |
| + q->PostTask([this] { TriggerScale(kScaleUp); }); |
| + EXPECT_TRUE(observer_->event.Wait(50)); |
| + EXPECT_EQ(observer_->scaled_down, 0); |
| + EXPECT_EQ(observer_->scaled_up, 1); |
| +} |
| + |
| +TEST_F(QualityScalerTest, ScalesDownAndBackUp) { |
| + q->PostTask([this] { TriggerScale(kScaleDown); }); |
| + EXPECT_TRUE(observer_->event.Wait(50)); |
| + EXPECT_EQ(observer_->scaled_down, 1); |
| + EXPECT_EQ(observer_->scaled_up, 0); |
| + q->PostTask([this] { TriggerScale(kScaleUp); }); |
| + EXPECT_TRUE(observer_->event.Wait(50)); |
| + EXPECT_EQ(observer_->scaled_down, 1); |
| + EXPECT_EQ(observer_->scaled_up, 1); |
| } |
| } // namespace webrtc |