blob: f8521ab888f52c80ea601f2d69f989e10ae19fb9 [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),
magjedf52d34d2017-08-29 00:58:52 -070042 fake_encoder_(new CountingFakeEncoder()),
43 fallback_wrapper_(cricket::VideoCodec("VP8"),
44 std::unique_ptr<VideoEncoder>(fake_encoder_)) {}
Peter Boström4d71ede2015-05-19 23:09:35 +020045
46 class CountingFakeEncoder : public VideoEncoder {
47 public:
48 int32_t InitEncode(const VideoCodec* codec_settings,
49 int32_t number_of_cores,
50 size_t max_payload_size) override {
51 ++init_encode_count_;
52 return init_encode_return_code_;
53 }
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -070054 int32_t Encode(const VideoFrame& frame,
Peter Boström4d71ede2015-05-19 23:09:35 +020055 const CodecSpecificInfo* codec_specific_info,
pbos22993e12015-10-19 02:39:06 -070056 const std::vector<FrameType>* frame_types) override {
Peter Boström4d71ede2015-05-19 23:09:35 +020057 ++encode_count_;
perkj275afc52016-09-01 00:21:16 -070058 if (encode_complete_callback_ &&
59 encode_return_code_ == WEBRTC_VIDEO_CODEC_OK) {
60 CodecSpecificInfo info;
61 info.codec_name = ImplementationName();
62 encode_complete_callback_->OnEncodedImage(EncodedImage(), &info,
63 nullptr);
64 }
noahricb1ce6632015-10-21 23:54:51 -070065 return encode_return_code_;
Peter Boström4d71ede2015-05-19 23:09:35 +020066 }
67
68 int32_t RegisterEncodeCompleteCallback(
69 EncodedImageCallback* callback) override {
70 encode_complete_callback_ = callback;
71 return WEBRTC_VIDEO_CODEC_OK;
72 }
73
74 int32_t Release() override {
75 ++release_count_;
76 return WEBRTC_VIDEO_CODEC_OK;
77 }
78
79 int32_t SetChannelParameters(uint32_t packet_loss, int64_t rtt) override {
80 ++set_channel_parameters_count_;
81 return WEBRTC_VIDEO_CODEC_OK;
82 }
83
Erik Språng08127a92016-11-16 16:41:30 +010084 int32_t SetRateAllocation(const BitrateAllocation& bitrate_allocation,
85 uint32_t framerate) override {
Peter Boström4d71ede2015-05-19 23:09:35 +020086 ++set_rates_count_;
87 return WEBRTC_VIDEO_CODEC_OK;
88 }
89
Peter Boströmeb66e802015-06-05 11:08:03 +020090 bool SupportsNativeHandle() const override {
91 ++supports_native_handle_count_;
asapersson22c76c42017-08-16 00:53:59 -070092 return supports_native_handle_;
Peter Boströmeb66e802015-06-05 11:08:03 +020093 }
94
Peter Boströmb7d9a972015-12-18 16:01:11 +010095 const char* ImplementationName() const override {
96 return "fake-encoder";
97 }
98
asapersson142fcc92017-08-17 08:58:54 -070099 VideoEncoder::ScalingSettings GetScalingSettings() const override {
100 return VideoEncoder::ScalingSettings(true);
101 }
102
Peter Boström4d71ede2015-05-19 23:09:35 +0200103 int init_encode_count_ = 0;
104 int32_t init_encode_return_code_ = WEBRTC_VIDEO_CODEC_OK;
noahricb1ce6632015-10-21 23:54:51 -0700105 int32_t encode_return_code_ = WEBRTC_VIDEO_CODEC_OK;
Peter Boström4d71ede2015-05-19 23:09:35 +0200106 int encode_count_ = 0;
107 EncodedImageCallback* encode_complete_callback_ = nullptr;
108 int release_count_ = 0;
109 int set_channel_parameters_count_ = 0;
110 int set_rates_count_ = 0;
Peter Boströmeb66e802015-06-05 11:08:03 +0200111 mutable int supports_native_handle_count_ = 0;
asapersson22c76c42017-08-16 00:53:59 -0700112 bool supports_native_handle_ = false;
Peter Boström4d71ede2015-05-19 23:09:35 +0200113 };
114
115 class FakeEncodedImageCallback : public EncodedImageCallback {
116 public:
Sergey Ulanov525df3f2016-08-02 17:46:41 -0700117 Result OnEncodedImage(
118 const EncodedImage& encoded_image,
119 const CodecSpecificInfo* codec_specific_info,
120 const RTPFragmentationHeader* fragmentation) override {
121 ++callback_count_;
perkj275afc52016-09-01 00:21:16 -0700122 last_codec_name_ = codec_specific_info->codec_name;
Sergey Ulanov525df3f2016-08-02 17:46:41 -0700123 return Result(Result::OK, callback_count_);
Peter Boström4d71ede2015-05-19 23:09:35 +0200124 }
125 int callback_count_ = 0;
perkj275afc52016-09-01 00:21:16 -0700126 std::string last_codec_name_;
Peter Boström4d71ede2015-05-19 23:09:35 +0200127 };
128
129 void UtilizeFallbackEncoder();
noahricb1ce6632015-10-21 23:54:51 -0700130 void FallbackFromEncodeRequest();
131 void EncodeFrame();
asapersson22c76c42017-08-16 00:53:59 -0700132 void EncodeFrame(int expected_ret);
perkj275afc52016-09-01 00:21:16 -0700133 void CheckLastEncoderName(const char* expected_name) {
134 EXPECT_STREQ(expected_name, callback_.last_codec_name_.c_str());
135 }
Peter Boström4d71ede2015-05-19 23:09:35 +0200136
asapersson22c76c42017-08-16 00:53:59 -0700137 test::ScopedFieldTrials override_field_trials_;
Peter Boström4d71ede2015-05-19 23:09:35 +0200138 FakeEncodedImageCallback callback_;
magjedf52d34d2017-08-29 00:58:52 -0700139 // |fake_encoder_| is owned and released by |fallback_wrapper_|.
140 CountingFakeEncoder* fake_encoder_;
Peter Boström4d71ede2015-05-19 23:09:35 +0200141 VideoEncoderSoftwareFallbackWrapper fallback_wrapper_;
142 VideoCodec codec_ = {};
nisse64ec8f82016-09-27 00:17:25 -0700143 std::unique_ptr<VideoFrame> frame_;
Erik Språng08127a92016-11-16 16:41:30 +0100144 std::unique_ptr<SimulcastRateAllocator> rate_allocator_;
Peter Boström4d71ede2015-05-19 23:09:35 +0200145};
146
noahricb1ce6632015-10-21 23:54:51 -0700147void VideoEncoderSoftwareFallbackWrapperTest::EncodeFrame() {
asapersson22c76c42017-08-16 00:53:59 -0700148 EncodeFrame(WEBRTC_VIDEO_CODEC_OK);
149}
150
151void VideoEncoderSoftwareFallbackWrapperTest::EncodeFrame(int expected_ret) {
asapersson142fcc92017-08-17 08:58:54 -0700152 rtc::scoped_refptr<I420Buffer> buffer =
153 I420Buffer::Create(codec_.width, codec_.height);
nisseaf916892017-01-10 07:44:26 -0800154 I420Buffer::SetBlack(buffer);
nisse776870a2016-09-21 03:52:16 -0700155 std::vector<FrameType> types(1, kVideoFrameKey);
nisse64ec8f82016-09-27 00:17:25 -0700156
157 frame_.reset(new VideoFrame(buffer, 0, 0, webrtc::kVideoRotation_0));
asapersson22c76c42017-08-16 00:53:59 -0700158 EXPECT_EQ(expected_ret, fallback_wrapper_.Encode(*frame_, nullptr, &types));
noahricb1ce6632015-10-21 23:54:51 -0700159}
160
Peter Boström4d71ede2015-05-19 23:09:35 +0200161void VideoEncoderSoftwareFallbackWrapperTest::UtilizeFallbackEncoder() {
Peter Boström4d71ede2015-05-19 23:09:35 +0200162 fallback_wrapper_.RegisterEncodeCompleteCallback(&callback_);
magjedf52d34d2017-08-29 00:58:52 -0700163 EXPECT_EQ(&callback_, fake_encoder_->encode_complete_callback_);
Peter Boström4d71ede2015-05-19 23:09:35 +0200164
165 // Register with failing fake encoder. Should succeed with VP8 fallback.
166 codec_.codecType = kVideoCodecVP8;
asapersson22c76c42017-08-16 00:53:59 -0700167 codec_.maxFramerate = kFramerate;
Peter Boström4d71ede2015-05-19 23:09:35 +0200168 codec_.width = kWidth;
169 codec_.height = kHeight;
Erik Språng08127a92016-11-16 16:41:30 +0100170 codec_.VP8()->numberOfTemporalLayers = 1;
171 std::unique_ptr<TemporalLayersFactory> tl_factory(
172 new TemporalLayersFactory());
173 codec_.VP8()->tl_factory = tl_factory.get();
174 rate_allocator_.reset(
175 new SimulcastRateAllocator(codec_, std::move(tl_factory)));
176
magjedf52d34d2017-08-29 00:58:52 -0700177 fake_encoder_->init_encode_return_code_ = WEBRTC_VIDEO_CODEC_ERROR;
Peter Boström4d71ede2015-05-19 23:09:35 +0200178 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK,
asapersson22c76c42017-08-16 00:53:59 -0700179 fallback_wrapper_.InitEncode(&codec_, kNumCores, kMaxPayloadSize));
180 EXPECT_EQ(
181 WEBRTC_VIDEO_CODEC_OK,
182 fallback_wrapper_.SetRateAllocation(
183 rate_allocator_->GetAllocation(300000, kFramerate), kFramerate));
Peter Boström4d71ede2015-05-19 23:09:35 +0200184
noahricb1ce6632015-10-21 23:54:51 -0700185 int callback_count = callback_.callback_count_;
magjedf52d34d2017-08-29 00:58:52 -0700186 int encode_count = fake_encoder_->encode_count_;
noahricb1ce6632015-10-21 23:54:51 -0700187 EncodeFrame();
magjedf52d34d2017-08-29 00:58:52 -0700188 EXPECT_EQ(encode_count, fake_encoder_->encode_count_);
noahricb1ce6632015-10-21 23:54:51 -0700189 EXPECT_EQ(callback_count + 1, callback_.callback_count_);
190}
Peter Boström4d71ede2015-05-19 23:09:35 +0200191
noahricb1ce6632015-10-21 23:54:51 -0700192void VideoEncoderSoftwareFallbackWrapperTest::FallbackFromEncodeRequest() {
193 fallback_wrapper_.RegisterEncodeCompleteCallback(&callback_);
194 codec_.codecType = kVideoCodecVP8;
asapersson22c76c42017-08-16 00:53:59 -0700195 codec_.maxFramerate = kFramerate;
noahricb1ce6632015-10-21 23:54:51 -0700196 codec_.width = kWidth;
197 codec_.height = kHeight;
Erik Språng08127a92016-11-16 16:41:30 +0100198 codec_.VP8()->numberOfTemporalLayers = 1;
199 std::unique_ptr<TemporalLayersFactory> tl_factory(
200 new TemporalLayersFactory());
201 codec_.VP8()->tl_factory = tl_factory.get();
202 rate_allocator_.reset(
203 new SimulcastRateAllocator(codec_, std::move(tl_factory)));
noahricb1ce6632015-10-21 23:54:51 -0700204 fallback_wrapper_.InitEncode(&codec_, 2, kMaxPayloadSize);
asapersson22c76c42017-08-16 00:53:59 -0700205 EXPECT_EQ(
206 WEBRTC_VIDEO_CODEC_OK,
207 fallback_wrapper_.SetRateAllocation(
208 rate_allocator_->GetAllocation(300000, kFramerate), kFramerate));
magjedf52d34d2017-08-29 00:58:52 -0700209 EXPECT_EQ(1, fake_encoder_->init_encode_count_);
noahricb1ce6632015-10-21 23:54:51 -0700210
211 // Have the non-fallback encoder request a software fallback.
magjedf52d34d2017-08-29 00:58:52 -0700212 fake_encoder_->encode_return_code_ = WEBRTC_VIDEO_CODEC_FALLBACK_SOFTWARE;
noahricb1ce6632015-10-21 23:54:51 -0700213 int callback_count = callback_.callback_count_;
magjedf52d34d2017-08-29 00:58:52 -0700214 int encode_count = fake_encoder_->encode_count_;
noahricb1ce6632015-10-21 23:54:51 -0700215 EncodeFrame();
216 // Single encode request, which returned failure.
magjedf52d34d2017-08-29 00:58:52 -0700217 EXPECT_EQ(encode_count + 1, fake_encoder_->encode_count_);
noahricb1ce6632015-10-21 23:54:51 -0700218 EXPECT_EQ(callback_count + 1, callback_.callback_count_);
Peter Boström4d71ede2015-05-19 23:09:35 +0200219}
220
221TEST_F(VideoEncoderSoftwareFallbackWrapperTest, InitializesEncoder) {
222 VideoCodec codec = {};
223 fallback_wrapper_.InitEncode(&codec, 2, kMaxPayloadSize);
magjedf52d34d2017-08-29 00:58:52 -0700224 EXPECT_EQ(1, fake_encoder_->init_encode_count_);
Peter Boström4d71ede2015-05-19 23:09:35 +0200225}
226
noahricb1ce6632015-10-21 23:54:51 -0700227TEST_F(VideoEncoderSoftwareFallbackWrapperTest, EncodeRequestsFallback) {
228 FallbackFromEncodeRequest();
229 // After fallback, further encodes shouldn't hit the fake encoder.
magjedf52d34d2017-08-29 00:58:52 -0700230 int encode_count = fake_encoder_->encode_count_;
noahricb1ce6632015-10-21 23:54:51 -0700231 EncodeFrame();
magjedf52d34d2017-08-29 00:58:52 -0700232 EXPECT_EQ(encode_count, fake_encoder_->encode_count_);
noahricb1ce6632015-10-21 23:54:51 -0700233}
234
Peter Boström4d71ede2015-05-19 23:09:35 +0200235TEST_F(VideoEncoderSoftwareFallbackWrapperTest, CanUtilizeFallbackEncoder) {
236 UtilizeFallbackEncoder();
237 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, fallback_wrapper_.Release());
238}
239
240TEST_F(VideoEncoderSoftwareFallbackWrapperTest,
noahricb1ce6632015-10-21 23:54:51 -0700241 InternalEncoderReleasedDuringFallback) {
magjedf52d34d2017-08-29 00:58:52 -0700242 EXPECT_EQ(0, fake_encoder_->release_count_);
noahricb1ce6632015-10-21 23:54:51 -0700243 UtilizeFallbackEncoder();
magjedf52d34d2017-08-29 00:58:52 -0700244 EXPECT_EQ(1, fake_encoder_->release_count_);
noahricb1ce6632015-10-21 23:54:51 -0700245 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, fallback_wrapper_.Release());
246 // No extra release when the fallback is released.
magjedf52d34d2017-08-29 00:58:52 -0700247 EXPECT_EQ(1, fake_encoder_->release_count_);
Peter Boström4d71ede2015-05-19 23:09:35 +0200248}
249
250TEST_F(VideoEncoderSoftwareFallbackWrapperTest,
251 InternalEncoderNotEncodingDuringFallback) {
252 UtilizeFallbackEncoder();
magjedf52d34d2017-08-29 00:58:52 -0700253 int encode_count = fake_encoder_->encode_count_;
noahricb1ce6632015-10-21 23:54:51 -0700254 EncodeFrame();
magjedf52d34d2017-08-29 00:58:52 -0700255 EXPECT_EQ(encode_count, fake_encoder_->encode_count_);
Peter Boström4d71ede2015-05-19 23:09:35 +0200256
257 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, fallback_wrapper_.Release());
258}
259
260TEST_F(VideoEncoderSoftwareFallbackWrapperTest,
261 CanRegisterCallbackWhileUsingFallbackEncoder) {
262 UtilizeFallbackEncoder();
263 // Registering an encode-complete callback should still work when fallback
264 // encoder is being used.
265 FakeEncodedImageCallback callback2;
266 fallback_wrapper_.RegisterEncodeCompleteCallback(&callback2);
magjedf52d34d2017-08-29 00:58:52 -0700267 EXPECT_EQ(&callback2, fake_encoder_->encode_complete_callback_);
Peter Boström4d71ede2015-05-19 23:09:35 +0200268
269 // Encoding a frame using the fallback should arrive at the new callback.
Peter Boström49e196a2015-10-23 15:58:18 +0200270 std::vector<FrameType> types(1, kVideoFrameKey);
nisse64ec8f82016-09-27 00:17:25 -0700271 frame_->set_timestamp(frame_->timestamp() + 1000);
Peter Boström4d71ede2015-05-19 23:09:35 +0200272 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK,
nisse64ec8f82016-09-27 00:17:25 -0700273 fallback_wrapper_.Encode(*frame_, nullptr, &types));
Peter Boström4d71ede2015-05-19 23:09:35 +0200274
275 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, fallback_wrapper_.Release());
276}
277
278TEST_F(VideoEncoderSoftwareFallbackWrapperTest,
279 SetChannelParametersForwardedDuringFallback) {
280 UtilizeFallbackEncoder();
magjedf52d34d2017-08-29 00:58:52 -0700281 EXPECT_EQ(0, fake_encoder_->set_channel_parameters_count_);
Peter Boström4d71ede2015-05-19 23:09:35 +0200282 fallback_wrapper_.SetChannelParameters(1, 1);
magjedf52d34d2017-08-29 00:58:52 -0700283 EXPECT_EQ(1, fake_encoder_->set_channel_parameters_count_);
Peter Boström4d71ede2015-05-19 23:09:35 +0200284 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, fallback_wrapper_.Release());
285}
286
287TEST_F(VideoEncoderSoftwareFallbackWrapperTest,
288 SetRatesForwardedDuringFallback) {
289 UtilizeFallbackEncoder();
magjedf52d34d2017-08-29 00:58:52 -0700290 EXPECT_EQ(1, fake_encoder_->set_rates_count_);
Erik Språng08127a92016-11-16 16:41:30 +0100291 fallback_wrapper_.SetRateAllocation(BitrateAllocation(), 1);
magjedf52d34d2017-08-29 00:58:52 -0700292 EXPECT_EQ(2, fake_encoder_->set_rates_count_);
Peter Boström4d71ede2015-05-19 23:09:35 +0200293 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, fallback_wrapper_.Release());
294}
295
296TEST_F(VideoEncoderSoftwareFallbackWrapperTest,
Peter Boströmeb66e802015-06-05 11:08:03 +0200297 SupportsNativeHandleForwardedWithoutFallback) {
298 fallback_wrapper_.SupportsNativeHandle();
magjedf52d34d2017-08-29 00:58:52 -0700299 EXPECT_EQ(1, fake_encoder_->supports_native_handle_count_);
Peter Boströmeb66e802015-06-05 11:08:03 +0200300}
301
302TEST_F(VideoEncoderSoftwareFallbackWrapperTest,
303 SupportsNativeHandleNotForwardedDuringFallback) {
304 UtilizeFallbackEncoder();
305 fallback_wrapper_.SupportsNativeHandle();
magjedf52d34d2017-08-29 00:58:52 -0700306 EXPECT_EQ(0, fake_encoder_->supports_native_handle_count_);
Peter Boströmeb66e802015-06-05 11:08:03 +0200307 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, fallback_wrapper_.Release());
308}
309
perkj275afc52016-09-01 00:21:16 -0700310TEST_F(VideoEncoderSoftwareFallbackWrapperTest, ReportsImplementationName) {
asapersson142fcc92017-08-17 08:58:54 -0700311 codec_.width = kWidth;
312 codec_.height = kHeight;
perkj275afc52016-09-01 00:21:16 -0700313 fallback_wrapper_.RegisterEncodeCompleteCallback(&callback_);
asapersson142fcc92017-08-17 08:58:54 -0700314 fallback_wrapper_.InitEncode(&codec_, kNumCores, kMaxPayloadSize);
perkj275afc52016-09-01 00:21:16 -0700315 EncodeFrame();
316 CheckLastEncoderName("fake-encoder");
317}
318
Peter Boströmb7d9a972015-12-18 16:01:11 +0100319TEST_F(VideoEncoderSoftwareFallbackWrapperTest,
320 ReportsFallbackImplementationName) {
321 UtilizeFallbackEncoder();
322 // Hard coded expected value since libvpx is the software implementation name
323 // for VP8. Change accordingly if the underlying implementation does.
perkj275afc52016-09-01 00:21:16 -0700324 CheckLastEncoderName("libvpx");
Peter Boströmb7d9a972015-12-18 16:01:11 +0100325}
326
asapersson22c76c42017-08-16 00:53:59 -0700327namespace {
328const int kLowKbps = 220;
329const int kHighKbps = 300;
330const int kMinLowDurationMs = 4000;
asapersson142fcc92017-08-17 08:58:54 -0700331const int kMinPixelsPerFrame = 1;
332const int kMinPixelsStop = 320 * 180;
asapersson22c76c42017-08-16 00:53:59 -0700333const std::string kFieldTrial = "WebRTC-VP8-Forced-Fallback-Encoder";
334} // namespace
335
336class ForcedFallbackTest : public VideoEncoderSoftwareFallbackWrapperTest {
337 public:
338 ForcedFallbackTest(const std::string& field_trials)
339 : VideoEncoderSoftwareFallbackWrapperTest(field_trials) {}
340
341 ~ForcedFallbackTest() override {}
342
343 protected:
344 void SetUp() override {
345 clock_.SetTimeMicros(1234);
346 ConfigureVp8Codec();
347 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, fallback_wrapper_.InitEncode(
348 &codec_, kNumCores, kMaxPayloadSize));
magjedf52d34d2017-08-29 00:58:52 -0700349 EXPECT_EQ(1, fake_encoder_->init_encode_count_);
asapersson22c76c42017-08-16 00:53:59 -0700350 }
351
352 void TearDown() override {
353 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, fallback_wrapper_.Release());
354 }
355
356 void ConfigureVp8Codec() {
357 fallback_wrapper_.RegisterEncodeCompleteCallback(&callback_);
358 std::unique_ptr<TemporalLayersFactory> tl_factory(
359 new TemporalLayersFactory());
360 codec_.codecType = kVideoCodecVP8;
361 codec_.maxFramerate = kFramerate;
362 codec_.width = kWidth;
363 codec_.height = kHeight;
364 codec_.VP8()->numberOfTemporalLayers = 1;
asapersson142fcc92017-08-17 08:58:54 -0700365 codec_.VP8()->automaticResizeOn = true;
366 codec_.VP8()->frameDroppingOn = true;
asapersson22c76c42017-08-16 00:53:59 -0700367 codec_.VP8()->tl_factory = tl_factory.get();
368 rate_allocator_.reset(
369 new SimulcastRateAllocator(codec_, std::move(tl_factory)));
370 }
371
372 void SetRateAllocation(uint32_t bitrate_kbps) {
373 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, fallback_wrapper_.SetRateAllocation(
374 rate_allocator_->GetAllocation(
375 bitrate_kbps * 1000, kFramerate),
376 kFramerate));
377 }
378
379 void EncodeFrameAndVerifyLastName(const char* expected_name) {
380 EncodeFrameAndVerifyLastName(expected_name, WEBRTC_VIDEO_CODEC_OK);
381 }
382
383 void EncodeFrameAndVerifyLastName(const char* expected_name,
384 int expected_ret) {
385 EncodeFrame(expected_ret);
386 CheckLastEncoderName(expected_name);
387 }
388
389 rtc::ScopedFakeClock clock_;
390};
391
392class ForcedFallbackTestEnabled : public ForcedFallbackTest {
393 public:
394 ForcedFallbackTestEnabled()
395 : ForcedFallbackTest(kFieldTrial + "/Enabled-" +
396 std::to_string(kLowKbps) + "," +
397 std::to_string(kHighKbps) + "," +
asapersson142fcc92017-08-17 08:58:54 -0700398 std::to_string(kMinLowDurationMs) + "," +
399 std::to_string(kMinPixelsPerFrame) + "/") {}
asapersson22c76c42017-08-16 00:53:59 -0700400};
401
402class ForcedFallbackTestDisabled : public ForcedFallbackTest {
403 public:
404 ForcedFallbackTestDisabled()
405 : ForcedFallbackTest(kFieldTrial + "/Disabled/") {}
406};
407
408TEST_F(ForcedFallbackTestDisabled, NoFallbackWithoutFieldTrial) {
409 // Bitrate at low threshold.
410 SetRateAllocation(kLowKbps);
411 EncodeFrameAndVerifyLastName("fake-encoder");
412 // Duration passed, expect no fallback.
413 clock_.AdvanceTime(rtc::TimeDelta::FromMilliseconds(kMinLowDurationMs));
414 EncodeFrameAndVerifyLastName("fake-encoder");
415}
416
417TEST_F(ForcedFallbackTestEnabled, FallbackIfAtLowLimit) {
418 // Bitrate at low threshold.
419 SetRateAllocation(kLowKbps);
420 EncodeFrameAndVerifyLastName("fake-encoder");
421 // Duration passed, expect fallback.
422 clock_.AdvanceTime(rtc::TimeDelta::FromMilliseconds(kMinLowDurationMs));
423 EncodeFrameAndVerifyLastName("libvpx");
424}
425
426TEST_F(ForcedFallbackTestEnabled, NoFallbackIfNotAtLowLimit) {
427 // Bitrate above low threshold.
428 SetRateAllocation(kLowKbps + 1);
429 EncodeFrameAndVerifyLastName("fake-encoder");
430 // Duration passed, expect no fallback.
431 clock_.AdvanceTime(rtc::TimeDelta::FromMilliseconds(kMinLowDurationMs));
432 EncodeFrameAndVerifyLastName("fake-encoder");
433}
434
435TEST_F(ForcedFallbackTestEnabled, NoFallbackIfResolutionIsTooLarge) {
436 // Resolution above max pixels.
437 codec_.width += 1;
438 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK,
439 fallback_wrapper_.InitEncode(&codec_, kNumCores, kMaxPayloadSize));
440 // Bitrate at low threshold.
441 SetRateAllocation(kLowKbps);
442 EncodeFrameAndVerifyLastName("fake-encoder");
443 // Duration passed, expect no fallback.
444 clock_.AdvanceTime(rtc::TimeDelta::FromMilliseconds(kMinLowDurationMs));
445 EncodeFrameAndVerifyLastName("fake-encoder");
446}
447
448TEST_F(ForcedFallbackTestEnabled, FallbackIfMinDurationPassed) {
449 // Bitrate at low threshold.
450 SetRateAllocation(kLowKbps);
451 EncodeFrameAndVerifyLastName("fake-encoder");
452 // Duration not passed, expect no fallback.
453 clock_.AdvanceTime(rtc::TimeDelta::FromMilliseconds(kMinLowDurationMs - 1));
454 EncodeFrameAndVerifyLastName("fake-encoder");
455 // Duration passed, expect fallback.
456 clock_.AdvanceTime(rtc::TimeDelta::FromMilliseconds(1));
457 EncodeFrameAndVerifyLastName("libvpx");
458}
459
460TEST_F(ForcedFallbackTestEnabled, FallbackStartTimeResetIfAboveLowLimit) {
461 // Bitrate at low threshold, start time set.
462 SetRateAllocation(kLowKbps);
463 EncodeFrameAndVerifyLastName("fake-encoder");
464 // Duration not passed, expect no fallback.
465 clock_.AdvanceTime(rtc::TimeDelta::FromMilliseconds(kMinLowDurationMs - 1));
466 EncodeFrameAndVerifyLastName("fake-encoder");
467
468 // Bitrate above low threshold, start time reset.
469 SetRateAllocation(kLowKbps + 1);
470 clock_.AdvanceTime(rtc::TimeDelta::FromMilliseconds(1));
471 EncodeFrameAndVerifyLastName("fake-encoder");
472
473 // Bitrate at low threshold, start time set.
474 SetRateAllocation(kLowKbps);
475 EncodeFrameAndVerifyLastName("fake-encoder");
476 // Duration not passed, expect no fallback.
477 clock_.AdvanceTime(rtc::TimeDelta::FromMilliseconds(kMinLowDurationMs - 1));
478 EncodeFrameAndVerifyLastName("fake-encoder");
479 // Duration passed, expect fallback.
480 clock_.AdvanceTime(rtc::TimeDelta::FromMilliseconds(1));
481 EncodeFrameAndVerifyLastName("libvpx");
482}
483
484TEST_F(ForcedFallbackTestEnabled, FallbackEndsIfAtHighLimit) {
485 // Bitrate at low threshold.
486 SetRateAllocation(kLowKbps);
487 EncodeFrameAndVerifyLastName("fake-encoder");
488 // Duration passed, expect fallback.
489 clock_.AdvanceTime(rtc::TimeDelta::FromMilliseconds(kMinLowDurationMs));
490 EncodeFrameAndVerifyLastName("libvpx");
491 // Bitrate below high threshold, expect fallback.
492 SetRateAllocation(kHighKbps - 1);
493 EncodeFrameAndVerifyLastName("libvpx");
494 // Bitrate at high threshold, expect fallback ended.
495 SetRateAllocation(kHighKbps);
496 EncodeFrameAndVerifyLastName("fake-encoder");
497}
498
499TEST_F(ForcedFallbackTestEnabled, MultipleStartEndFallback) {
500 const int kNumRuns = 5;
501 for (int i = 0; i < kNumRuns; ++i) {
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, expect fallback ended.
509 SetRateAllocation(kHighKbps);
510 EncodeFrameAndVerifyLastName("fake-encoder");
511 }
512}
513
514TEST_F(ForcedFallbackTestEnabled, DropsFirstNonNativeFrameAfterFallbackEnds) {
magjedf52d34d2017-08-29 00:58:52 -0700515 fake_encoder_->supports_native_handle_ = true;
asapersson22c76c42017-08-16 00:53:59 -0700516
517 // Bitrate at low threshold.
518 SetRateAllocation(kLowKbps);
519 EncodeFrameAndVerifyLastName("fake-encoder");
520 // Duration passed, expect fallback.
521 clock_.AdvanceTime(rtc::TimeDelta::FromMilliseconds(kMinLowDurationMs));
522 EncodeFrameAndVerifyLastName("libvpx");
523 // Bitrate at high threshold, fallback should be ended but first non-native
524 // frame dropped (i.e. frame not encoded).
525 SetRateAllocation(kHighKbps);
526 EncodeFrameAndVerifyLastName("libvpx", WEBRTC_VIDEO_CODEC_ERROR);
527 // Next frame should be encoded.
528 EncodeFrameAndVerifyLastName("fake-encoder");
529}
530
531TEST_F(ForcedFallbackTestEnabled, FallbackIsKeptWhenInitEncodeIsCalled) {
532 // Bitrate below low threshold.
533 SetRateAllocation(kLowKbps - 1);
534 EncodeFrameAndVerifyLastName("fake-encoder");
535 // Duration passed, expect fallback.
536 clock_.AdvanceTime(rtc::TimeDelta::FromMilliseconds(kMinLowDurationMs));
537 EncodeFrameAndVerifyLastName("libvpx");
538
539 // Re-initialize encoder, still expect fallback.
540 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK,
541 fallback_wrapper_.InitEncode(&codec_, kNumCores, kMaxPayloadSize));
magjedf52d34d2017-08-29 00:58:52 -0700542 EXPECT_EQ(1, fake_encoder_->init_encode_count_); // No change.
asapersson22c76c42017-08-16 00:53:59 -0700543 SetRateAllocation(kLowKbps);
544 EncodeFrameAndVerifyLastName("libvpx");
545}
546
547TEST_F(ForcedFallbackTestEnabled, FallbackIsEndedWhenResolutionIsTooLarge) {
548 // Bitrate below low threshold.
549 SetRateAllocation(kLowKbps - 1);
550 EncodeFrameAndVerifyLastName("fake-encoder");
551 // Duration passed, expect fallback.
552 clock_.AdvanceTime(rtc::TimeDelta::FromMilliseconds(kMinLowDurationMs));
553 EncodeFrameAndVerifyLastName("libvpx");
554
555 // Re-initialize encoder with a larger resolution, expect no fallback.
556 codec_.width += 1;
557 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK,
558 fallback_wrapper_.InitEncode(&codec_, kNumCores, kMaxPayloadSize));
magjedf52d34d2017-08-29 00:58:52 -0700559 EXPECT_EQ(2, fake_encoder_->init_encode_count_);
asapersson22c76c42017-08-16 00:53:59 -0700560 SetRateAllocation(kLowKbps);
561 EncodeFrameAndVerifyLastName("fake-encoder");
562}
563
564TEST_F(ForcedFallbackTestEnabled, FallbackIsEndedForNonValidSettings) {
565 // Bitrate below low threshold.
566 SetRateAllocation(kLowKbps - 1);
567 EncodeFrameAndVerifyLastName("fake-encoder");
568 // Duration passed, expect fallback.
569 clock_.AdvanceTime(rtc::TimeDelta::FromMilliseconds(kMinLowDurationMs));
570 EncodeFrameAndVerifyLastName("libvpx");
571
572 // Re-initialize encoder with invalid setting, expect no fallback.
573 codec_.VP8()->numberOfTemporalLayers = 2;
574 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK,
575 fallback_wrapper_.InitEncode(&codec_, kNumCores, kMaxPayloadSize));
magjedf52d34d2017-08-29 00:58:52 -0700576 EXPECT_EQ(2, fake_encoder_->init_encode_count_);
asapersson22c76c42017-08-16 00:53:59 -0700577 SetRateAllocation(kLowKbps);
578 EncodeFrameAndVerifyLastName("fake-encoder");
579
580 // Re-initialize encoder with valid setting but fallback disabled from now on.
581 codec_.VP8()->numberOfTemporalLayers = 1;
582 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK,
583 fallback_wrapper_.InitEncode(&codec_, kNumCores, kMaxPayloadSize));
magjedf52d34d2017-08-29 00:58:52 -0700584 EXPECT_EQ(3, fake_encoder_->init_encode_count_);
asapersson22c76c42017-08-16 00:53:59 -0700585 // Bitrate at low threshold.
586 SetRateAllocation(kLowKbps);
587 EncodeFrameAndVerifyLastName("fake-encoder");
588 // Duration passed, expect no fallback.
589 clock_.AdvanceTime(rtc::TimeDelta::FromMilliseconds(kMinLowDurationMs));
590 EncodeFrameAndVerifyLastName("fake-encoder");
591}
592
asapersson142fcc92017-08-17 08:58:54 -0700593TEST_F(ForcedFallbackTestEnabled, GetScaleSettingsWithoutFallback) {
594 // Bitrate at low threshold.
595 SetRateAllocation(kLowKbps);
596 EncodeFrameAndVerifyLastName("fake-encoder");
597 // Default min pixels per frame should be used.
598 const auto settings = fallback_wrapper_.GetScalingSettings();
599 EXPECT_TRUE(settings.enabled);
600 EXPECT_EQ(kDefaultMinPixelsPerFrame, settings.min_pixels_per_frame);
601}
602
603TEST_F(ForcedFallbackTestEnabled, GetScaleSettingsWithFallback) {
604 // Bitrate at low threshold.
605 SetRateAllocation(kLowKbps);
606 EncodeFrameAndVerifyLastName("fake-encoder");
607 // Duration passed, expect fallback.
608 clock_.AdvanceTime(rtc::TimeDelta::FromMilliseconds(kMinLowDurationMs));
609 EncodeFrameAndVerifyLastName("libvpx");
610 // Configured min pixels per frame should be used.
611 const auto settings = fallback_wrapper_.GetScalingSettings();
612 EXPECT_TRUE(settings.enabled);
613 EXPECT_EQ(kMinPixelsPerFrame, settings.min_pixels_per_frame);
614}
615
616TEST_F(ForcedFallbackTestEnabled, FallbackIsKeptIfResolutionIsTooSmall) {
617 // Bitrate at low threshold.
618 SetRateAllocation(kLowKbps);
619 EncodeFrameAndVerifyLastName("fake-encoder");
620 // Duration passed, expect fallback.
621 clock_.AdvanceTime(rtc::TimeDelta::FromMilliseconds(kMinLowDurationMs));
622 EncodeFrameAndVerifyLastName("libvpx");
623
624 // Re-initialize encoder with a resolution less than |kMinPixelsStop|.
625 codec_.height = kMinPixelsStop / codec_.width - 1;
626 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK,
627 fallback_wrapper_.InitEncode(&codec_, kNumCores, kMaxPayloadSize));
magjedf52d34d2017-08-29 00:58:52 -0700628 EXPECT_EQ(1, fake_encoder_->init_encode_count_); // No change
asapersson142fcc92017-08-17 08:58:54 -0700629 SetRateAllocation(kHighKbps - 1);
630 EncodeFrameAndVerifyLastName("libvpx");
631 // Bitrate at high threshold but resolution too small for fallback to end.
632 SetRateAllocation(kHighKbps);
633 EncodeFrameAndVerifyLastName("libvpx");
634
635 // Re-initialize encoder with a resolution equal to |kMinPixelsStop|.
636 codec_.height++;
637 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK,
638 fallback_wrapper_.InitEncode(&codec_, kNumCores, kMaxPayloadSize));
magjedf52d34d2017-08-29 00:58:52 -0700639 EXPECT_EQ(1, fake_encoder_->init_encode_count_); // No change
asapersson142fcc92017-08-17 08:58:54 -0700640 SetRateAllocation(kHighKbps - 1);
641 EncodeFrameAndVerifyLastName("libvpx");
642 // Bitrate at high threshold and resolution large enough for fallback to end.
643 SetRateAllocation(kHighKbps);
644 EncodeFrameAndVerifyLastName("fake-encoder");
645}
646
Peter Boström4d71ede2015-05-19 23:09:35 +0200647} // namespace webrtc