blob: ecf719948f0b7911ef29391ee3904cbd684a5fed [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
magjed614d5b72016-11-15 06:30:54 -080011#include "webrtc/media/engine/videoencodersoftwarefallbackwrapper.h"
12
13#include <utility>
Peter Boström4d71ede2015-05-19 23:09:35 +020014
nisseaf916892017-01-10 07:44:26 -080015#include "webrtc/api/video/i420_buffer.h"
kjellandera8d8aad2017-03-08 05:42:26 -080016#include "webrtc/modules/video_coding/codecs/vp8/simulcast_rate_allocator.h"
Erik Språng08127a92016-11-16 16:41:30 +010017#include "webrtc/modules/video_coding/codecs/vp8/temporal_layers.h"
perkj275afc52016-09-01 00:21:16 -070018#include "webrtc/modules/video_coding/include/video_codec_interface.h"
Henrik Kjellander2557b862015-11-18 22:00:21 +010019#include "webrtc/modules/video_coding/include/video_error_codes.h"
Edward Lemurc20978e2017-07-06 19:44:34 +020020#include "webrtc/rtc_base/checks.h"
asapersson22c76c42017-08-16 00:53:59 -070021#include "webrtc/rtc_base/fakeclock.h"
22#include "webrtc/test/field_trial.h"
kwibergac9f8762016-09-30 22:29:43 -070023#include "webrtc/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;
asapersson22c76c42017-08-16 00:53:59 -070033} // namespace
Peter Boström4d71ede2015-05-19 23:09:35 +020034
35class VideoEncoderSoftwareFallbackWrapperTest : public ::testing::Test {
36 protected:
37 VideoEncoderSoftwareFallbackWrapperTest()
asapersson22c76c42017-08-16 00:53:59 -070038 : VideoEncoderSoftwareFallbackWrapperTest("") {}
39 explicit VideoEncoderSoftwareFallbackWrapperTest(
40 const std::string& field_trials)
41 : override_field_trials_(field_trials),
42 fallback_wrapper_(cricket::VideoCodec("VP8"), &fake_encoder_) {}
Peter Boström4d71ede2015-05-19 23:09:35 +020043
44 class CountingFakeEncoder : public VideoEncoder {
45 public:
46 int32_t InitEncode(const VideoCodec* codec_settings,
47 int32_t number_of_cores,
48 size_t max_payload_size) override {
49 ++init_encode_count_;
50 return init_encode_return_code_;
51 }
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -070052 int32_t Encode(const VideoFrame& frame,
Peter Boström4d71ede2015-05-19 23:09:35 +020053 const CodecSpecificInfo* codec_specific_info,
pbos22993e12015-10-19 02:39:06 -070054 const std::vector<FrameType>* frame_types) override {
Peter Boström4d71ede2015-05-19 23:09:35 +020055 ++encode_count_;
perkj275afc52016-09-01 00:21:16 -070056 if (encode_complete_callback_ &&
57 encode_return_code_ == WEBRTC_VIDEO_CODEC_OK) {
58 CodecSpecificInfo info;
59 info.codec_name = ImplementationName();
60 encode_complete_callback_->OnEncodedImage(EncodedImage(), &info,
61 nullptr);
62 }
noahricb1ce6632015-10-21 23:54:51 -070063 return encode_return_code_;
Peter Boström4d71ede2015-05-19 23:09:35 +020064 }
65
66 int32_t RegisterEncodeCompleteCallback(
67 EncodedImageCallback* callback) override {
68 encode_complete_callback_ = callback;
69 return WEBRTC_VIDEO_CODEC_OK;
70 }
71
72 int32_t Release() override {
73 ++release_count_;
74 return WEBRTC_VIDEO_CODEC_OK;
75 }
76
77 int32_t SetChannelParameters(uint32_t packet_loss, int64_t rtt) override {
78 ++set_channel_parameters_count_;
79 return WEBRTC_VIDEO_CODEC_OK;
80 }
81
Erik Språng08127a92016-11-16 16:41:30 +010082 int32_t SetRateAllocation(const BitrateAllocation& bitrate_allocation,
83 uint32_t framerate) override {
Peter Boström4d71ede2015-05-19 23:09:35 +020084 ++set_rates_count_;
85 return WEBRTC_VIDEO_CODEC_OK;
86 }
87
Peter Boströmeb66e802015-06-05 11:08:03 +020088 bool SupportsNativeHandle() const override {
89 ++supports_native_handle_count_;
asapersson22c76c42017-08-16 00:53:59 -070090 return supports_native_handle_;
Peter Boströmeb66e802015-06-05 11:08:03 +020091 }
92
Peter Boströmb7d9a972015-12-18 16:01:11 +010093 const char* ImplementationName() const override {
94 return "fake-encoder";
95 }
96
asapersson142fcc92017-08-17 08:58:54 -070097 VideoEncoder::ScalingSettings GetScalingSettings() const override {
98 return VideoEncoder::ScalingSettings(true);
99 }
100
Peter Boström4d71ede2015-05-19 23:09:35 +0200101 int init_encode_count_ = 0;
102 int32_t init_encode_return_code_ = WEBRTC_VIDEO_CODEC_OK;
noahricb1ce6632015-10-21 23:54:51 -0700103 int32_t encode_return_code_ = WEBRTC_VIDEO_CODEC_OK;
Peter Boström4d71ede2015-05-19 23:09:35 +0200104 int encode_count_ = 0;
105 EncodedImageCallback* encode_complete_callback_ = nullptr;
106 int release_count_ = 0;
107 int set_channel_parameters_count_ = 0;
108 int set_rates_count_ = 0;
Peter Boströmeb66e802015-06-05 11:08:03 +0200109 mutable int supports_native_handle_count_ = 0;
asapersson22c76c42017-08-16 00:53:59 -0700110 bool supports_native_handle_ = false;
Peter Boström4d71ede2015-05-19 23:09:35 +0200111 };
112
113 class FakeEncodedImageCallback : public EncodedImageCallback {
114 public:
Sergey Ulanov525df3f2016-08-02 17:46:41 -0700115 Result OnEncodedImage(
116 const EncodedImage& encoded_image,
117 const CodecSpecificInfo* codec_specific_info,
118 const RTPFragmentationHeader* fragmentation) override {
119 ++callback_count_;
perkj275afc52016-09-01 00:21:16 -0700120 last_codec_name_ = codec_specific_info->codec_name;
Sergey Ulanov525df3f2016-08-02 17:46:41 -0700121 return Result(Result::OK, callback_count_);
Peter Boström4d71ede2015-05-19 23:09:35 +0200122 }
123 int callback_count_ = 0;
perkj275afc52016-09-01 00:21:16 -0700124 std::string last_codec_name_;
Peter Boström4d71ede2015-05-19 23:09:35 +0200125 };
126
127 void UtilizeFallbackEncoder();
noahricb1ce6632015-10-21 23:54:51 -0700128 void FallbackFromEncodeRequest();
129 void EncodeFrame();
asapersson22c76c42017-08-16 00:53:59 -0700130 void EncodeFrame(int expected_ret);
perkj275afc52016-09-01 00:21:16 -0700131 void CheckLastEncoderName(const char* expected_name) {
132 EXPECT_STREQ(expected_name, callback_.last_codec_name_.c_str());
133 }
Peter Boström4d71ede2015-05-19 23:09:35 +0200134
asapersson22c76c42017-08-16 00:53:59 -0700135 test::ScopedFieldTrials override_field_trials_;
Peter Boström4d71ede2015-05-19 23:09:35 +0200136 FakeEncodedImageCallback callback_;
137 CountingFakeEncoder fake_encoder_;
138 VideoEncoderSoftwareFallbackWrapper fallback_wrapper_;
139 VideoCodec codec_ = {};
nisse64ec8f82016-09-27 00:17:25 -0700140 std::unique_ptr<VideoFrame> frame_;
Erik Språng08127a92016-11-16 16:41:30 +0100141 std::unique_ptr<SimulcastRateAllocator> rate_allocator_;
Peter Boström4d71ede2015-05-19 23:09:35 +0200142};
143
noahricb1ce6632015-10-21 23:54:51 -0700144void VideoEncoderSoftwareFallbackWrapperTest::EncodeFrame() {
asapersson22c76c42017-08-16 00:53:59 -0700145 EncodeFrame(WEBRTC_VIDEO_CODEC_OK);
146}
147
148void VideoEncoderSoftwareFallbackWrapperTest::EncodeFrame(int expected_ret) {
asapersson142fcc92017-08-17 08:58:54 -0700149 rtc::scoped_refptr<I420Buffer> buffer =
150 I420Buffer::Create(codec_.width, codec_.height);
nisseaf916892017-01-10 07:44:26 -0800151 I420Buffer::SetBlack(buffer);
nisse776870a2016-09-21 03:52:16 -0700152 std::vector<FrameType> types(1, kVideoFrameKey);
nisse64ec8f82016-09-27 00:17:25 -0700153
154 frame_.reset(new VideoFrame(buffer, 0, 0, webrtc::kVideoRotation_0));
asapersson22c76c42017-08-16 00:53:59 -0700155 EXPECT_EQ(expected_ret, fallback_wrapper_.Encode(*frame_, nullptr, &types));
noahricb1ce6632015-10-21 23:54:51 -0700156}
157
Peter Boström4d71ede2015-05-19 23:09:35 +0200158void VideoEncoderSoftwareFallbackWrapperTest::UtilizeFallbackEncoder() {
Peter Boström4d71ede2015-05-19 23:09:35 +0200159 fallback_wrapper_.RegisterEncodeCompleteCallback(&callback_);
160 EXPECT_EQ(&callback_, fake_encoder_.encode_complete_callback_);
161
162 // Register with failing fake encoder. Should succeed with VP8 fallback.
163 codec_.codecType = kVideoCodecVP8;
asapersson22c76c42017-08-16 00:53:59 -0700164 codec_.maxFramerate = kFramerate;
Peter Boström4d71ede2015-05-19 23:09:35 +0200165 codec_.width = kWidth;
166 codec_.height = kHeight;
Erik Språng08127a92016-11-16 16:41:30 +0100167 codec_.VP8()->numberOfTemporalLayers = 1;
168 std::unique_ptr<TemporalLayersFactory> tl_factory(
169 new TemporalLayersFactory());
170 codec_.VP8()->tl_factory = tl_factory.get();
171 rate_allocator_.reset(
172 new SimulcastRateAllocator(codec_, std::move(tl_factory)));
173
Peter Boström4d71ede2015-05-19 23:09:35 +0200174 fake_encoder_.init_encode_return_code_ = WEBRTC_VIDEO_CODEC_ERROR;
175 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK,
asapersson22c76c42017-08-16 00:53:59 -0700176 fallback_wrapper_.InitEncode(&codec_, kNumCores, kMaxPayloadSize));
177 EXPECT_EQ(
178 WEBRTC_VIDEO_CODEC_OK,
179 fallback_wrapper_.SetRateAllocation(
180 rate_allocator_->GetAllocation(300000, kFramerate), kFramerate));
Peter Boström4d71ede2015-05-19 23:09:35 +0200181
noahricb1ce6632015-10-21 23:54:51 -0700182 int callback_count = callback_.callback_count_;
183 int encode_count = fake_encoder_.encode_count_;
184 EncodeFrame();
185 EXPECT_EQ(encode_count, fake_encoder_.encode_count_);
186 EXPECT_EQ(callback_count + 1, callback_.callback_count_);
187}
Peter Boström4d71ede2015-05-19 23:09:35 +0200188
noahricb1ce6632015-10-21 23:54:51 -0700189void VideoEncoderSoftwareFallbackWrapperTest::FallbackFromEncodeRequest() {
190 fallback_wrapper_.RegisterEncodeCompleteCallback(&callback_);
191 codec_.codecType = kVideoCodecVP8;
asapersson22c76c42017-08-16 00:53:59 -0700192 codec_.maxFramerate = kFramerate;
noahricb1ce6632015-10-21 23:54:51 -0700193 codec_.width = kWidth;
194 codec_.height = kHeight;
Erik Språng08127a92016-11-16 16:41:30 +0100195 codec_.VP8()->numberOfTemporalLayers = 1;
196 std::unique_ptr<TemporalLayersFactory> tl_factory(
197 new TemporalLayersFactory());
198 codec_.VP8()->tl_factory = tl_factory.get();
199 rate_allocator_.reset(
200 new SimulcastRateAllocator(codec_, std::move(tl_factory)));
noahricb1ce6632015-10-21 23:54:51 -0700201 fallback_wrapper_.InitEncode(&codec_, 2, kMaxPayloadSize);
asapersson22c76c42017-08-16 00:53:59 -0700202 EXPECT_EQ(
203 WEBRTC_VIDEO_CODEC_OK,
204 fallback_wrapper_.SetRateAllocation(
205 rate_allocator_->GetAllocation(300000, kFramerate), kFramerate));
noahricb1ce6632015-10-21 23:54:51 -0700206 EXPECT_EQ(1, fake_encoder_.init_encode_count_);
207
208 // Have the non-fallback encoder request a software fallback.
209 fake_encoder_.encode_return_code_ = WEBRTC_VIDEO_CODEC_FALLBACK_SOFTWARE;
210 int callback_count = callback_.callback_count_;
211 int encode_count = fake_encoder_.encode_count_;
212 EncodeFrame();
213 // Single encode request, which returned failure.
214 EXPECT_EQ(encode_count + 1, fake_encoder_.encode_count_);
215 EXPECT_EQ(callback_count + 1, callback_.callback_count_);
Peter Boström4d71ede2015-05-19 23:09:35 +0200216}
217
218TEST_F(VideoEncoderSoftwareFallbackWrapperTest, InitializesEncoder) {
219 VideoCodec codec = {};
220 fallback_wrapper_.InitEncode(&codec, 2, kMaxPayloadSize);
221 EXPECT_EQ(1, fake_encoder_.init_encode_count_);
222}
223
noahricb1ce6632015-10-21 23:54:51 -0700224TEST_F(VideoEncoderSoftwareFallbackWrapperTest, EncodeRequestsFallback) {
225 FallbackFromEncodeRequest();
226 // After fallback, further encodes shouldn't hit the fake encoder.
227 int encode_count = fake_encoder_.encode_count_;
228 EncodeFrame();
229 EXPECT_EQ(encode_count, fake_encoder_.encode_count_);
230}
231
Peter Boström4d71ede2015-05-19 23:09:35 +0200232TEST_F(VideoEncoderSoftwareFallbackWrapperTest, CanUtilizeFallbackEncoder) {
233 UtilizeFallbackEncoder();
234 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, fallback_wrapper_.Release());
235}
236
237TEST_F(VideoEncoderSoftwareFallbackWrapperTest,
noahricb1ce6632015-10-21 23:54:51 -0700238 InternalEncoderReleasedDuringFallback) {
Peter Boström4d71ede2015-05-19 23:09:35 +0200239 EXPECT_EQ(0, fake_encoder_.release_count_);
noahricb1ce6632015-10-21 23:54:51 -0700240 UtilizeFallbackEncoder();
241 EXPECT_EQ(1, fake_encoder_.release_count_);
242 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, fallback_wrapper_.Release());
243 // No extra release when the fallback is released.
244 EXPECT_EQ(1, fake_encoder_.release_count_);
Peter Boström4d71ede2015-05-19 23:09:35 +0200245}
246
247TEST_F(VideoEncoderSoftwareFallbackWrapperTest,
248 InternalEncoderNotEncodingDuringFallback) {
249 UtilizeFallbackEncoder();
noahricb1ce6632015-10-21 23:54:51 -0700250 int encode_count = fake_encoder_.encode_count_;
251 EncodeFrame();
252 EXPECT_EQ(encode_count, fake_encoder_.encode_count_);
Peter Boström4d71ede2015-05-19 23:09:35 +0200253
254 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, fallback_wrapper_.Release());
255}
256
257TEST_F(VideoEncoderSoftwareFallbackWrapperTest,
258 CanRegisterCallbackWhileUsingFallbackEncoder) {
259 UtilizeFallbackEncoder();
260 // Registering an encode-complete callback should still work when fallback
261 // encoder is being used.
262 FakeEncodedImageCallback callback2;
263 fallback_wrapper_.RegisterEncodeCompleteCallback(&callback2);
264 EXPECT_EQ(&callback2, fake_encoder_.encode_complete_callback_);
265
266 // Encoding a frame using the fallback should arrive at the new callback.
Peter Boström49e196a2015-10-23 15:58:18 +0200267 std::vector<FrameType> types(1, kVideoFrameKey);
nisse64ec8f82016-09-27 00:17:25 -0700268 frame_->set_timestamp(frame_->timestamp() + 1000);
Peter Boström4d71ede2015-05-19 23:09:35 +0200269 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK,
nisse64ec8f82016-09-27 00:17:25 -0700270 fallback_wrapper_.Encode(*frame_, nullptr, &types));
Peter Boström4d71ede2015-05-19 23:09:35 +0200271
272 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, fallback_wrapper_.Release());
273}
274
275TEST_F(VideoEncoderSoftwareFallbackWrapperTest,
276 SetChannelParametersForwardedDuringFallback) {
277 UtilizeFallbackEncoder();
278 EXPECT_EQ(0, fake_encoder_.set_channel_parameters_count_);
279 fallback_wrapper_.SetChannelParameters(1, 1);
280 EXPECT_EQ(1, fake_encoder_.set_channel_parameters_count_);
281 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, fallback_wrapper_.Release());
282}
283
284TEST_F(VideoEncoderSoftwareFallbackWrapperTest,
285 SetRatesForwardedDuringFallback) {
286 UtilizeFallbackEncoder();
287 EXPECT_EQ(1, fake_encoder_.set_rates_count_);
Erik Språng08127a92016-11-16 16:41:30 +0100288 fallback_wrapper_.SetRateAllocation(BitrateAllocation(), 1);
Peter Boström4d71ede2015-05-19 23:09:35 +0200289 EXPECT_EQ(2, fake_encoder_.set_rates_count_);
290 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, fallback_wrapper_.Release());
291}
292
293TEST_F(VideoEncoderSoftwareFallbackWrapperTest,
Peter Boströmeb66e802015-06-05 11:08:03 +0200294 SupportsNativeHandleForwardedWithoutFallback) {
295 fallback_wrapper_.SupportsNativeHandle();
296 EXPECT_EQ(1, fake_encoder_.supports_native_handle_count_);
297}
298
299TEST_F(VideoEncoderSoftwareFallbackWrapperTest,
300 SupportsNativeHandleNotForwardedDuringFallback) {
301 UtilizeFallbackEncoder();
302 fallback_wrapper_.SupportsNativeHandle();
303 EXPECT_EQ(0, fake_encoder_.supports_native_handle_count_);
304 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, fallback_wrapper_.Release());
305}
306
perkj275afc52016-09-01 00:21:16 -0700307TEST_F(VideoEncoderSoftwareFallbackWrapperTest, ReportsImplementationName) {
asapersson142fcc92017-08-17 08:58:54 -0700308 codec_.width = kWidth;
309 codec_.height = kHeight;
perkj275afc52016-09-01 00:21:16 -0700310 fallback_wrapper_.RegisterEncodeCompleteCallback(&callback_);
asapersson142fcc92017-08-17 08:58:54 -0700311 fallback_wrapper_.InitEncode(&codec_, kNumCores, kMaxPayloadSize);
perkj275afc52016-09-01 00:21:16 -0700312 EncodeFrame();
313 CheckLastEncoderName("fake-encoder");
314}
315
Peter Boströmb7d9a972015-12-18 16:01:11 +0100316TEST_F(VideoEncoderSoftwareFallbackWrapperTest,
317 ReportsFallbackImplementationName) {
318 UtilizeFallbackEncoder();
319 // Hard coded expected value since libvpx is the software implementation name
320 // for VP8. Change accordingly if the underlying implementation does.
perkj275afc52016-09-01 00:21:16 -0700321 CheckLastEncoderName("libvpx");
Peter Boströmb7d9a972015-12-18 16:01:11 +0100322}
323
asapersson22c76c42017-08-16 00:53:59 -0700324namespace {
325const int kLowKbps = 220;
326const int kHighKbps = 300;
327const int kMinLowDurationMs = 4000;
asapersson142fcc92017-08-17 08:58:54 -0700328const int kMinPixelsPerFrame = 1;
329const int kMinPixelsStop = 320 * 180;
asapersson22c76c42017-08-16 00:53:59 -0700330const std::string kFieldTrial = "WebRTC-VP8-Forced-Fallback-Encoder";
331} // namespace
332
333class ForcedFallbackTest : public VideoEncoderSoftwareFallbackWrapperTest {
334 public:
335 ForcedFallbackTest(const std::string& field_trials)
336 : VideoEncoderSoftwareFallbackWrapperTest(field_trials) {}
337
338 ~ForcedFallbackTest() override {}
339
340 protected:
341 void SetUp() override {
342 clock_.SetTimeMicros(1234);
343 ConfigureVp8Codec();
344 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, fallback_wrapper_.InitEncode(
345 &codec_, kNumCores, kMaxPayloadSize));
346 EXPECT_EQ(1, fake_encoder_.init_encode_count_);
347 }
348
349 void TearDown() override {
350 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, fallback_wrapper_.Release());
351 }
352
353 void ConfigureVp8Codec() {
354 fallback_wrapper_.RegisterEncodeCompleteCallback(&callback_);
355 std::unique_ptr<TemporalLayersFactory> tl_factory(
356 new TemporalLayersFactory());
357 codec_.codecType = kVideoCodecVP8;
358 codec_.maxFramerate = kFramerate;
359 codec_.width = kWidth;
360 codec_.height = kHeight;
361 codec_.VP8()->numberOfTemporalLayers = 1;
asapersson142fcc92017-08-17 08:58:54 -0700362 codec_.VP8()->automaticResizeOn = true;
363 codec_.VP8()->frameDroppingOn = true;
asapersson22c76c42017-08-16 00:53:59 -0700364 codec_.VP8()->tl_factory = tl_factory.get();
365 rate_allocator_.reset(
366 new SimulcastRateAllocator(codec_, std::move(tl_factory)));
367 }
368
369 void SetRateAllocation(uint32_t bitrate_kbps) {
370 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, fallback_wrapper_.SetRateAllocation(
371 rate_allocator_->GetAllocation(
372 bitrate_kbps * 1000, kFramerate),
373 kFramerate));
374 }
375
376 void EncodeFrameAndVerifyLastName(const char* expected_name) {
377 EncodeFrameAndVerifyLastName(expected_name, WEBRTC_VIDEO_CODEC_OK);
378 }
379
380 void EncodeFrameAndVerifyLastName(const char* expected_name,
381 int expected_ret) {
382 EncodeFrame(expected_ret);
383 CheckLastEncoderName(expected_name);
384 }
385
386 rtc::ScopedFakeClock clock_;
387};
388
389class ForcedFallbackTestEnabled : public ForcedFallbackTest {
390 public:
391 ForcedFallbackTestEnabled()
392 : ForcedFallbackTest(kFieldTrial + "/Enabled-" +
393 std::to_string(kLowKbps) + "," +
394 std::to_string(kHighKbps) + "," +
asapersson142fcc92017-08-17 08:58:54 -0700395 std::to_string(kMinLowDurationMs) + "," +
396 std::to_string(kMinPixelsPerFrame) + "/") {}
asapersson22c76c42017-08-16 00:53:59 -0700397};
398
399class ForcedFallbackTestDisabled : public ForcedFallbackTest {
400 public:
401 ForcedFallbackTestDisabled()
402 : ForcedFallbackTest(kFieldTrial + "/Disabled/") {}
403};
404
405TEST_F(ForcedFallbackTestDisabled, NoFallbackWithoutFieldTrial) {
406 // Bitrate at low threshold.
407 SetRateAllocation(kLowKbps);
408 EncodeFrameAndVerifyLastName("fake-encoder");
409 // Duration passed, expect no fallback.
410 clock_.AdvanceTime(rtc::TimeDelta::FromMilliseconds(kMinLowDurationMs));
411 EncodeFrameAndVerifyLastName("fake-encoder");
412}
413
414TEST_F(ForcedFallbackTestEnabled, FallbackIfAtLowLimit) {
415 // Bitrate at low threshold.
416 SetRateAllocation(kLowKbps);
417 EncodeFrameAndVerifyLastName("fake-encoder");
418 // Duration passed, expect fallback.
419 clock_.AdvanceTime(rtc::TimeDelta::FromMilliseconds(kMinLowDurationMs));
420 EncodeFrameAndVerifyLastName("libvpx");
421}
422
423TEST_F(ForcedFallbackTestEnabled, NoFallbackIfNotAtLowLimit) {
424 // Bitrate above low threshold.
425 SetRateAllocation(kLowKbps + 1);
426 EncodeFrameAndVerifyLastName("fake-encoder");
427 // Duration passed, expect no fallback.
428 clock_.AdvanceTime(rtc::TimeDelta::FromMilliseconds(kMinLowDurationMs));
429 EncodeFrameAndVerifyLastName("fake-encoder");
430}
431
432TEST_F(ForcedFallbackTestEnabled, NoFallbackIfResolutionIsTooLarge) {
433 // Resolution above max pixels.
434 codec_.width += 1;
435 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK,
436 fallback_wrapper_.InitEncode(&codec_, kNumCores, kMaxPayloadSize));
437 // Bitrate at low threshold.
438 SetRateAllocation(kLowKbps);
439 EncodeFrameAndVerifyLastName("fake-encoder");
440 // Duration passed, expect no fallback.
441 clock_.AdvanceTime(rtc::TimeDelta::FromMilliseconds(kMinLowDurationMs));
442 EncodeFrameAndVerifyLastName("fake-encoder");
443}
444
445TEST_F(ForcedFallbackTestEnabled, FallbackIfMinDurationPassed) {
446 // Bitrate at low threshold.
447 SetRateAllocation(kLowKbps);
448 EncodeFrameAndVerifyLastName("fake-encoder");
449 // Duration not passed, expect no fallback.
450 clock_.AdvanceTime(rtc::TimeDelta::FromMilliseconds(kMinLowDurationMs - 1));
451 EncodeFrameAndVerifyLastName("fake-encoder");
452 // Duration passed, expect fallback.
453 clock_.AdvanceTime(rtc::TimeDelta::FromMilliseconds(1));
454 EncodeFrameAndVerifyLastName("libvpx");
455}
456
457TEST_F(ForcedFallbackTestEnabled, FallbackStartTimeResetIfAboveLowLimit) {
458 // Bitrate at low threshold, start time set.
459 SetRateAllocation(kLowKbps);
460 EncodeFrameAndVerifyLastName("fake-encoder");
461 // Duration not passed, expect no fallback.
462 clock_.AdvanceTime(rtc::TimeDelta::FromMilliseconds(kMinLowDurationMs - 1));
463 EncodeFrameAndVerifyLastName("fake-encoder");
464
465 // Bitrate above low threshold, start time reset.
466 SetRateAllocation(kLowKbps + 1);
467 clock_.AdvanceTime(rtc::TimeDelta::FromMilliseconds(1));
468 EncodeFrameAndVerifyLastName("fake-encoder");
469
470 // Bitrate at low threshold, start time set.
471 SetRateAllocation(kLowKbps);
472 EncodeFrameAndVerifyLastName("fake-encoder");
473 // Duration not passed, expect no fallback.
474 clock_.AdvanceTime(rtc::TimeDelta::FromMilliseconds(kMinLowDurationMs - 1));
475 EncodeFrameAndVerifyLastName("fake-encoder");
476 // Duration passed, expect fallback.
477 clock_.AdvanceTime(rtc::TimeDelta::FromMilliseconds(1));
478 EncodeFrameAndVerifyLastName("libvpx");
479}
480
481TEST_F(ForcedFallbackTestEnabled, FallbackEndsIfAtHighLimit) {
482 // Bitrate at low threshold.
483 SetRateAllocation(kLowKbps);
484 EncodeFrameAndVerifyLastName("fake-encoder");
485 // Duration passed, expect fallback.
486 clock_.AdvanceTime(rtc::TimeDelta::FromMilliseconds(kMinLowDurationMs));
487 EncodeFrameAndVerifyLastName("libvpx");
488 // Bitrate below high threshold, expect fallback.
489 SetRateAllocation(kHighKbps - 1);
490 EncodeFrameAndVerifyLastName("libvpx");
491 // Bitrate at high threshold, expect fallback ended.
492 SetRateAllocation(kHighKbps);
493 EncodeFrameAndVerifyLastName("fake-encoder");
494}
495
496TEST_F(ForcedFallbackTestEnabled, MultipleStartEndFallback) {
497 const int kNumRuns = 5;
498 for (int i = 0; i < kNumRuns; ++i) {
499 // Bitrate at low threshold.
500 SetRateAllocation(kLowKbps);
501 EncodeFrameAndVerifyLastName("fake-encoder");
502 // Duration passed, expect fallback.
503 clock_.AdvanceTime(rtc::TimeDelta::FromMilliseconds(kMinLowDurationMs));
504 EncodeFrameAndVerifyLastName("libvpx");
505 // Bitrate at high threshold, expect fallback ended.
506 SetRateAllocation(kHighKbps);
507 EncodeFrameAndVerifyLastName("fake-encoder");
508 }
509}
510
511TEST_F(ForcedFallbackTestEnabled, DropsFirstNonNativeFrameAfterFallbackEnds) {
512 fake_encoder_.supports_native_handle_ = true;
513
514 // Bitrate at low threshold.
515 SetRateAllocation(kLowKbps);
516 EncodeFrameAndVerifyLastName("fake-encoder");
517 // Duration passed, expect fallback.
518 clock_.AdvanceTime(rtc::TimeDelta::FromMilliseconds(kMinLowDurationMs));
519 EncodeFrameAndVerifyLastName("libvpx");
520 // Bitrate at high threshold, fallback should be ended but first non-native
521 // frame dropped (i.e. frame not encoded).
522 SetRateAllocation(kHighKbps);
523 EncodeFrameAndVerifyLastName("libvpx", WEBRTC_VIDEO_CODEC_ERROR);
524 // Next frame should be encoded.
525 EncodeFrameAndVerifyLastName("fake-encoder");
526}
527
528TEST_F(ForcedFallbackTestEnabled, FallbackIsKeptWhenInitEncodeIsCalled) {
529 // Bitrate below low threshold.
530 SetRateAllocation(kLowKbps - 1);
531 EncodeFrameAndVerifyLastName("fake-encoder");
532 // Duration passed, expect fallback.
533 clock_.AdvanceTime(rtc::TimeDelta::FromMilliseconds(kMinLowDurationMs));
534 EncodeFrameAndVerifyLastName("libvpx");
535
536 // Re-initialize encoder, still expect fallback.
537 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK,
538 fallback_wrapper_.InitEncode(&codec_, kNumCores, kMaxPayloadSize));
539 EXPECT_EQ(1, fake_encoder_.init_encode_count_); // No change.
540 SetRateAllocation(kLowKbps);
541 EncodeFrameAndVerifyLastName("libvpx");
542}
543
544TEST_F(ForcedFallbackTestEnabled, FallbackIsEndedWhenResolutionIsTooLarge) {
545 // Bitrate below low threshold.
546 SetRateAllocation(kLowKbps - 1);
547 EncodeFrameAndVerifyLastName("fake-encoder");
548 // Duration passed, expect fallback.
549 clock_.AdvanceTime(rtc::TimeDelta::FromMilliseconds(kMinLowDurationMs));
550 EncodeFrameAndVerifyLastName("libvpx");
551
552 // Re-initialize encoder with a larger resolution, expect no fallback.
553 codec_.width += 1;
554 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK,
555 fallback_wrapper_.InitEncode(&codec_, kNumCores, kMaxPayloadSize));
556 EXPECT_EQ(2, fake_encoder_.init_encode_count_);
557 SetRateAllocation(kLowKbps);
558 EncodeFrameAndVerifyLastName("fake-encoder");
559}
560
561TEST_F(ForcedFallbackTestEnabled, FallbackIsEndedForNonValidSettings) {
562 // Bitrate below low threshold.
563 SetRateAllocation(kLowKbps - 1);
564 EncodeFrameAndVerifyLastName("fake-encoder");
565 // Duration passed, expect fallback.
566 clock_.AdvanceTime(rtc::TimeDelta::FromMilliseconds(kMinLowDurationMs));
567 EncodeFrameAndVerifyLastName("libvpx");
568
569 // Re-initialize encoder with invalid setting, expect no fallback.
570 codec_.VP8()->numberOfTemporalLayers = 2;
571 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK,
572 fallback_wrapper_.InitEncode(&codec_, kNumCores, kMaxPayloadSize));
573 EXPECT_EQ(2, fake_encoder_.init_encode_count_);
574 SetRateAllocation(kLowKbps);
575 EncodeFrameAndVerifyLastName("fake-encoder");
576
577 // Re-initialize encoder with valid setting but fallback disabled from now on.
578 codec_.VP8()->numberOfTemporalLayers = 1;
579 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK,
580 fallback_wrapper_.InitEncode(&codec_, kNumCores, kMaxPayloadSize));
581 EXPECT_EQ(3, fake_encoder_.init_encode_count_);
582 // Bitrate at low threshold.
583 SetRateAllocation(kLowKbps);
584 EncodeFrameAndVerifyLastName("fake-encoder");
585 // Duration passed, expect no fallback.
586 clock_.AdvanceTime(rtc::TimeDelta::FromMilliseconds(kMinLowDurationMs));
587 EncodeFrameAndVerifyLastName("fake-encoder");
588}
589
asapersson142fcc92017-08-17 08:58:54 -0700590TEST_F(ForcedFallbackTestEnabled, GetScaleSettingsWithoutFallback) {
591 // Bitrate at low threshold.
592 SetRateAllocation(kLowKbps);
593 EncodeFrameAndVerifyLastName("fake-encoder");
594 // Default min pixels per frame should be used.
595 const auto settings = fallback_wrapper_.GetScalingSettings();
596 EXPECT_TRUE(settings.enabled);
597 EXPECT_EQ(kDefaultMinPixelsPerFrame, settings.min_pixels_per_frame);
598}
599
600TEST_F(ForcedFallbackTestEnabled, GetScaleSettingsWithFallback) {
601 // Bitrate at low threshold.
602 SetRateAllocation(kLowKbps);
603 EncodeFrameAndVerifyLastName("fake-encoder");
604 // Duration passed, expect fallback.
605 clock_.AdvanceTime(rtc::TimeDelta::FromMilliseconds(kMinLowDurationMs));
606 EncodeFrameAndVerifyLastName("libvpx");
607 // Configured min pixels per frame should be used.
608 const auto settings = fallback_wrapper_.GetScalingSettings();
609 EXPECT_TRUE(settings.enabled);
610 EXPECT_EQ(kMinPixelsPerFrame, settings.min_pixels_per_frame);
611}
612
613TEST_F(ForcedFallbackTestEnabled, FallbackIsKeptIfResolutionIsTooSmall) {
614 // Bitrate at low threshold.
615 SetRateAllocation(kLowKbps);
616 EncodeFrameAndVerifyLastName("fake-encoder");
617 // Duration passed, expect fallback.
618 clock_.AdvanceTime(rtc::TimeDelta::FromMilliseconds(kMinLowDurationMs));
619 EncodeFrameAndVerifyLastName("libvpx");
620
621 // Re-initialize encoder with a resolution less than |kMinPixelsStop|.
622 codec_.height = kMinPixelsStop / codec_.width - 1;
623 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK,
624 fallback_wrapper_.InitEncode(&codec_, kNumCores, kMaxPayloadSize));
625 EXPECT_EQ(1, fake_encoder_.init_encode_count_); // No change
626 SetRateAllocation(kHighKbps - 1);
627 EncodeFrameAndVerifyLastName("libvpx");
628 // Bitrate at high threshold but resolution too small for fallback to end.
629 SetRateAllocation(kHighKbps);
630 EncodeFrameAndVerifyLastName("libvpx");
631
632 // Re-initialize encoder with a resolution equal to |kMinPixelsStop|.
633 codec_.height++;
634 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK,
635 fallback_wrapper_.InitEncode(&codec_, kNumCores, kMaxPayloadSize));
636 EXPECT_EQ(1, fake_encoder_.init_encode_count_); // No change
637 SetRateAllocation(kHighKbps - 1);
638 EncodeFrameAndVerifyLastName("libvpx");
639 // Bitrate at high threshold and resolution large enough for fallback to end.
640 SetRateAllocation(kHighKbps);
641 EncodeFrameAndVerifyLastName("fake-encoder");
642}
643
Peter Boström4d71ede2015-05-19 23:09:35 +0200644} // namespace webrtc