blob: f66551958fcabcd982e1c9937e8a9c579839c429 [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;
asapersson22c76c42017-08-16 00:53:59 -070032} // namespace
Peter Boström4d71ede2015-05-19 23:09:35 +020033
34class VideoEncoderSoftwareFallbackWrapperTest : public ::testing::Test {
35 protected:
36 VideoEncoderSoftwareFallbackWrapperTest()
asapersson22c76c42017-08-16 00:53:59 -070037 : VideoEncoderSoftwareFallbackWrapperTest("") {}
38 explicit VideoEncoderSoftwareFallbackWrapperTest(
39 const std::string& field_trials)
40 : override_field_trials_(field_trials),
41 fallback_wrapper_(cricket::VideoCodec("VP8"), &fake_encoder_) {}
Peter Boström4d71ede2015-05-19 23:09:35 +020042
43 class CountingFakeEncoder : public VideoEncoder {
44 public:
45 int32_t InitEncode(const VideoCodec* codec_settings,
46 int32_t number_of_cores,
47 size_t max_payload_size) override {
48 ++init_encode_count_;
49 return init_encode_return_code_;
50 }
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -070051 int32_t Encode(const VideoFrame& frame,
Peter Boström4d71ede2015-05-19 23:09:35 +020052 const CodecSpecificInfo* codec_specific_info,
pbos22993e12015-10-19 02:39:06 -070053 const std::vector<FrameType>* frame_types) override {
Peter Boström4d71ede2015-05-19 23:09:35 +020054 ++encode_count_;
perkj275afc52016-09-01 00:21:16 -070055 if (encode_complete_callback_ &&
56 encode_return_code_ == WEBRTC_VIDEO_CODEC_OK) {
57 CodecSpecificInfo info;
58 info.codec_name = ImplementationName();
59 encode_complete_callback_->OnEncodedImage(EncodedImage(), &info,
60 nullptr);
61 }
noahricb1ce6632015-10-21 23:54:51 -070062 return encode_return_code_;
Peter Boström4d71ede2015-05-19 23:09:35 +020063 }
64
65 int32_t RegisterEncodeCompleteCallback(
66 EncodedImageCallback* callback) override {
67 encode_complete_callback_ = callback;
68 return WEBRTC_VIDEO_CODEC_OK;
69 }
70
71 int32_t Release() override {
72 ++release_count_;
73 return WEBRTC_VIDEO_CODEC_OK;
74 }
75
76 int32_t SetChannelParameters(uint32_t packet_loss, int64_t rtt) override {
77 ++set_channel_parameters_count_;
78 return WEBRTC_VIDEO_CODEC_OK;
79 }
80
Erik Språng08127a92016-11-16 16:41:30 +010081 int32_t SetRateAllocation(const BitrateAllocation& bitrate_allocation,
82 uint32_t framerate) override {
Peter Boström4d71ede2015-05-19 23:09:35 +020083 ++set_rates_count_;
84 return WEBRTC_VIDEO_CODEC_OK;
85 }
86
Peter Boströmeb66e802015-06-05 11:08:03 +020087 bool SupportsNativeHandle() const override {
88 ++supports_native_handle_count_;
asapersson22c76c42017-08-16 00:53:59 -070089 return supports_native_handle_;
Peter Boströmeb66e802015-06-05 11:08:03 +020090 }
91
Peter Boströmb7d9a972015-12-18 16:01:11 +010092 const char* ImplementationName() const override {
93 return "fake-encoder";
94 }
95
Peter Boström4d71ede2015-05-19 23:09:35 +020096 int init_encode_count_ = 0;
97 int32_t init_encode_return_code_ = WEBRTC_VIDEO_CODEC_OK;
noahricb1ce6632015-10-21 23:54:51 -070098 int32_t encode_return_code_ = WEBRTC_VIDEO_CODEC_OK;
Peter Boström4d71ede2015-05-19 23:09:35 +020099 int encode_count_ = 0;
100 EncodedImageCallback* encode_complete_callback_ = nullptr;
101 int release_count_ = 0;
102 int set_channel_parameters_count_ = 0;
103 int set_rates_count_ = 0;
Peter Boströmeb66e802015-06-05 11:08:03 +0200104 mutable int supports_native_handle_count_ = 0;
asapersson22c76c42017-08-16 00:53:59 -0700105 bool supports_native_handle_ = false;
Peter Boström4d71ede2015-05-19 23:09:35 +0200106 };
107
108 class FakeEncodedImageCallback : public EncodedImageCallback {
109 public:
Sergey Ulanov525df3f2016-08-02 17:46:41 -0700110 Result OnEncodedImage(
111 const EncodedImage& encoded_image,
112 const CodecSpecificInfo* codec_specific_info,
113 const RTPFragmentationHeader* fragmentation) override {
114 ++callback_count_;
perkj275afc52016-09-01 00:21:16 -0700115 last_codec_name_ = codec_specific_info->codec_name;
Sergey Ulanov525df3f2016-08-02 17:46:41 -0700116 return Result(Result::OK, callback_count_);
Peter Boström4d71ede2015-05-19 23:09:35 +0200117 }
118 int callback_count_ = 0;
perkj275afc52016-09-01 00:21:16 -0700119 std::string last_codec_name_;
Peter Boström4d71ede2015-05-19 23:09:35 +0200120 };
121
122 void UtilizeFallbackEncoder();
noahricb1ce6632015-10-21 23:54:51 -0700123 void FallbackFromEncodeRequest();
124 void EncodeFrame();
asapersson22c76c42017-08-16 00:53:59 -0700125 void EncodeFrame(int expected_ret);
perkj275afc52016-09-01 00:21:16 -0700126 void CheckLastEncoderName(const char* expected_name) {
127 EXPECT_STREQ(expected_name, callback_.last_codec_name_.c_str());
128 }
Peter Boström4d71ede2015-05-19 23:09:35 +0200129
asapersson22c76c42017-08-16 00:53:59 -0700130 test::ScopedFieldTrials override_field_trials_;
Peter Boström4d71ede2015-05-19 23:09:35 +0200131 FakeEncodedImageCallback callback_;
132 CountingFakeEncoder fake_encoder_;
133 VideoEncoderSoftwareFallbackWrapper fallback_wrapper_;
134 VideoCodec codec_ = {};
nisse64ec8f82016-09-27 00:17:25 -0700135 std::unique_ptr<VideoFrame> frame_;
Erik Språng08127a92016-11-16 16:41:30 +0100136 std::unique_ptr<SimulcastRateAllocator> rate_allocator_;
Peter Boström4d71ede2015-05-19 23:09:35 +0200137};
138
noahricb1ce6632015-10-21 23:54:51 -0700139void VideoEncoderSoftwareFallbackWrapperTest::EncodeFrame() {
asapersson22c76c42017-08-16 00:53:59 -0700140 EncodeFrame(WEBRTC_VIDEO_CODEC_OK);
141}
142
143void VideoEncoderSoftwareFallbackWrapperTest::EncodeFrame(int expected_ret) {
Magnus Jedvert7a721e82017-06-14 11:28:08 +0200144 rtc::scoped_refptr<I420Buffer> buffer = I420Buffer::Create(kWidth, kHeight);
nisseaf916892017-01-10 07:44:26 -0800145 I420Buffer::SetBlack(buffer);
nisse776870a2016-09-21 03:52:16 -0700146 std::vector<FrameType> types(1, kVideoFrameKey);
nisse64ec8f82016-09-27 00:17:25 -0700147
148 frame_.reset(new VideoFrame(buffer, 0, 0, webrtc::kVideoRotation_0));
asapersson22c76c42017-08-16 00:53:59 -0700149 EXPECT_EQ(expected_ret, fallback_wrapper_.Encode(*frame_, nullptr, &types));
noahricb1ce6632015-10-21 23:54:51 -0700150}
151
Peter Boström4d71ede2015-05-19 23:09:35 +0200152void VideoEncoderSoftwareFallbackWrapperTest::UtilizeFallbackEncoder() {
Peter Boström4d71ede2015-05-19 23:09:35 +0200153 fallback_wrapper_.RegisterEncodeCompleteCallback(&callback_);
154 EXPECT_EQ(&callback_, fake_encoder_.encode_complete_callback_);
155
156 // Register with failing fake encoder. Should succeed with VP8 fallback.
157 codec_.codecType = kVideoCodecVP8;
asapersson22c76c42017-08-16 00:53:59 -0700158 codec_.maxFramerate = kFramerate;
Peter Boström4d71ede2015-05-19 23:09:35 +0200159 codec_.width = kWidth;
160 codec_.height = kHeight;
Erik Språng08127a92016-11-16 16:41:30 +0100161 codec_.VP8()->numberOfTemporalLayers = 1;
162 std::unique_ptr<TemporalLayersFactory> tl_factory(
163 new TemporalLayersFactory());
164 codec_.VP8()->tl_factory = tl_factory.get();
165 rate_allocator_.reset(
166 new SimulcastRateAllocator(codec_, std::move(tl_factory)));
167
Peter Boström4d71ede2015-05-19 23:09:35 +0200168 fake_encoder_.init_encode_return_code_ = WEBRTC_VIDEO_CODEC_ERROR;
169 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK,
asapersson22c76c42017-08-16 00:53:59 -0700170 fallback_wrapper_.InitEncode(&codec_, kNumCores, kMaxPayloadSize));
171 EXPECT_EQ(
172 WEBRTC_VIDEO_CODEC_OK,
173 fallback_wrapper_.SetRateAllocation(
174 rate_allocator_->GetAllocation(300000, kFramerate), kFramerate));
Peter Boström4d71ede2015-05-19 23:09:35 +0200175
noahricb1ce6632015-10-21 23:54:51 -0700176 int callback_count = callback_.callback_count_;
177 int encode_count = fake_encoder_.encode_count_;
178 EncodeFrame();
179 EXPECT_EQ(encode_count, fake_encoder_.encode_count_);
180 EXPECT_EQ(callback_count + 1, callback_.callback_count_);
181}
Peter Boström4d71ede2015-05-19 23:09:35 +0200182
noahricb1ce6632015-10-21 23:54:51 -0700183void VideoEncoderSoftwareFallbackWrapperTest::FallbackFromEncodeRequest() {
184 fallback_wrapper_.RegisterEncodeCompleteCallback(&callback_);
185 codec_.codecType = kVideoCodecVP8;
asapersson22c76c42017-08-16 00:53:59 -0700186 codec_.maxFramerate = kFramerate;
noahricb1ce6632015-10-21 23:54:51 -0700187 codec_.width = kWidth;
188 codec_.height = kHeight;
Erik Språng08127a92016-11-16 16:41:30 +0100189 codec_.VP8()->numberOfTemporalLayers = 1;
190 std::unique_ptr<TemporalLayersFactory> tl_factory(
191 new TemporalLayersFactory());
192 codec_.VP8()->tl_factory = tl_factory.get();
193 rate_allocator_.reset(
194 new SimulcastRateAllocator(codec_, std::move(tl_factory)));
noahricb1ce6632015-10-21 23:54:51 -0700195 fallback_wrapper_.InitEncode(&codec_, 2, kMaxPayloadSize);
asapersson22c76c42017-08-16 00:53:59 -0700196 EXPECT_EQ(
197 WEBRTC_VIDEO_CODEC_OK,
198 fallback_wrapper_.SetRateAllocation(
199 rate_allocator_->GetAllocation(300000, kFramerate), kFramerate));
noahricb1ce6632015-10-21 23:54:51 -0700200 EXPECT_EQ(1, fake_encoder_.init_encode_count_);
201
202 // Have the non-fallback encoder request a software fallback.
203 fake_encoder_.encode_return_code_ = WEBRTC_VIDEO_CODEC_FALLBACK_SOFTWARE;
204 int callback_count = callback_.callback_count_;
205 int encode_count = fake_encoder_.encode_count_;
206 EncodeFrame();
207 // Single encode request, which returned failure.
208 EXPECT_EQ(encode_count + 1, fake_encoder_.encode_count_);
209 EXPECT_EQ(callback_count + 1, callback_.callback_count_);
Peter Boström4d71ede2015-05-19 23:09:35 +0200210}
211
212TEST_F(VideoEncoderSoftwareFallbackWrapperTest, InitializesEncoder) {
213 VideoCodec codec = {};
214 fallback_wrapper_.InitEncode(&codec, 2, kMaxPayloadSize);
215 EXPECT_EQ(1, fake_encoder_.init_encode_count_);
216}
217
noahricb1ce6632015-10-21 23:54:51 -0700218TEST_F(VideoEncoderSoftwareFallbackWrapperTest, EncodeRequestsFallback) {
219 FallbackFromEncodeRequest();
220 // After fallback, further encodes shouldn't hit the fake encoder.
221 int encode_count = fake_encoder_.encode_count_;
222 EncodeFrame();
223 EXPECT_EQ(encode_count, fake_encoder_.encode_count_);
224}
225
Peter Boström4d71ede2015-05-19 23:09:35 +0200226TEST_F(VideoEncoderSoftwareFallbackWrapperTest, CanUtilizeFallbackEncoder) {
227 UtilizeFallbackEncoder();
228 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, fallback_wrapper_.Release());
229}
230
231TEST_F(VideoEncoderSoftwareFallbackWrapperTest,
noahricb1ce6632015-10-21 23:54:51 -0700232 InternalEncoderReleasedDuringFallback) {
Peter Boström4d71ede2015-05-19 23:09:35 +0200233 EXPECT_EQ(0, fake_encoder_.release_count_);
noahricb1ce6632015-10-21 23:54:51 -0700234 UtilizeFallbackEncoder();
235 EXPECT_EQ(1, fake_encoder_.release_count_);
236 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, fallback_wrapper_.Release());
237 // No extra release when the fallback is released.
238 EXPECT_EQ(1, fake_encoder_.release_count_);
Peter Boström4d71ede2015-05-19 23:09:35 +0200239}
240
241TEST_F(VideoEncoderSoftwareFallbackWrapperTest,
242 InternalEncoderNotEncodingDuringFallback) {
243 UtilizeFallbackEncoder();
noahricb1ce6632015-10-21 23:54:51 -0700244 int encode_count = fake_encoder_.encode_count_;
245 EncodeFrame();
246 EXPECT_EQ(encode_count, fake_encoder_.encode_count_);
Peter Boström4d71ede2015-05-19 23:09:35 +0200247
248 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, fallback_wrapper_.Release());
249}
250
251TEST_F(VideoEncoderSoftwareFallbackWrapperTest,
252 CanRegisterCallbackWhileUsingFallbackEncoder) {
253 UtilizeFallbackEncoder();
254 // Registering an encode-complete callback should still work when fallback
255 // encoder is being used.
256 FakeEncodedImageCallback callback2;
257 fallback_wrapper_.RegisterEncodeCompleteCallback(&callback2);
258 EXPECT_EQ(&callback2, fake_encoder_.encode_complete_callback_);
259
260 // Encoding a frame using the fallback should arrive at the new callback.
Peter Boström49e196a2015-10-23 15:58:18 +0200261 std::vector<FrameType> types(1, kVideoFrameKey);
nisse64ec8f82016-09-27 00:17:25 -0700262 frame_->set_timestamp(frame_->timestamp() + 1000);
Peter Boström4d71ede2015-05-19 23:09:35 +0200263 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK,
nisse64ec8f82016-09-27 00:17:25 -0700264 fallback_wrapper_.Encode(*frame_, nullptr, &types));
Peter Boström4d71ede2015-05-19 23:09:35 +0200265
266 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, fallback_wrapper_.Release());
267}
268
269TEST_F(VideoEncoderSoftwareFallbackWrapperTest,
270 SetChannelParametersForwardedDuringFallback) {
271 UtilizeFallbackEncoder();
272 EXPECT_EQ(0, fake_encoder_.set_channel_parameters_count_);
273 fallback_wrapper_.SetChannelParameters(1, 1);
274 EXPECT_EQ(1, fake_encoder_.set_channel_parameters_count_);
275 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, fallback_wrapper_.Release());
276}
277
278TEST_F(VideoEncoderSoftwareFallbackWrapperTest,
279 SetRatesForwardedDuringFallback) {
280 UtilizeFallbackEncoder();
281 EXPECT_EQ(1, fake_encoder_.set_rates_count_);
Erik Språng08127a92016-11-16 16:41:30 +0100282 fallback_wrapper_.SetRateAllocation(BitrateAllocation(), 1);
Peter Boström4d71ede2015-05-19 23:09:35 +0200283 EXPECT_EQ(2, fake_encoder_.set_rates_count_);
284 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, fallback_wrapper_.Release());
285}
286
287TEST_F(VideoEncoderSoftwareFallbackWrapperTest,
Peter Boströmeb66e802015-06-05 11:08:03 +0200288 SupportsNativeHandleForwardedWithoutFallback) {
289 fallback_wrapper_.SupportsNativeHandle();
290 EXPECT_EQ(1, fake_encoder_.supports_native_handle_count_);
291}
292
293TEST_F(VideoEncoderSoftwareFallbackWrapperTest,
294 SupportsNativeHandleNotForwardedDuringFallback) {
295 UtilizeFallbackEncoder();
296 fallback_wrapper_.SupportsNativeHandle();
297 EXPECT_EQ(0, fake_encoder_.supports_native_handle_count_);
298 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, fallback_wrapper_.Release());
299}
300
perkj275afc52016-09-01 00:21:16 -0700301TEST_F(VideoEncoderSoftwareFallbackWrapperTest, ReportsImplementationName) {
302 VideoCodec codec = {};
303 fallback_wrapper_.RegisterEncodeCompleteCallback(&callback_);
asapersson22c76c42017-08-16 00:53:59 -0700304 fallback_wrapper_.InitEncode(&codec, kNumCores, kMaxPayloadSize);
perkj275afc52016-09-01 00:21:16 -0700305 EncodeFrame();
306 CheckLastEncoderName("fake-encoder");
307}
308
Peter Boströmb7d9a972015-12-18 16:01:11 +0100309TEST_F(VideoEncoderSoftwareFallbackWrapperTest,
310 ReportsFallbackImplementationName) {
311 UtilizeFallbackEncoder();
312 // Hard coded expected value since libvpx is the software implementation name
313 // for VP8. Change accordingly if the underlying implementation does.
perkj275afc52016-09-01 00:21:16 -0700314 CheckLastEncoderName("libvpx");
Peter Boströmb7d9a972015-12-18 16:01:11 +0100315}
316
asapersson22c76c42017-08-16 00:53:59 -0700317namespace {
318const int kLowKbps = 220;
319const int kHighKbps = 300;
320const int kMinLowDurationMs = 4000;
321const std::string kFieldTrial = "WebRTC-VP8-Forced-Fallback-Encoder";
322} // namespace
323
324class ForcedFallbackTest : public VideoEncoderSoftwareFallbackWrapperTest {
325 public:
326 ForcedFallbackTest(const std::string& field_trials)
327 : VideoEncoderSoftwareFallbackWrapperTest(field_trials) {}
328
329 ~ForcedFallbackTest() override {}
330
331 protected:
332 void SetUp() override {
333 clock_.SetTimeMicros(1234);
334 ConfigureVp8Codec();
335 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, fallback_wrapper_.InitEncode(
336 &codec_, kNumCores, kMaxPayloadSize));
337 EXPECT_EQ(1, fake_encoder_.init_encode_count_);
338 }
339
340 void TearDown() override {
341 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, fallback_wrapper_.Release());
342 }
343
344 void ConfigureVp8Codec() {
345 fallback_wrapper_.RegisterEncodeCompleteCallback(&callback_);
346 std::unique_ptr<TemporalLayersFactory> tl_factory(
347 new TemporalLayersFactory());
348 codec_.codecType = kVideoCodecVP8;
349 codec_.maxFramerate = kFramerate;
350 codec_.width = kWidth;
351 codec_.height = kHeight;
352 codec_.VP8()->numberOfTemporalLayers = 1;
353 codec_.VP8()->tl_factory = tl_factory.get();
354 rate_allocator_.reset(
355 new SimulcastRateAllocator(codec_, std::move(tl_factory)));
356 }
357
358 void SetRateAllocation(uint32_t bitrate_kbps) {
359 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, fallback_wrapper_.SetRateAllocation(
360 rate_allocator_->GetAllocation(
361 bitrate_kbps * 1000, kFramerate),
362 kFramerate));
363 }
364
365 void EncodeFrameAndVerifyLastName(const char* expected_name) {
366 EncodeFrameAndVerifyLastName(expected_name, WEBRTC_VIDEO_CODEC_OK);
367 }
368
369 void EncodeFrameAndVerifyLastName(const char* expected_name,
370 int expected_ret) {
371 EncodeFrame(expected_ret);
372 CheckLastEncoderName(expected_name);
373 }
374
375 rtc::ScopedFakeClock clock_;
376};
377
378class ForcedFallbackTestEnabled : public ForcedFallbackTest {
379 public:
380 ForcedFallbackTestEnabled()
381 : ForcedFallbackTest(kFieldTrial + "/Enabled-" +
382 std::to_string(kLowKbps) + "," +
383 std::to_string(kHighKbps) + "," +
384 std::to_string(kMinLowDurationMs) + "/") {}
385};
386
387class ForcedFallbackTestDisabled : public ForcedFallbackTest {
388 public:
389 ForcedFallbackTestDisabled()
390 : ForcedFallbackTest(kFieldTrial + "/Disabled/") {}
391};
392
393TEST_F(ForcedFallbackTestDisabled, NoFallbackWithoutFieldTrial) {
394 // Bitrate at low threshold.
395 SetRateAllocation(kLowKbps);
396 EncodeFrameAndVerifyLastName("fake-encoder");
397 // Duration passed, expect no fallback.
398 clock_.AdvanceTime(rtc::TimeDelta::FromMilliseconds(kMinLowDurationMs));
399 EncodeFrameAndVerifyLastName("fake-encoder");
400}
401
402TEST_F(ForcedFallbackTestEnabled, FallbackIfAtLowLimit) {
403 // Bitrate at low threshold.
404 SetRateAllocation(kLowKbps);
405 EncodeFrameAndVerifyLastName("fake-encoder");
406 // Duration passed, expect fallback.
407 clock_.AdvanceTime(rtc::TimeDelta::FromMilliseconds(kMinLowDurationMs));
408 EncodeFrameAndVerifyLastName("libvpx");
409}
410
411TEST_F(ForcedFallbackTestEnabled, NoFallbackIfNotAtLowLimit) {
412 // Bitrate above low threshold.
413 SetRateAllocation(kLowKbps + 1);
414 EncodeFrameAndVerifyLastName("fake-encoder");
415 // Duration passed, expect no fallback.
416 clock_.AdvanceTime(rtc::TimeDelta::FromMilliseconds(kMinLowDurationMs));
417 EncodeFrameAndVerifyLastName("fake-encoder");
418}
419
420TEST_F(ForcedFallbackTestEnabled, NoFallbackIfResolutionIsTooLarge) {
421 // Resolution above max pixels.
422 codec_.width += 1;
423 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK,
424 fallback_wrapper_.InitEncode(&codec_, kNumCores, kMaxPayloadSize));
425 // Bitrate at low threshold.
426 SetRateAllocation(kLowKbps);
427 EncodeFrameAndVerifyLastName("fake-encoder");
428 // Duration passed, expect no fallback.
429 clock_.AdvanceTime(rtc::TimeDelta::FromMilliseconds(kMinLowDurationMs));
430 EncodeFrameAndVerifyLastName("fake-encoder");
431}
432
433TEST_F(ForcedFallbackTestEnabled, FallbackIfMinDurationPassed) {
434 // Bitrate at low threshold.
435 SetRateAllocation(kLowKbps);
436 EncodeFrameAndVerifyLastName("fake-encoder");
437 // Duration not passed, expect no fallback.
438 clock_.AdvanceTime(rtc::TimeDelta::FromMilliseconds(kMinLowDurationMs - 1));
439 EncodeFrameAndVerifyLastName("fake-encoder");
440 // Duration passed, expect fallback.
441 clock_.AdvanceTime(rtc::TimeDelta::FromMilliseconds(1));
442 EncodeFrameAndVerifyLastName("libvpx");
443}
444
445TEST_F(ForcedFallbackTestEnabled, FallbackStartTimeResetIfAboveLowLimit) {
446 // Bitrate at low threshold, start time set.
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
453 // Bitrate above low threshold, start time reset.
454 SetRateAllocation(kLowKbps + 1);
455 clock_.AdvanceTime(rtc::TimeDelta::FromMilliseconds(1));
456 EncodeFrameAndVerifyLastName("fake-encoder");
457
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 // Duration passed, expect fallback.
465 clock_.AdvanceTime(rtc::TimeDelta::FromMilliseconds(1));
466 EncodeFrameAndVerifyLastName("libvpx");
467}
468
469TEST_F(ForcedFallbackTestEnabled, FallbackEndsIfAtHighLimit) {
470 // Bitrate at low threshold.
471 SetRateAllocation(kLowKbps);
472 EncodeFrameAndVerifyLastName("fake-encoder");
473 // Duration passed, expect fallback.
474 clock_.AdvanceTime(rtc::TimeDelta::FromMilliseconds(kMinLowDurationMs));
475 EncodeFrameAndVerifyLastName("libvpx");
476 // Bitrate below high threshold, expect fallback.
477 SetRateAllocation(kHighKbps - 1);
478 EncodeFrameAndVerifyLastName("libvpx");
479 // Bitrate at high threshold, expect fallback ended.
480 SetRateAllocation(kHighKbps);
481 EncodeFrameAndVerifyLastName("fake-encoder");
482}
483
484TEST_F(ForcedFallbackTestEnabled, MultipleStartEndFallback) {
485 const int kNumRuns = 5;
486 for (int i = 0; i < kNumRuns; ++i) {
487 // Bitrate at low threshold.
488 SetRateAllocation(kLowKbps);
489 EncodeFrameAndVerifyLastName("fake-encoder");
490 // Duration passed, expect fallback.
491 clock_.AdvanceTime(rtc::TimeDelta::FromMilliseconds(kMinLowDurationMs));
492 EncodeFrameAndVerifyLastName("libvpx");
493 // Bitrate at high threshold, expect fallback ended.
494 SetRateAllocation(kHighKbps);
495 EncodeFrameAndVerifyLastName("fake-encoder");
496 }
497}
498
499TEST_F(ForcedFallbackTestEnabled, DropsFirstNonNativeFrameAfterFallbackEnds) {
500 fake_encoder_.supports_native_handle_ = true;
501
502 // Bitrate at low threshold.
503 SetRateAllocation(kLowKbps);
504 EncodeFrameAndVerifyLastName("fake-encoder");
505 // Duration passed, expect fallback.
506 clock_.AdvanceTime(rtc::TimeDelta::FromMilliseconds(kMinLowDurationMs));
507 EncodeFrameAndVerifyLastName("libvpx");
508 // Bitrate at high threshold, fallback should be ended but first non-native
509 // frame dropped (i.e. frame not encoded).
510 SetRateAllocation(kHighKbps);
511 EncodeFrameAndVerifyLastName("libvpx", WEBRTC_VIDEO_CODEC_ERROR);
512 // Next frame should be encoded.
513 EncodeFrameAndVerifyLastName("fake-encoder");
514}
515
516TEST_F(ForcedFallbackTestEnabled, FallbackIsKeptWhenInitEncodeIsCalled) {
517 // Bitrate below low threshold.
518 SetRateAllocation(kLowKbps - 1);
519 EncodeFrameAndVerifyLastName("fake-encoder");
520 // Duration passed, expect fallback.
521 clock_.AdvanceTime(rtc::TimeDelta::FromMilliseconds(kMinLowDurationMs));
522 EncodeFrameAndVerifyLastName("libvpx");
523
524 // Re-initialize encoder, still expect fallback.
525 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK,
526 fallback_wrapper_.InitEncode(&codec_, kNumCores, kMaxPayloadSize));
527 EXPECT_EQ(1, fake_encoder_.init_encode_count_); // No change.
528 SetRateAllocation(kLowKbps);
529 EncodeFrameAndVerifyLastName("libvpx");
530}
531
532TEST_F(ForcedFallbackTestEnabled, FallbackIsEndedWhenResolutionIsTooLarge) {
533 // Bitrate below low threshold.
534 SetRateAllocation(kLowKbps - 1);
535 EncodeFrameAndVerifyLastName("fake-encoder");
536 // Duration passed, expect fallback.
537 clock_.AdvanceTime(rtc::TimeDelta::FromMilliseconds(kMinLowDurationMs));
538 EncodeFrameAndVerifyLastName("libvpx");
539
540 // Re-initialize encoder with a larger resolution, expect no fallback.
541 codec_.width += 1;
542 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK,
543 fallback_wrapper_.InitEncode(&codec_, kNumCores, kMaxPayloadSize));
544 EXPECT_EQ(2, fake_encoder_.init_encode_count_);
545 SetRateAllocation(kLowKbps);
546 EncodeFrameAndVerifyLastName("fake-encoder");
547}
548
549TEST_F(ForcedFallbackTestEnabled, FallbackIsEndedForNonValidSettings) {
550 // Bitrate below low threshold.
551 SetRateAllocation(kLowKbps - 1);
552 EncodeFrameAndVerifyLastName("fake-encoder");
553 // Duration passed, expect fallback.
554 clock_.AdvanceTime(rtc::TimeDelta::FromMilliseconds(kMinLowDurationMs));
555 EncodeFrameAndVerifyLastName("libvpx");
556
557 // Re-initialize encoder with invalid setting, expect no fallback.
558 codec_.VP8()->numberOfTemporalLayers = 2;
559 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK,
560 fallback_wrapper_.InitEncode(&codec_, kNumCores, kMaxPayloadSize));
561 EXPECT_EQ(2, fake_encoder_.init_encode_count_);
562 SetRateAllocation(kLowKbps);
563 EncodeFrameAndVerifyLastName("fake-encoder");
564
565 // Re-initialize encoder with valid setting but fallback disabled from now on.
566 codec_.VP8()->numberOfTemporalLayers = 1;
567 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK,
568 fallback_wrapper_.InitEncode(&codec_, kNumCores, kMaxPayloadSize));
569 EXPECT_EQ(3, fake_encoder_.init_encode_count_);
570 // Bitrate at low threshold.
571 SetRateAllocation(kLowKbps);
572 EncodeFrameAndVerifyLastName("fake-encoder");
573 // Duration passed, expect no fallback.
574 clock_.AdvanceTime(rtc::TimeDelta::FromMilliseconds(kMinLowDurationMs));
575 EncodeFrameAndVerifyLastName("fake-encoder");
576}
577
Peter Boström4d71ede2015-05-19 23:09:35 +0200578} // namespace webrtc