Moving src/webrtc into src/.
In order to eliminate the WebRTC Subtree mirror in Chromium, WebRTC is moving the content of the src/webrtc directory up to the src/ directory. NOPRESUBMIT=true NOTREECHECKS=true NOTRY=true TBR=tommi@webrtc.org Bug: chromium:611808 Change-Id: Iac59c5b51b950f174119565bac87955a7994bc38 Reviewed-on: https://webrtc-review.googlesource.com/1560 Commit-Queue: Mirko Bonadei <mbonadei@webrtc.org> Reviewed-by: Henrik Kjellander <kjellander@webrtc.org> Cr-Commit-Position: refs/heads/master@{#19845}
This commit is contained in:
committed by
Commit Bot
parent
6674846b4a
commit
bb547203bf
202
modules/video_coding/utility/quality_scaler_unittest.cc
Normal file
202
modules/video_coding/utility/quality_scaler_unittest.cc
Normal file
@ -0,0 +1,202 @@
|
||||
/*
|
||||
* Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "webrtc/modules/video_coding/utility/quality_scaler.h"
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "webrtc/rtc_base/event.h"
|
||||
#include "webrtc/rtc_base/task_queue.h"
|
||||
#include "webrtc/test/gmock.h"
|
||||
#include "webrtc/test/gtest.h"
|
||||
|
||||
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 size_t kDefaultTimeoutMs = 150;
|
||||
} // namespace
|
||||
|
||||
#define DO_SYNC(q, block) do { \
|
||||
rtc::Event event(false, false); \
|
||||
q->PostTask([this, &event] { \
|
||||
block; \
|
||||
event.Set(); \
|
||||
}); \
|
||||
RTC_CHECK(event.Wait(1000)); \
|
||||
} while (0)
|
||||
|
||||
|
||||
class MockAdaptationObserver : public AdaptationObserverInterface {
|
||||
public:
|
||||
MockAdaptationObserver() : event(false, false) {}
|
||||
virtual ~MockAdaptationObserver() {}
|
||||
|
||||
void AdaptUp(AdaptReason r) override {
|
||||
adapt_up_events_++;
|
||||
event.Set();
|
||||
}
|
||||
void AdaptDown(AdaptReason r) override {
|
||||
adapt_down_events_++;
|
||||
event.Set();
|
||||
}
|
||||
|
||||
rtc::Event event;
|
||||
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(AdaptationObserverInterface* observer,
|
||||
VideoEncoder::QpThresholds thresholds)
|
||||
: QualityScaler(observer, thresholds, 5) {}
|
||||
};
|
||||
|
||||
class QualityScalerTest : public ::testing::Test {
|
||||
protected:
|
||||
enum ScaleDirection {
|
||||
kKeepScaleAtHighQp,
|
||||
kScaleDown,
|
||||
kScaleDownAboveHighQp,
|
||||
kScaleUp
|
||||
};
|
||||
|
||||
QualityScalerTest()
|
||||
: q_(new rtc::TaskQueue("QualityScalerTestQueue")),
|
||||
observer_(new MockAdaptationObserver()) {
|
||||
DO_SYNC(q_, {
|
||||
qs_ = std::unique_ptr<QualityScaler>(new QualityScalerUnderTest(
|
||||
observer_.get(),
|
||||
VideoEncoder::QpThresholds(kLowQpThreshold, kHighQp)));});
|
||||
}
|
||||
|
||||
~QualityScalerTest() {
|
||||
DO_SYNC(q_, {qs_.reset(nullptr);});
|
||||
}
|
||||
|
||||
void TriggerScale(ScaleDirection scale_direction) {
|
||||
for (int i = 0; i < kFramerate * 5; ++i) {
|
||||
switch (scale_direction) {
|
||||
case kScaleUp:
|
||||
qs_->ReportQP(kLowQp);
|
||||
break;
|
||||
case kScaleDown:
|
||||
qs_->ReportDroppedFrame();
|
||||
break;
|
||||
case kKeepScaleAtHighQp:
|
||||
qs_->ReportQP(kHighQp);
|
||||
break;
|
||||
case kScaleDownAboveHighQp:
|
||||
qs_->ReportQP(kHighQp + 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::unique_ptr<rtc::TaskQueue> q_;
|
||||
std::unique_ptr<QualityScaler> qs_;
|
||||
std::unique_ptr<MockAdaptationObserver> observer_;
|
||||
};
|
||||
|
||||
TEST_F(QualityScalerTest, DownscalesAfterContinuousFramedrop) {
|
||||
DO_SYNC(q_, { TriggerScale(kScaleDown); });
|
||||
EXPECT_TRUE(observer_->event.Wait(kDefaultTimeoutMs));
|
||||
EXPECT_EQ(1, observer_->adapt_down_events_);
|
||||
}
|
||||
|
||||
TEST_F(QualityScalerTest, KeepsScaleAtHighQp) {
|
||||
DO_SYNC(q_, { TriggerScale(kKeepScaleAtHighQp); });
|
||||
EXPECT_FALSE(observer_->event.Wait(kDefaultTimeoutMs));
|
||||
EXPECT_EQ(0, observer_->adapt_down_events_);
|
||||
EXPECT_EQ(0, observer_->adapt_up_events_);
|
||||
}
|
||||
|
||||
TEST_F(QualityScalerTest, DownscalesAboveHighQp) {
|
||||
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, DownscalesAfterTwoThirdsFramedrop) {
|
||||
DO_SYNC(q_, {
|
||||
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_);
|
||||
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) {
|
||||
qs_->ReportDroppedFrame();
|
||||
qs_->ReportQP(kHighQp);
|
||||
}
|
||||
});
|
||||
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));
|
||||
EXPECT_EQ(0, observer_->adapt_down_events_);
|
||||
EXPECT_EQ(1, observer_->adapt_up_events_);
|
||||
}
|
||||
|
||||
TEST_F(QualityScalerTest, ScalesDownAndBackUp) {
|
||||
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_);
|
||||
DO_SYNC(q_, { TriggerScale(kScaleUp); });
|
||||
EXPECT_TRUE(observer_->event.Wait(kDefaultTimeoutMs));
|
||||
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