blob: 1ec325d84487a572c848b80b613f4f0e0a7d0b55 [file] [log] [blame]
Peter Boström4d71ede2015-05-19 23:09:35 +02001/*
2 * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020011#include "media/engine/videoencodersoftwarefallbackwrapper.h"
magjed614d5b72016-11-15 06:30:54 -080012
13#include <utility>
Peter Boström4d71ede2015-05-19 23:09:35 +020014
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020015#include "api/video/i420_buffer.h"
16#include "modules/video_coding/codecs/vp8/simulcast_rate_allocator.h"
17#include "modules/video_coding/codecs/vp8/temporal_layers.h"
18#include "modules/video_coding/include/video_codec_interface.h"
19#include "modules/video_coding/include/video_error_codes.h"
20#include "rtc_base/checks.h"
21#include "rtc_base/fakeclock.h"
22#include "test/field_trial.h"
23#include "test/gtest.h"
Peter Boström4d71ede2015-05-19 23:09:35 +020024
25namespace webrtc {
asapersson22c76c42017-08-16 00:53:59 -070026namespace {
noahricb1ce6632015-10-21 23:54:51 -070027const int kWidth = 320;
28const int kHeight = 240;
asapersson22c76c42017-08-16 00:53:59 -070029const int kNumCores = 2;
30const uint32_t kFramerate = 30;
Peter Boström4d71ede2015-05-19 23:09:35 +020031const size_t kMaxPayloadSize = 800;
asapersson142fcc92017-08-17 08:58:54 -070032const int kDefaultMinPixelsPerFrame = 320 * 180;
Åsa Persson45bbc8a2017-11-13 10:16:47 +010033const int kLowThreshold = 10;
34const int kHighThreshold = 20;
asapersson22c76c42017-08-16 00:53:59 -070035} // namespace
Peter Boström4d71ede2015-05-19 23:09:35 +020036
37class VideoEncoderSoftwareFallbackWrapperTest : public ::testing::Test {
38 protected:
39 VideoEncoderSoftwareFallbackWrapperTest()
asapersson22c76c42017-08-16 00:53:59 -070040 : VideoEncoderSoftwareFallbackWrapperTest("") {}
41 explicit VideoEncoderSoftwareFallbackWrapperTest(
42 const std::string& field_trials)
43 : override_field_trials_(field_trials),
magjedf52d34d2017-08-29 00:58:52 -070044 fake_encoder_(new CountingFakeEncoder()),
45 fallback_wrapper_(cricket::VideoCodec("VP8"),
46 std::unique_ptr<VideoEncoder>(fake_encoder_)) {}
Peter Boström4d71ede2015-05-19 23:09:35 +020047
48 class CountingFakeEncoder : public VideoEncoder {
49 public:
50 int32_t InitEncode(const VideoCodec* codec_settings,
51 int32_t number_of_cores,
52 size_t max_payload_size) override {
53 ++init_encode_count_;
54 return init_encode_return_code_;
55 }
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -070056 int32_t Encode(const VideoFrame& frame,
Peter Boström4d71ede2015-05-19 23:09:35 +020057 const CodecSpecificInfo* codec_specific_info,
pbos22993e12015-10-19 02:39:06 -070058 const std::vector<FrameType>* frame_types) override {
Peter Boström4d71ede2015-05-19 23:09:35 +020059 ++encode_count_;
perkj275afc52016-09-01 00:21:16 -070060 if (encode_complete_callback_ &&
61 encode_return_code_ == WEBRTC_VIDEO_CODEC_OK) {
62 CodecSpecificInfo info;
63 info.codec_name = ImplementationName();
64 encode_complete_callback_->OnEncodedImage(EncodedImage(), &info,
65 nullptr);
66 }
noahricb1ce6632015-10-21 23:54:51 -070067 return encode_return_code_;
Peter Boström4d71ede2015-05-19 23:09:35 +020068 }
69
70 int32_t RegisterEncodeCompleteCallback(
71 EncodedImageCallback* callback) override {
72 encode_complete_callback_ = callback;
73 return WEBRTC_VIDEO_CODEC_OK;
74 }
75
76 int32_t Release() override {
77 ++release_count_;
78 return WEBRTC_VIDEO_CODEC_OK;
79 }
80
81 int32_t SetChannelParameters(uint32_t packet_loss, int64_t rtt) override {
82 ++set_channel_parameters_count_;
83 return WEBRTC_VIDEO_CODEC_OK;
84 }
85
Erik Språng08127a92016-11-16 16:41:30 +010086 int32_t SetRateAllocation(const BitrateAllocation& bitrate_allocation,
87 uint32_t framerate) override {
Peter Boström4d71ede2015-05-19 23:09:35 +020088 ++set_rates_count_;
89 return WEBRTC_VIDEO_CODEC_OK;
90 }
91
Peter Boströmeb66e802015-06-05 11:08:03 +020092 bool SupportsNativeHandle() const override {
93 ++supports_native_handle_count_;
asapersson22c76c42017-08-16 00:53:59 -070094 return supports_native_handle_;
Peter Boströmeb66e802015-06-05 11:08:03 +020095 }
96
Peter Boströmb7d9a972015-12-18 16:01:11 +010097 const char* ImplementationName() const override {
98 return "fake-encoder";
99 }
100
asapersson142fcc92017-08-17 08:58:54 -0700101 VideoEncoder::ScalingSettings GetScalingSettings() const override {
Åsa Persson45bbc8a2017-11-13 10:16:47 +0100102 return VideoEncoder::ScalingSettings(true, kLowThreshold, kHighThreshold);
asapersson142fcc92017-08-17 08:58:54 -0700103 }
104
Peter Boström4d71ede2015-05-19 23:09:35 +0200105 int init_encode_count_ = 0;
106 int32_t init_encode_return_code_ = WEBRTC_VIDEO_CODEC_OK;
noahricb1ce6632015-10-21 23:54:51 -0700107 int32_t encode_return_code_ = WEBRTC_VIDEO_CODEC_OK;
Peter Boström4d71ede2015-05-19 23:09:35 +0200108 int encode_count_ = 0;
109 EncodedImageCallback* encode_complete_callback_ = nullptr;
110 int release_count_ = 0;
111 int set_channel_parameters_count_ = 0;
112 int set_rates_count_ = 0;
Peter Boströmeb66e802015-06-05 11:08:03 +0200113 mutable int supports_native_handle_count_ = 0;
asapersson22c76c42017-08-16 00:53:59 -0700114 bool supports_native_handle_ = false;
Peter Boström4d71ede2015-05-19 23:09:35 +0200115 };
116
117 class FakeEncodedImageCallback : public EncodedImageCallback {
118 public:
Sergey Ulanov525df3f2016-08-02 17:46:41 -0700119 Result OnEncodedImage(
120 const EncodedImage& encoded_image,
121 const CodecSpecificInfo* codec_specific_info,
122 const RTPFragmentationHeader* fragmentation) override {
123 ++callback_count_;
perkj275afc52016-09-01 00:21:16 -0700124 last_codec_name_ = codec_specific_info->codec_name;
Sergey Ulanov525df3f2016-08-02 17:46:41 -0700125 return Result(Result::OK, callback_count_);
Peter Boström4d71ede2015-05-19 23:09:35 +0200126 }
127 int callback_count_ = 0;
perkj275afc52016-09-01 00:21:16 -0700128 std::string last_codec_name_;
Peter Boström4d71ede2015-05-19 23:09:35 +0200129 };
130
131 void UtilizeFallbackEncoder();
noahricb1ce6632015-10-21 23:54:51 -0700132 void FallbackFromEncodeRequest();
133 void EncodeFrame();
asapersson22c76c42017-08-16 00:53:59 -0700134 void EncodeFrame(int expected_ret);
perkj275afc52016-09-01 00:21:16 -0700135 void CheckLastEncoderName(const char* expected_name) {
136 EXPECT_STREQ(expected_name, callback_.last_codec_name_.c_str());
137 }
Peter Boström4d71ede2015-05-19 23:09:35 +0200138
asapersson22c76c42017-08-16 00:53:59 -0700139 test::ScopedFieldTrials override_field_trials_;
Peter Boström4d71ede2015-05-19 23:09:35 +0200140 FakeEncodedImageCallback callback_;
magjedf52d34d2017-08-29 00:58:52 -0700141 // |fake_encoder_| is owned and released by |fallback_wrapper_|.
142 CountingFakeEncoder* fake_encoder_;
Peter Boström4d71ede2015-05-19 23:09:35 +0200143 VideoEncoderSoftwareFallbackWrapper fallback_wrapper_;
144 VideoCodec codec_ = {};
nisse64ec8f82016-09-27 00:17:25 -0700145 std::unique_ptr<VideoFrame> frame_;
Erik Språng08127a92016-11-16 16:41:30 +0100146 std::unique_ptr<SimulcastRateAllocator> rate_allocator_;
Peter Boström4d71ede2015-05-19 23:09:35 +0200147};
148
noahricb1ce6632015-10-21 23:54:51 -0700149void VideoEncoderSoftwareFallbackWrapperTest::EncodeFrame() {
asapersson22c76c42017-08-16 00:53:59 -0700150 EncodeFrame(WEBRTC_VIDEO_CODEC_OK);
151}
152
153void VideoEncoderSoftwareFallbackWrapperTest::EncodeFrame(int expected_ret) {
asapersson142fcc92017-08-17 08:58:54 -0700154 rtc::scoped_refptr<I420Buffer> buffer =
155 I420Buffer::Create(codec_.width, codec_.height);
nisseaf916892017-01-10 07:44:26 -0800156 I420Buffer::SetBlack(buffer);
nisse776870a2016-09-21 03:52:16 -0700157 std::vector<FrameType> types(1, kVideoFrameKey);
nisse64ec8f82016-09-27 00:17:25 -0700158
159 frame_.reset(new VideoFrame(buffer, 0, 0, webrtc::kVideoRotation_0));
asapersson22c76c42017-08-16 00:53:59 -0700160 EXPECT_EQ(expected_ret, fallback_wrapper_.Encode(*frame_, nullptr, &types));
noahricb1ce6632015-10-21 23:54:51 -0700161}
162
Peter Boström4d71ede2015-05-19 23:09:35 +0200163void VideoEncoderSoftwareFallbackWrapperTest::UtilizeFallbackEncoder() {
Peter Boström4d71ede2015-05-19 23:09:35 +0200164 fallback_wrapper_.RegisterEncodeCompleteCallback(&callback_);
magjedf52d34d2017-08-29 00:58:52 -0700165 EXPECT_EQ(&callback_, fake_encoder_->encode_complete_callback_);
Peter Boström4d71ede2015-05-19 23:09:35 +0200166
167 // Register with failing fake encoder. Should succeed with VP8 fallback.
168 codec_.codecType = kVideoCodecVP8;
asapersson22c76c42017-08-16 00:53:59 -0700169 codec_.maxFramerate = kFramerate;
Peter Boström4d71ede2015-05-19 23:09:35 +0200170 codec_.width = kWidth;
171 codec_.height = kHeight;
Erik Språng08127a92016-11-16 16:41:30 +0100172 codec_.VP8()->numberOfTemporalLayers = 1;
173 std::unique_ptr<TemporalLayersFactory> tl_factory(
174 new TemporalLayersFactory());
175 codec_.VP8()->tl_factory = tl_factory.get();
176 rate_allocator_.reset(
177 new SimulcastRateAllocator(codec_, std::move(tl_factory)));
178
magjedf52d34d2017-08-29 00:58:52 -0700179 fake_encoder_->init_encode_return_code_ = WEBRTC_VIDEO_CODEC_ERROR;
Peter Boström4d71ede2015-05-19 23:09:35 +0200180 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK,
asapersson22c76c42017-08-16 00:53:59 -0700181 fallback_wrapper_.InitEncode(&codec_, kNumCores, kMaxPayloadSize));
182 EXPECT_EQ(
183 WEBRTC_VIDEO_CODEC_OK,
184 fallback_wrapper_.SetRateAllocation(
185 rate_allocator_->GetAllocation(300000, kFramerate), kFramerate));
Peter Boström4d71ede2015-05-19 23:09:35 +0200186
noahricb1ce6632015-10-21 23:54:51 -0700187 int callback_count = callback_.callback_count_;
magjedf52d34d2017-08-29 00:58:52 -0700188 int encode_count = fake_encoder_->encode_count_;
noahricb1ce6632015-10-21 23:54:51 -0700189 EncodeFrame();
magjedf52d34d2017-08-29 00:58:52 -0700190 EXPECT_EQ(encode_count, fake_encoder_->encode_count_);
noahricb1ce6632015-10-21 23:54:51 -0700191 EXPECT_EQ(callback_count + 1, callback_.callback_count_);
192}
Peter Boström4d71ede2015-05-19 23:09:35 +0200193
noahricb1ce6632015-10-21 23:54:51 -0700194void VideoEncoderSoftwareFallbackWrapperTest::FallbackFromEncodeRequest() {
195 fallback_wrapper_.RegisterEncodeCompleteCallback(&callback_);
196 codec_.codecType = kVideoCodecVP8;
asapersson22c76c42017-08-16 00:53:59 -0700197 codec_.maxFramerate = kFramerate;
noahricb1ce6632015-10-21 23:54:51 -0700198 codec_.width = kWidth;
199 codec_.height = kHeight;
Erik Språng08127a92016-11-16 16:41:30 +0100200 codec_.VP8()->numberOfTemporalLayers = 1;
201 std::unique_ptr<TemporalLayersFactory> tl_factory(
202 new TemporalLayersFactory());
203 codec_.VP8()->tl_factory = tl_factory.get();
204 rate_allocator_.reset(
205 new SimulcastRateAllocator(codec_, std::move(tl_factory)));
noahricb1ce6632015-10-21 23:54:51 -0700206 fallback_wrapper_.InitEncode(&codec_, 2, kMaxPayloadSize);
asapersson22c76c42017-08-16 00:53:59 -0700207 EXPECT_EQ(
208 WEBRTC_VIDEO_CODEC_OK,
209 fallback_wrapper_.SetRateAllocation(
210 rate_allocator_->GetAllocation(300000, kFramerate), kFramerate));
magjedf52d34d2017-08-29 00:58:52 -0700211 EXPECT_EQ(1, fake_encoder_->init_encode_count_);
noahricb1ce6632015-10-21 23:54:51 -0700212
213 // Have the non-fallback encoder request a software fallback.
magjedf52d34d2017-08-29 00:58:52 -0700214 fake_encoder_->encode_return_code_ = WEBRTC_VIDEO_CODEC_FALLBACK_SOFTWARE;
noahricb1ce6632015-10-21 23:54:51 -0700215 int callback_count = callback_.callback_count_;
magjedf52d34d2017-08-29 00:58:52 -0700216 int encode_count = fake_encoder_->encode_count_;
noahricb1ce6632015-10-21 23:54:51 -0700217 EncodeFrame();
218 // Single encode request, which returned failure.
magjedf52d34d2017-08-29 00:58:52 -0700219 EXPECT_EQ(encode_count + 1, fake_encoder_->encode_count_);
noahricb1ce6632015-10-21 23:54:51 -0700220 EXPECT_EQ(callback_count + 1, callback_.callback_count_);
Peter Boström4d71ede2015-05-19 23:09:35 +0200221}
222
223TEST_F(VideoEncoderSoftwareFallbackWrapperTest, InitializesEncoder) {
224 VideoCodec codec = {};
225 fallback_wrapper_.InitEncode(&codec, 2, kMaxPayloadSize);
magjedf52d34d2017-08-29 00:58:52 -0700226 EXPECT_EQ(1, fake_encoder_->init_encode_count_);
Peter Boström4d71ede2015-05-19 23:09:35 +0200227}
228
noahricb1ce6632015-10-21 23:54:51 -0700229TEST_F(VideoEncoderSoftwareFallbackWrapperTest, EncodeRequestsFallback) {
230 FallbackFromEncodeRequest();
231 // After fallback, further encodes shouldn't hit the fake encoder.
magjedf52d34d2017-08-29 00:58:52 -0700232 int encode_count = fake_encoder_->encode_count_;
noahricb1ce6632015-10-21 23:54:51 -0700233 EncodeFrame();
magjedf52d34d2017-08-29 00:58:52 -0700234 EXPECT_EQ(encode_count, fake_encoder_->encode_count_);
noahricb1ce6632015-10-21 23:54:51 -0700235}
236
Peter Boström4d71ede2015-05-19 23:09:35 +0200237TEST_F(VideoEncoderSoftwareFallbackWrapperTest, CanUtilizeFallbackEncoder) {
238 UtilizeFallbackEncoder();
239 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, fallback_wrapper_.Release());
240}
241
242TEST_F(VideoEncoderSoftwareFallbackWrapperTest,
noahricb1ce6632015-10-21 23:54:51 -0700243 InternalEncoderReleasedDuringFallback) {
magjedf52d34d2017-08-29 00:58:52 -0700244 EXPECT_EQ(0, fake_encoder_->release_count_);
noahricb1ce6632015-10-21 23:54:51 -0700245 UtilizeFallbackEncoder();
magjedf52d34d2017-08-29 00:58:52 -0700246 EXPECT_EQ(1, fake_encoder_->release_count_);
noahricb1ce6632015-10-21 23:54:51 -0700247 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, fallback_wrapper_.Release());
248 // No extra release when the fallback is released.
magjedf52d34d2017-08-29 00:58:52 -0700249 EXPECT_EQ(1, fake_encoder_->release_count_);
Peter Boström4d71ede2015-05-19 23:09:35 +0200250}
251
252TEST_F(VideoEncoderSoftwareFallbackWrapperTest,
253 InternalEncoderNotEncodingDuringFallback) {
254 UtilizeFallbackEncoder();
magjedf52d34d2017-08-29 00:58:52 -0700255 int encode_count = fake_encoder_->encode_count_;
noahricb1ce6632015-10-21 23:54:51 -0700256 EncodeFrame();
magjedf52d34d2017-08-29 00:58:52 -0700257 EXPECT_EQ(encode_count, fake_encoder_->encode_count_);
Peter Boström4d71ede2015-05-19 23:09:35 +0200258
259 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, fallback_wrapper_.Release());
260}
261
262TEST_F(VideoEncoderSoftwareFallbackWrapperTest,
263 CanRegisterCallbackWhileUsingFallbackEncoder) {
264 UtilizeFallbackEncoder();
265 // Registering an encode-complete callback should still work when fallback
266 // encoder is being used.
267 FakeEncodedImageCallback callback2;
268 fallback_wrapper_.RegisterEncodeCompleteCallback(&callback2);
magjedf52d34d2017-08-29 00:58:52 -0700269 EXPECT_EQ(&callback2, fake_encoder_->encode_complete_callback_);
Peter Boström4d71ede2015-05-19 23:09:35 +0200270
271 // Encoding a frame using the fallback should arrive at the new callback.
Peter Boström49e196a2015-10-23 15:58:18 +0200272 std::vector<FrameType> types(1, kVideoFrameKey);
nisse64ec8f82016-09-27 00:17:25 -0700273 frame_->set_timestamp(frame_->timestamp() + 1000);
Peter Boström4d71ede2015-05-19 23:09:35 +0200274 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK,
nisse64ec8f82016-09-27 00:17:25 -0700275 fallback_wrapper_.Encode(*frame_, nullptr, &types));
Peter Boström4d71ede2015-05-19 23:09:35 +0200276
277 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, fallback_wrapper_.Release());
278}
279
280TEST_F(VideoEncoderSoftwareFallbackWrapperTest,
281 SetChannelParametersForwardedDuringFallback) {
282 UtilizeFallbackEncoder();
magjedf52d34d2017-08-29 00:58:52 -0700283 EXPECT_EQ(0, fake_encoder_->set_channel_parameters_count_);
Peter Boström4d71ede2015-05-19 23:09:35 +0200284 fallback_wrapper_.SetChannelParameters(1, 1);
magjedf52d34d2017-08-29 00:58:52 -0700285 EXPECT_EQ(1, fake_encoder_->set_channel_parameters_count_);
Peter Boström4d71ede2015-05-19 23:09:35 +0200286 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, fallback_wrapper_.Release());
287}
288
289TEST_F(VideoEncoderSoftwareFallbackWrapperTest,
290 SetRatesForwardedDuringFallback) {
291 UtilizeFallbackEncoder();
magjedf52d34d2017-08-29 00:58:52 -0700292 EXPECT_EQ(1, fake_encoder_->set_rates_count_);
Erik Språng08127a92016-11-16 16:41:30 +0100293 fallback_wrapper_.SetRateAllocation(BitrateAllocation(), 1);
magjedf52d34d2017-08-29 00:58:52 -0700294 EXPECT_EQ(2, fake_encoder_->set_rates_count_);
Peter Boström4d71ede2015-05-19 23:09:35 +0200295 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, fallback_wrapper_.Release());
296}
297
298TEST_F(VideoEncoderSoftwareFallbackWrapperTest,
Peter Boströmeb66e802015-06-05 11:08:03 +0200299 SupportsNativeHandleForwardedWithoutFallback) {
300 fallback_wrapper_.SupportsNativeHandle();
magjedf52d34d2017-08-29 00:58:52 -0700301 EXPECT_EQ(1, fake_encoder_->supports_native_handle_count_);
Peter Boströmeb66e802015-06-05 11:08:03 +0200302}
303
304TEST_F(VideoEncoderSoftwareFallbackWrapperTest,
305 SupportsNativeHandleNotForwardedDuringFallback) {
306 UtilizeFallbackEncoder();
307 fallback_wrapper_.SupportsNativeHandle();
magjedf52d34d2017-08-29 00:58:52 -0700308 EXPECT_EQ(0, fake_encoder_->supports_native_handle_count_);
Peter Boströmeb66e802015-06-05 11:08:03 +0200309 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, fallback_wrapper_.Release());
310}
311
perkj275afc52016-09-01 00:21:16 -0700312TEST_F(VideoEncoderSoftwareFallbackWrapperTest, ReportsImplementationName) {
asapersson142fcc92017-08-17 08:58:54 -0700313 codec_.width = kWidth;
314 codec_.height = kHeight;
perkj275afc52016-09-01 00:21:16 -0700315 fallback_wrapper_.RegisterEncodeCompleteCallback(&callback_);
asapersson142fcc92017-08-17 08:58:54 -0700316 fallback_wrapper_.InitEncode(&codec_, kNumCores, kMaxPayloadSize);
perkj275afc52016-09-01 00:21:16 -0700317 EncodeFrame();
318 CheckLastEncoderName("fake-encoder");
319}
320
Peter Boströmb7d9a972015-12-18 16:01:11 +0100321TEST_F(VideoEncoderSoftwareFallbackWrapperTest,
322 ReportsFallbackImplementationName) {
323 UtilizeFallbackEncoder();
324 // Hard coded expected value since libvpx is the software implementation name
325 // for VP8. Change accordingly if the underlying implementation does.
perkj275afc52016-09-01 00:21:16 -0700326 CheckLastEncoderName("libvpx");
Peter Boströmb7d9a972015-12-18 16:01:11 +0100327}
328
asapersson22c76c42017-08-16 00:53:59 -0700329namespace {
Åsa Persson45bbc8a2017-11-13 10:16:47 +0100330const int kBitrateKbps = 200;
asapersson142fcc92017-08-17 08:58:54 -0700331const int kMinPixelsPerFrame = 1;
Åsa Persson45bbc8a2017-11-13 10:16:47 +0100332const char kFieldTrial[] = "WebRTC-VP8-Forced-Fallback-Encoder-v2";
asapersson22c76c42017-08-16 00:53:59 -0700333} // namespace
334
335class ForcedFallbackTest : public VideoEncoderSoftwareFallbackWrapperTest {
336 public:
Steve Antone78bcb92017-10-31 09:53:08 -0700337 explicit ForcedFallbackTest(const std::string& field_trials)
asapersson22c76c42017-08-16 00:53:59 -0700338 : VideoEncoderSoftwareFallbackWrapperTest(field_trials) {}
339
340 ~ForcedFallbackTest() override {}
341
342 protected:
343 void SetUp() override {
344 clock_.SetTimeMicros(1234);
345 ConfigureVp8Codec();
asapersson22c76c42017-08-16 00:53:59 -0700346 }
347
348 void TearDown() override {
349 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, fallback_wrapper_.Release());
350 }
351
352 void ConfigureVp8Codec() {
353 fallback_wrapper_.RegisterEncodeCompleteCallback(&callback_);
354 std::unique_ptr<TemporalLayersFactory> tl_factory(
355 new TemporalLayersFactory());
356 codec_.codecType = kVideoCodecVP8;
357 codec_.maxFramerate = kFramerate;
358 codec_.width = kWidth;
359 codec_.height = kHeight;
360 codec_.VP8()->numberOfTemporalLayers = 1;
asapersson142fcc92017-08-17 08:58:54 -0700361 codec_.VP8()->automaticResizeOn = true;
362 codec_.VP8()->frameDroppingOn = true;
asapersson22c76c42017-08-16 00:53:59 -0700363 codec_.VP8()->tl_factory = tl_factory.get();
364 rate_allocator_.reset(
365 new SimulcastRateAllocator(codec_, std::move(tl_factory)));
366 }
367
Åsa Persson45bbc8a2017-11-13 10:16:47 +0100368 void InitEncode(int width, int height) {
369 codec_.width = width;
370 codec_.height = height;
371 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, fallback_wrapper_.InitEncode(
372 &codec_, kNumCores, kMaxPayloadSize));
373 SetRateAllocation(kBitrateKbps);
374 }
375
asapersson22c76c42017-08-16 00:53:59 -0700376 void SetRateAllocation(uint32_t bitrate_kbps) {
377 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, fallback_wrapper_.SetRateAllocation(
378 rate_allocator_->GetAllocation(
379 bitrate_kbps * 1000, kFramerate),
380 kFramerate));
381 }
382
383 void EncodeFrameAndVerifyLastName(const char* expected_name) {
384 EncodeFrameAndVerifyLastName(expected_name, WEBRTC_VIDEO_CODEC_OK);
385 }
386
387 void EncodeFrameAndVerifyLastName(const char* expected_name,
388 int expected_ret) {
389 EncodeFrame(expected_ret);
390 CheckLastEncoderName(expected_name);
391 }
392
393 rtc::ScopedFakeClock clock_;
394};
395
396class ForcedFallbackTestEnabled : public ForcedFallbackTest {
397 public:
398 ForcedFallbackTestEnabled()
Steve Antone78bcb92017-10-31 09:53:08 -0700399 : ForcedFallbackTest(std::string(kFieldTrial) + "/Enabled-" +
Åsa Persson45bbc8a2017-11-13 10:16:47 +0100400 std::to_string(kMinPixelsPerFrame) + "," +
401 std::to_string(kWidth * kHeight) + ",30000/") {}
asapersson22c76c42017-08-16 00:53:59 -0700402};
403
404class ForcedFallbackTestDisabled : public ForcedFallbackTest {
405 public:
406 ForcedFallbackTestDisabled()
Steve Antone78bcb92017-10-31 09:53:08 -0700407 : ForcedFallbackTest(std::string(kFieldTrial) + "/Disabled/") {}
asapersson22c76c42017-08-16 00:53:59 -0700408};
409
410TEST_F(ForcedFallbackTestDisabled, NoFallbackWithoutFieldTrial) {
Åsa Persson45bbc8a2017-11-13 10:16:47 +0100411 // Resolution above max threshold.
412 InitEncode(kWidth + 1, kHeight);
413 EXPECT_EQ(1, fake_encoder_->init_encode_count_);
asapersson22c76c42017-08-16 00:53:59 -0700414 EncodeFrameAndVerifyLastName("fake-encoder");
Åsa Persson45bbc8a2017-11-13 10:16:47 +0100415
416 // Resolution at max threshold.
417 InitEncode(kWidth, kHeight);
asapersson22c76c42017-08-16 00:53:59 -0700418 EncodeFrameAndVerifyLastName("fake-encoder");
419}
420
Åsa Persson45bbc8a2017-11-13 10:16:47 +0100421TEST_F(ForcedFallbackTestEnabled, FallbackIfAtMaxResolutionLimit) {
422 // Resolution above max threshold.
423 InitEncode(kWidth + 1, kHeight);
424 EXPECT_EQ(1, fake_encoder_->init_encode_count_);
asapersson22c76c42017-08-16 00:53:59 -0700425 EncodeFrameAndVerifyLastName("fake-encoder");
Åsa Persson45bbc8a2017-11-13 10:16:47 +0100426
427 // Resolution at max threshold.
428 InitEncode(kWidth, kHeight);
asapersson22c76c42017-08-16 00:53:59 -0700429 EncodeFrameAndVerifyLastName("libvpx");
430}
431
Åsa Persson45bbc8a2017-11-13 10:16:47 +0100432TEST_F(ForcedFallbackTestEnabled, FallbackIsKeptWhenInitEncodeIsCalled) {
433 // Resolution above max threshold.
434 InitEncode(kWidth + 1, kHeight);
435 EXPECT_EQ(1, fake_encoder_->init_encode_count_);
asapersson22c76c42017-08-16 00:53:59 -0700436 EncodeFrameAndVerifyLastName("fake-encoder");
asapersson22c76c42017-08-16 00:53:59 -0700437
Åsa Persson45bbc8a2017-11-13 10:16:47 +0100438 // Resolution at max threshold.
439 InitEncode(kWidth, kHeight);
440 EncodeFrameAndVerifyLastName("libvpx");
asapersson22c76c42017-08-16 00:53:59 -0700441
Åsa Persson45bbc8a2017-11-13 10:16:47 +0100442 // Re-initialize encoder, still expect fallback.
443 InitEncode(kWidth / 2, kHeight / 2);
444 EXPECT_EQ(1, fake_encoder_->init_encode_count_); // No change.
asapersson22c76c42017-08-16 00:53:59 -0700445 EncodeFrameAndVerifyLastName("libvpx");
446}
447
Åsa Persson45bbc8a2017-11-13 10:16:47 +0100448TEST_F(ForcedFallbackTestEnabled, FallbackIsEndedWhenResolutionIsTooLarge) {
449 // Resolution above max threshold.
450 InitEncode(kWidth + 1, kHeight);
451 EXPECT_EQ(1, fake_encoder_->init_encode_count_);
asapersson22c76c42017-08-16 00:53:59 -0700452 EncodeFrameAndVerifyLastName("fake-encoder");
453
Åsa Persson45bbc8a2017-11-13 10:16:47 +0100454 // Resolution at max threshold.
455 InitEncode(kWidth, kHeight);
asapersson22c76c42017-08-16 00:53:59 -0700456 EncodeFrameAndVerifyLastName("libvpx");
Åsa Persson45bbc8a2017-11-13 10:16:47 +0100457
458 // Re-initialize encoder with a larger resolution, expect no fallback.
459 InitEncode(kWidth + 1, kHeight);
460 EXPECT_EQ(2, fake_encoder_->init_encode_count_);
461 EncodeFrameAndVerifyLastName("fake-encoder");
asapersson22c76c42017-08-16 00:53:59 -0700462}
463
Åsa Persson45bbc8a2017-11-13 10:16:47 +0100464TEST_F(ForcedFallbackTestEnabled, FallbackIsEndedForNonValidSettings) {
465 // Resolution at max threshold.
466 InitEncode(kWidth, kHeight);
467 EncodeFrameAndVerifyLastName("libvpx");
468
469 // Re-initialize encoder with invalid setting, expect no fallback.
470 codec_.VP8()->numberOfTemporalLayers = 2;
471 InitEncode(kWidth, kHeight);
472 EXPECT_EQ(1, fake_encoder_->init_encode_count_);
asapersson22c76c42017-08-16 00:53:59 -0700473 EncodeFrameAndVerifyLastName("fake-encoder");
Åsa Persson45bbc8a2017-11-13 10:16:47 +0100474
475 // Re-initialize encoder with valid setting but fallback disabled from now on.
476 codec_.VP8()->numberOfTemporalLayers = 1;
477 InitEncode(kWidth, kHeight);
478 EXPECT_EQ(2, fake_encoder_->init_encode_count_);
asapersson22c76c42017-08-16 00:53:59 -0700479 EncodeFrameAndVerifyLastName("fake-encoder");
480}
481
482TEST_F(ForcedFallbackTestEnabled, MultipleStartEndFallback) {
483 const int kNumRuns = 5;
Åsa Persson45bbc8a2017-11-13 10:16:47 +0100484 for (int i = 1; i <= kNumRuns; ++i) {
485 // Resolution at max threshold.
486 InitEncode(kWidth, kHeight);
asapersson22c76c42017-08-16 00:53:59 -0700487 EncodeFrameAndVerifyLastName("libvpx");
Åsa Persson45bbc8a2017-11-13 10:16:47 +0100488 // Resolution above max threshold.
489 InitEncode(kWidth + 1, kHeight);
490 EXPECT_EQ(i, fake_encoder_->init_encode_count_);
asapersson22c76c42017-08-16 00:53:59 -0700491 EncodeFrameAndVerifyLastName("fake-encoder");
492 }
493}
494
Åsa Persson45bbc8a2017-11-13 10:16:47 +0100495TEST_F(ForcedFallbackTestDisabled, GetScaleSettings) {
496 // Resolution above max threshold.
497 InitEncode(kWidth + 1, kHeight);
498 EXPECT_EQ(1, fake_encoder_->init_encode_count_);
asapersson22c76c42017-08-16 00:53:59 -0700499 EncodeFrameAndVerifyLastName("fake-encoder");
500
asapersson142fcc92017-08-17 08:58:54 -0700501 // Default min pixels per frame should be used.
502 const auto settings = fallback_wrapper_.GetScalingSettings();
503 EXPECT_TRUE(settings.enabled);
504 EXPECT_EQ(kDefaultMinPixelsPerFrame, settings.min_pixels_per_frame);
505}
506
Åsa Persson45bbc8a2017-11-13 10:16:47 +0100507TEST_F(ForcedFallbackTestEnabled, GetScaleSettingsWithNoFallback) {
508 // Resolution above max threshold.
509 InitEncode(kWidth + 1, kHeight);
asapersson142fcc92017-08-17 08:58:54 -0700510 EncodeFrameAndVerifyLastName("fake-encoder");
Åsa Persson45bbc8a2017-11-13 10:16:47 +0100511
512 // Configured min pixels per frame should be used.
513 const auto settings = fallback_wrapper_.GetScalingSettings();
514 EXPECT_TRUE(settings.enabled);
515 EXPECT_EQ(kMinPixelsPerFrame, settings.min_pixels_per_frame);
516 ASSERT_TRUE(settings.thresholds);
517 EXPECT_EQ(kLowThreshold, settings.thresholds->low);
518 EXPECT_EQ(kHighThreshold, settings.thresholds->high);
519}
520
521TEST_F(ForcedFallbackTestEnabled, GetScaleSettingsWithFallback) {
522 // Resolution at max threshold.
523 InitEncode(kWidth, kHeight);
asapersson142fcc92017-08-17 08:58:54 -0700524 EncodeFrameAndVerifyLastName("libvpx");
Åsa Persson45bbc8a2017-11-13 10:16:47 +0100525
asapersson142fcc92017-08-17 08:58:54 -0700526 // Configured min pixels per frame should be used.
527 const auto settings = fallback_wrapper_.GetScalingSettings();
528 EXPECT_TRUE(settings.enabled);
529 EXPECT_EQ(kMinPixelsPerFrame, settings.min_pixels_per_frame);
530}
531
Åsa Persson45bbc8a2017-11-13 10:16:47 +0100532TEST_F(ForcedFallbackTestEnabled, ScalingDisabledIfResizeOff) {
533 // Resolution at max threshold.
534 codec_.VP8()->automaticResizeOn = false;
535 InitEncode(kWidth, kHeight);
asapersson142fcc92017-08-17 08:58:54 -0700536 EncodeFrameAndVerifyLastName("libvpx");
537
Åsa Persson45bbc8a2017-11-13 10:16:47 +0100538 // Should be disabled for automatic resize off.
539 const auto settings = fallback_wrapper_.GetScalingSettings();
540 EXPECT_FALSE(settings.enabled);
asapersson142fcc92017-08-17 08:58:54 -0700541}
542
Peter Boström4d71ede2015-05-19 23:09:35 +0200543} // namespace webrtc