blob: e39b02f71ce5bdd2e977d94e0f245ce3cf7acc02 [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"
Magnus Jedvertee92d622017-11-13 15:26:17 +010016#include "modules/video_coding/codecs/vp8/include/vp8.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020017#include "modules/video_coding/codecs/vp8/simulcast_rate_allocator.h"
18#include "modules/video_coding/codecs/vp8/temporal_layers.h"
19#include "modules/video_coding/include/video_codec_interface.h"
20#include "modules/video_coding/include/video_error_codes.h"
21#include "rtc_base/checks.h"
22#include "rtc_base/fakeclock.h"
23#include "test/field_trial.h"
24#include "test/gtest.h"
Peter Boström4d71ede2015-05-19 23:09:35 +020025
26namespace webrtc {
asapersson22c76c42017-08-16 00:53:59 -070027namespace {
noahricb1ce6632015-10-21 23:54:51 -070028const int kWidth = 320;
29const int kHeight = 240;
asapersson22c76c42017-08-16 00:53:59 -070030const int kNumCores = 2;
31const uint32_t kFramerate = 30;
Peter Boström4d71ede2015-05-19 23:09:35 +020032const size_t kMaxPayloadSize = 800;
asapersson142fcc92017-08-17 08:58:54 -070033const int kDefaultMinPixelsPerFrame = 320 * 180;
Åsa Persson45bbc8a2017-11-13 10:16:47 +010034const int kLowThreshold = 10;
35const int kHighThreshold = 20;
asapersson22c76c42017-08-16 00:53:59 -070036} // namespace
Peter Boström4d71ede2015-05-19 23:09:35 +020037
38class VideoEncoderSoftwareFallbackWrapperTest : public ::testing::Test {
39 protected:
40 VideoEncoderSoftwareFallbackWrapperTest()
asapersson22c76c42017-08-16 00:53:59 -070041 : VideoEncoderSoftwareFallbackWrapperTest("") {}
42 explicit VideoEncoderSoftwareFallbackWrapperTest(
43 const std::string& field_trials)
44 : override_field_trials_(field_trials),
magjedf52d34d2017-08-29 00:58:52 -070045 fake_encoder_(new CountingFakeEncoder()),
Magnus Jedvertee92d622017-11-13 15:26:17 +010046 fallback_wrapper_(std::unique_ptr<VideoEncoder>(VP8Encoder::Create()),
magjedf52d34d2017-08-29 00:58:52 -070047 std::unique_ptr<VideoEncoder>(fake_encoder_)) {}
Peter Boström4d71ede2015-05-19 23:09:35 +020048
49 class CountingFakeEncoder : public VideoEncoder {
50 public:
51 int32_t InitEncode(const VideoCodec* codec_settings,
52 int32_t number_of_cores,
53 size_t max_payload_size) override {
54 ++init_encode_count_;
55 return init_encode_return_code_;
56 }
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -070057 int32_t Encode(const VideoFrame& frame,
Peter Boström4d71ede2015-05-19 23:09:35 +020058 const CodecSpecificInfo* codec_specific_info,
pbos22993e12015-10-19 02:39:06 -070059 const std::vector<FrameType>* frame_types) override {
Peter Boström4d71ede2015-05-19 23:09:35 +020060 ++encode_count_;
perkj275afc52016-09-01 00:21:16 -070061 if (encode_complete_callback_ &&
62 encode_return_code_ == WEBRTC_VIDEO_CODEC_OK) {
63 CodecSpecificInfo info;
64 info.codec_name = ImplementationName();
65 encode_complete_callback_->OnEncodedImage(EncodedImage(), &info,
66 nullptr);
67 }
noahricb1ce6632015-10-21 23:54:51 -070068 return encode_return_code_;
Peter Boström4d71ede2015-05-19 23:09:35 +020069 }
70
71 int32_t RegisterEncodeCompleteCallback(
72 EncodedImageCallback* callback) override {
73 encode_complete_callback_ = callback;
74 return WEBRTC_VIDEO_CODEC_OK;
75 }
76
77 int32_t Release() override {
78 ++release_count_;
79 return WEBRTC_VIDEO_CODEC_OK;
80 }
81
82 int32_t SetChannelParameters(uint32_t packet_loss, int64_t rtt) override {
83 ++set_channel_parameters_count_;
84 return WEBRTC_VIDEO_CODEC_OK;
85 }
86
Erik Språng08127a92016-11-16 16:41:30 +010087 int32_t SetRateAllocation(const BitrateAllocation& bitrate_allocation,
88 uint32_t framerate) override {
Peter Boström4d71ede2015-05-19 23:09:35 +020089 ++set_rates_count_;
90 return WEBRTC_VIDEO_CODEC_OK;
91 }
92
Peter Boströmeb66e802015-06-05 11:08:03 +020093 bool SupportsNativeHandle() const override {
94 ++supports_native_handle_count_;
asapersson22c76c42017-08-16 00:53:59 -070095 return supports_native_handle_;
Peter Boströmeb66e802015-06-05 11:08:03 +020096 }
97
Peter Boströmb7d9a972015-12-18 16:01:11 +010098 const char* ImplementationName() const override {
99 return "fake-encoder";
100 }
101
asapersson142fcc92017-08-17 08:58:54 -0700102 VideoEncoder::ScalingSettings GetScalingSettings() const override {
Åsa Persson45bbc8a2017-11-13 10:16:47 +0100103 return VideoEncoder::ScalingSettings(true, kLowThreshold, kHighThreshold);
asapersson142fcc92017-08-17 08:58:54 -0700104 }
105
Peter Boström4d71ede2015-05-19 23:09:35 +0200106 int init_encode_count_ = 0;
107 int32_t init_encode_return_code_ = WEBRTC_VIDEO_CODEC_OK;
noahricb1ce6632015-10-21 23:54:51 -0700108 int32_t encode_return_code_ = WEBRTC_VIDEO_CODEC_OK;
Peter Boström4d71ede2015-05-19 23:09:35 +0200109 int encode_count_ = 0;
110 EncodedImageCallback* encode_complete_callback_ = nullptr;
111 int release_count_ = 0;
112 int set_channel_parameters_count_ = 0;
113 int set_rates_count_ = 0;
Peter Boströmeb66e802015-06-05 11:08:03 +0200114 mutable int supports_native_handle_count_ = 0;
asapersson22c76c42017-08-16 00:53:59 -0700115 bool supports_native_handle_ = false;
Peter Boström4d71ede2015-05-19 23:09:35 +0200116 };
117
118 class FakeEncodedImageCallback : public EncodedImageCallback {
119 public:
Sergey Ulanov525df3f2016-08-02 17:46:41 -0700120 Result OnEncodedImage(
121 const EncodedImage& encoded_image,
122 const CodecSpecificInfo* codec_specific_info,
123 const RTPFragmentationHeader* fragmentation) override {
124 ++callback_count_;
perkj275afc52016-09-01 00:21:16 -0700125 last_codec_name_ = codec_specific_info->codec_name;
Sergey Ulanov525df3f2016-08-02 17:46:41 -0700126 return Result(Result::OK, callback_count_);
Peter Boström4d71ede2015-05-19 23:09:35 +0200127 }
128 int callback_count_ = 0;
perkj275afc52016-09-01 00:21:16 -0700129 std::string last_codec_name_;
Peter Boström4d71ede2015-05-19 23:09:35 +0200130 };
131
132 void UtilizeFallbackEncoder();
noahricb1ce6632015-10-21 23:54:51 -0700133 void FallbackFromEncodeRequest();
134 void EncodeFrame();
asapersson22c76c42017-08-16 00:53:59 -0700135 void EncodeFrame(int expected_ret);
perkj275afc52016-09-01 00:21:16 -0700136 void CheckLastEncoderName(const char* expected_name) {
137 EXPECT_STREQ(expected_name, callback_.last_codec_name_.c_str());
138 }
Peter Boström4d71ede2015-05-19 23:09:35 +0200139
asapersson22c76c42017-08-16 00:53:59 -0700140 test::ScopedFieldTrials override_field_trials_;
Peter Boström4d71ede2015-05-19 23:09:35 +0200141 FakeEncodedImageCallback callback_;
magjedf52d34d2017-08-29 00:58:52 -0700142 // |fake_encoder_| is owned and released by |fallback_wrapper_|.
143 CountingFakeEncoder* fake_encoder_;
Peter Boström4d71ede2015-05-19 23:09:35 +0200144 VideoEncoderSoftwareFallbackWrapper fallback_wrapper_;
145 VideoCodec codec_ = {};
nisse64ec8f82016-09-27 00:17:25 -0700146 std::unique_ptr<VideoFrame> frame_;
Erik Språng08127a92016-11-16 16:41:30 +0100147 std::unique_ptr<SimulcastRateAllocator> rate_allocator_;
Peter Boström4d71ede2015-05-19 23:09:35 +0200148};
149
noahricb1ce6632015-10-21 23:54:51 -0700150void VideoEncoderSoftwareFallbackWrapperTest::EncodeFrame() {
asapersson22c76c42017-08-16 00:53:59 -0700151 EncodeFrame(WEBRTC_VIDEO_CODEC_OK);
152}
153
154void VideoEncoderSoftwareFallbackWrapperTest::EncodeFrame(int expected_ret) {
asapersson142fcc92017-08-17 08:58:54 -0700155 rtc::scoped_refptr<I420Buffer> buffer =
156 I420Buffer::Create(codec_.width, codec_.height);
nisseaf916892017-01-10 07:44:26 -0800157 I420Buffer::SetBlack(buffer);
nisse776870a2016-09-21 03:52:16 -0700158 std::vector<FrameType> types(1, kVideoFrameKey);
nisse64ec8f82016-09-27 00:17:25 -0700159
160 frame_.reset(new VideoFrame(buffer, 0, 0, webrtc::kVideoRotation_0));
asapersson22c76c42017-08-16 00:53:59 -0700161 EXPECT_EQ(expected_ret, fallback_wrapper_.Encode(*frame_, nullptr, &types));
noahricb1ce6632015-10-21 23:54:51 -0700162}
163
Peter Boström4d71ede2015-05-19 23:09:35 +0200164void VideoEncoderSoftwareFallbackWrapperTest::UtilizeFallbackEncoder() {
Peter Boström4d71ede2015-05-19 23:09:35 +0200165 fallback_wrapper_.RegisterEncodeCompleteCallback(&callback_);
magjedf52d34d2017-08-29 00:58:52 -0700166 EXPECT_EQ(&callback_, fake_encoder_->encode_complete_callback_);
Peter Boström4d71ede2015-05-19 23:09:35 +0200167
168 // Register with failing fake encoder. Should succeed with VP8 fallback.
169 codec_.codecType = kVideoCodecVP8;
asapersson22c76c42017-08-16 00:53:59 -0700170 codec_.maxFramerate = kFramerate;
Peter Boström4d71ede2015-05-19 23:09:35 +0200171 codec_.width = kWidth;
172 codec_.height = kHeight;
Erik Språng08127a92016-11-16 16:41:30 +0100173 codec_.VP8()->numberOfTemporalLayers = 1;
174 std::unique_ptr<TemporalLayersFactory> tl_factory(
175 new TemporalLayersFactory());
176 codec_.VP8()->tl_factory = tl_factory.get();
177 rate_allocator_.reset(
178 new SimulcastRateAllocator(codec_, std::move(tl_factory)));
179
magjedf52d34d2017-08-29 00:58:52 -0700180 fake_encoder_->init_encode_return_code_ = WEBRTC_VIDEO_CODEC_ERROR;
Peter Boström4d71ede2015-05-19 23:09:35 +0200181 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK,
asapersson22c76c42017-08-16 00:53:59 -0700182 fallback_wrapper_.InitEncode(&codec_, kNumCores, kMaxPayloadSize));
183 EXPECT_EQ(
184 WEBRTC_VIDEO_CODEC_OK,
185 fallback_wrapper_.SetRateAllocation(
186 rate_allocator_->GetAllocation(300000, kFramerate), kFramerate));
Peter Boström4d71ede2015-05-19 23:09:35 +0200187
noahricb1ce6632015-10-21 23:54:51 -0700188 int callback_count = callback_.callback_count_;
magjedf52d34d2017-08-29 00:58:52 -0700189 int encode_count = fake_encoder_->encode_count_;
noahricb1ce6632015-10-21 23:54:51 -0700190 EncodeFrame();
magjedf52d34d2017-08-29 00:58:52 -0700191 EXPECT_EQ(encode_count, fake_encoder_->encode_count_);
noahricb1ce6632015-10-21 23:54:51 -0700192 EXPECT_EQ(callback_count + 1, callback_.callback_count_);
193}
Peter Boström4d71ede2015-05-19 23:09:35 +0200194
noahricb1ce6632015-10-21 23:54:51 -0700195void VideoEncoderSoftwareFallbackWrapperTest::FallbackFromEncodeRequest() {
196 fallback_wrapper_.RegisterEncodeCompleteCallback(&callback_);
197 codec_.codecType = kVideoCodecVP8;
asapersson22c76c42017-08-16 00:53:59 -0700198 codec_.maxFramerate = kFramerate;
noahricb1ce6632015-10-21 23:54:51 -0700199 codec_.width = kWidth;
200 codec_.height = kHeight;
Erik Språng08127a92016-11-16 16:41:30 +0100201 codec_.VP8()->numberOfTemporalLayers = 1;
202 std::unique_ptr<TemporalLayersFactory> tl_factory(
203 new TemporalLayersFactory());
204 codec_.VP8()->tl_factory = tl_factory.get();
205 rate_allocator_.reset(
206 new SimulcastRateAllocator(codec_, std::move(tl_factory)));
noahricb1ce6632015-10-21 23:54:51 -0700207 fallback_wrapper_.InitEncode(&codec_, 2, kMaxPayloadSize);
asapersson22c76c42017-08-16 00:53:59 -0700208 EXPECT_EQ(
209 WEBRTC_VIDEO_CODEC_OK,
210 fallback_wrapper_.SetRateAllocation(
211 rate_allocator_->GetAllocation(300000, kFramerate), kFramerate));
magjedf52d34d2017-08-29 00:58:52 -0700212 EXPECT_EQ(1, fake_encoder_->init_encode_count_);
noahricb1ce6632015-10-21 23:54:51 -0700213
214 // Have the non-fallback encoder request a software fallback.
magjedf52d34d2017-08-29 00:58:52 -0700215 fake_encoder_->encode_return_code_ = WEBRTC_VIDEO_CODEC_FALLBACK_SOFTWARE;
noahricb1ce6632015-10-21 23:54:51 -0700216 int callback_count = callback_.callback_count_;
magjedf52d34d2017-08-29 00:58:52 -0700217 int encode_count = fake_encoder_->encode_count_;
noahricb1ce6632015-10-21 23:54:51 -0700218 EncodeFrame();
219 // Single encode request, which returned failure.
magjedf52d34d2017-08-29 00:58:52 -0700220 EXPECT_EQ(encode_count + 1, fake_encoder_->encode_count_);
noahricb1ce6632015-10-21 23:54:51 -0700221 EXPECT_EQ(callback_count + 1, callback_.callback_count_);
Peter Boström4d71ede2015-05-19 23:09:35 +0200222}
223
224TEST_F(VideoEncoderSoftwareFallbackWrapperTest, InitializesEncoder) {
225 VideoCodec codec = {};
226 fallback_wrapper_.InitEncode(&codec, 2, kMaxPayloadSize);
magjedf52d34d2017-08-29 00:58:52 -0700227 EXPECT_EQ(1, fake_encoder_->init_encode_count_);
Peter Boström4d71ede2015-05-19 23:09:35 +0200228}
229
noahricb1ce6632015-10-21 23:54:51 -0700230TEST_F(VideoEncoderSoftwareFallbackWrapperTest, EncodeRequestsFallback) {
231 FallbackFromEncodeRequest();
232 // After fallback, further encodes shouldn't hit the fake encoder.
magjedf52d34d2017-08-29 00:58:52 -0700233 int encode_count = fake_encoder_->encode_count_;
noahricb1ce6632015-10-21 23:54:51 -0700234 EncodeFrame();
magjedf52d34d2017-08-29 00:58:52 -0700235 EXPECT_EQ(encode_count, fake_encoder_->encode_count_);
noahricb1ce6632015-10-21 23:54:51 -0700236}
237
Peter Boström4d71ede2015-05-19 23:09:35 +0200238TEST_F(VideoEncoderSoftwareFallbackWrapperTest, CanUtilizeFallbackEncoder) {
239 UtilizeFallbackEncoder();
240 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, fallback_wrapper_.Release());
241}
242
243TEST_F(VideoEncoderSoftwareFallbackWrapperTest,
noahricb1ce6632015-10-21 23:54:51 -0700244 InternalEncoderReleasedDuringFallback) {
magjedf52d34d2017-08-29 00:58:52 -0700245 EXPECT_EQ(0, fake_encoder_->release_count_);
noahricb1ce6632015-10-21 23:54:51 -0700246 UtilizeFallbackEncoder();
magjedf52d34d2017-08-29 00:58:52 -0700247 EXPECT_EQ(1, fake_encoder_->release_count_);
noahricb1ce6632015-10-21 23:54:51 -0700248 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, fallback_wrapper_.Release());
249 // No extra release when the fallback is released.
magjedf52d34d2017-08-29 00:58:52 -0700250 EXPECT_EQ(1, fake_encoder_->release_count_);
Peter Boström4d71ede2015-05-19 23:09:35 +0200251}
252
253TEST_F(VideoEncoderSoftwareFallbackWrapperTest,
254 InternalEncoderNotEncodingDuringFallback) {
255 UtilizeFallbackEncoder();
magjedf52d34d2017-08-29 00:58:52 -0700256 int encode_count = fake_encoder_->encode_count_;
noahricb1ce6632015-10-21 23:54:51 -0700257 EncodeFrame();
magjedf52d34d2017-08-29 00:58:52 -0700258 EXPECT_EQ(encode_count, fake_encoder_->encode_count_);
Peter Boström4d71ede2015-05-19 23:09:35 +0200259
260 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, fallback_wrapper_.Release());
261}
262
263TEST_F(VideoEncoderSoftwareFallbackWrapperTest,
264 CanRegisterCallbackWhileUsingFallbackEncoder) {
265 UtilizeFallbackEncoder();
266 // Registering an encode-complete callback should still work when fallback
267 // encoder is being used.
268 FakeEncodedImageCallback callback2;
269 fallback_wrapper_.RegisterEncodeCompleteCallback(&callback2);
magjedf52d34d2017-08-29 00:58:52 -0700270 EXPECT_EQ(&callback2, fake_encoder_->encode_complete_callback_);
Peter Boström4d71ede2015-05-19 23:09:35 +0200271
272 // Encoding a frame using the fallback should arrive at the new callback.
Peter Boström49e196a2015-10-23 15:58:18 +0200273 std::vector<FrameType> types(1, kVideoFrameKey);
nisse64ec8f82016-09-27 00:17:25 -0700274 frame_->set_timestamp(frame_->timestamp() + 1000);
Peter Boström4d71ede2015-05-19 23:09:35 +0200275 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK,
nisse64ec8f82016-09-27 00:17:25 -0700276 fallback_wrapper_.Encode(*frame_, nullptr, &types));
Peter Boström4d71ede2015-05-19 23:09:35 +0200277
278 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, fallback_wrapper_.Release());
279}
280
281TEST_F(VideoEncoderSoftwareFallbackWrapperTest,
282 SetChannelParametersForwardedDuringFallback) {
283 UtilizeFallbackEncoder();
magjedf52d34d2017-08-29 00:58:52 -0700284 EXPECT_EQ(0, fake_encoder_->set_channel_parameters_count_);
Peter Boström4d71ede2015-05-19 23:09:35 +0200285 fallback_wrapper_.SetChannelParameters(1, 1);
magjedf52d34d2017-08-29 00:58:52 -0700286 EXPECT_EQ(1, fake_encoder_->set_channel_parameters_count_);
Peter Boström4d71ede2015-05-19 23:09:35 +0200287 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, fallback_wrapper_.Release());
288}
289
290TEST_F(VideoEncoderSoftwareFallbackWrapperTest,
291 SetRatesForwardedDuringFallback) {
292 UtilizeFallbackEncoder();
magjedf52d34d2017-08-29 00:58:52 -0700293 EXPECT_EQ(1, fake_encoder_->set_rates_count_);
Erik Språng08127a92016-11-16 16:41:30 +0100294 fallback_wrapper_.SetRateAllocation(BitrateAllocation(), 1);
magjedf52d34d2017-08-29 00:58:52 -0700295 EXPECT_EQ(2, fake_encoder_->set_rates_count_);
Peter Boström4d71ede2015-05-19 23:09:35 +0200296 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, fallback_wrapper_.Release());
297}
298
299TEST_F(VideoEncoderSoftwareFallbackWrapperTest,
Peter Boströmeb66e802015-06-05 11:08:03 +0200300 SupportsNativeHandleForwardedWithoutFallback) {
301 fallback_wrapper_.SupportsNativeHandle();
magjedf52d34d2017-08-29 00:58:52 -0700302 EXPECT_EQ(1, fake_encoder_->supports_native_handle_count_);
Peter Boströmeb66e802015-06-05 11:08:03 +0200303}
304
305TEST_F(VideoEncoderSoftwareFallbackWrapperTest,
306 SupportsNativeHandleNotForwardedDuringFallback) {
307 UtilizeFallbackEncoder();
308 fallback_wrapper_.SupportsNativeHandle();
magjedf52d34d2017-08-29 00:58:52 -0700309 EXPECT_EQ(0, fake_encoder_->supports_native_handle_count_);
Peter Boströmeb66e802015-06-05 11:08:03 +0200310 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, fallback_wrapper_.Release());
311}
312
perkj275afc52016-09-01 00:21:16 -0700313TEST_F(VideoEncoderSoftwareFallbackWrapperTest, ReportsImplementationName) {
asapersson142fcc92017-08-17 08:58:54 -0700314 codec_.width = kWidth;
315 codec_.height = kHeight;
perkj275afc52016-09-01 00:21:16 -0700316 fallback_wrapper_.RegisterEncodeCompleteCallback(&callback_);
asapersson142fcc92017-08-17 08:58:54 -0700317 fallback_wrapper_.InitEncode(&codec_, kNumCores, kMaxPayloadSize);
perkj275afc52016-09-01 00:21:16 -0700318 EncodeFrame();
319 CheckLastEncoderName("fake-encoder");
320}
321
Peter Boströmb7d9a972015-12-18 16:01:11 +0100322TEST_F(VideoEncoderSoftwareFallbackWrapperTest,
323 ReportsFallbackImplementationName) {
324 UtilizeFallbackEncoder();
325 // Hard coded expected value since libvpx is the software implementation name
326 // for VP8. Change accordingly if the underlying implementation does.
perkj275afc52016-09-01 00:21:16 -0700327 CheckLastEncoderName("libvpx");
Peter Boströmb7d9a972015-12-18 16:01:11 +0100328}
329
asapersson22c76c42017-08-16 00:53:59 -0700330namespace {
Åsa Persson45bbc8a2017-11-13 10:16:47 +0100331const int kBitrateKbps = 200;
asapersson142fcc92017-08-17 08:58:54 -0700332const int kMinPixelsPerFrame = 1;
Åsa Persson45bbc8a2017-11-13 10:16:47 +0100333const char kFieldTrial[] = "WebRTC-VP8-Forced-Fallback-Encoder-v2";
asapersson22c76c42017-08-16 00:53:59 -0700334} // namespace
335
336class ForcedFallbackTest : public VideoEncoderSoftwareFallbackWrapperTest {
337 public:
Steve Antone78bcb92017-10-31 09:53:08 -0700338 explicit ForcedFallbackTest(const std::string& field_trials)
asapersson22c76c42017-08-16 00:53:59 -0700339 : VideoEncoderSoftwareFallbackWrapperTest(field_trials) {}
340
341 ~ForcedFallbackTest() override {}
342
343 protected:
344 void SetUp() override {
345 clock_.SetTimeMicros(1234);
346 ConfigureVp8Codec();
asapersson22c76c42017-08-16 00:53:59 -0700347 }
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
Åsa Persson45bbc8a2017-11-13 10:16:47 +0100369 void InitEncode(int width, int height) {
370 codec_.width = width;
371 codec_.height = height;
372 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, fallback_wrapper_.InitEncode(
373 &codec_, kNumCores, kMaxPayloadSize));
374 SetRateAllocation(kBitrateKbps);
375 }
376
asapersson22c76c42017-08-16 00:53:59 -0700377 void SetRateAllocation(uint32_t bitrate_kbps) {
378 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, fallback_wrapper_.SetRateAllocation(
379 rate_allocator_->GetAllocation(
380 bitrate_kbps * 1000, kFramerate),
381 kFramerate));
382 }
383
384 void EncodeFrameAndVerifyLastName(const char* expected_name) {
385 EncodeFrameAndVerifyLastName(expected_name, WEBRTC_VIDEO_CODEC_OK);
386 }
387
388 void EncodeFrameAndVerifyLastName(const char* expected_name,
389 int expected_ret) {
390 EncodeFrame(expected_ret);
391 CheckLastEncoderName(expected_name);
392 }
393
394 rtc::ScopedFakeClock clock_;
395};
396
397class ForcedFallbackTestEnabled : public ForcedFallbackTest {
398 public:
399 ForcedFallbackTestEnabled()
Steve Antone78bcb92017-10-31 09:53:08 -0700400 : ForcedFallbackTest(std::string(kFieldTrial) + "/Enabled-" +
Åsa Persson45bbc8a2017-11-13 10:16:47 +0100401 std::to_string(kMinPixelsPerFrame) + "," +
402 std::to_string(kWidth * kHeight) + ",30000/") {}
asapersson22c76c42017-08-16 00:53:59 -0700403};
404
405class ForcedFallbackTestDisabled : public ForcedFallbackTest {
406 public:
407 ForcedFallbackTestDisabled()
Steve Antone78bcb92017-10-31 09:53:08 -0700408 : ForcedFallbackTest(std::string(kFieldTrial) + "/Disabled/") {}
asapersson22c76c42017-08-16 00:53:59 -0700409};
410
411TEST_F(ForcedFallbackTestDisabled, NoFallbackWithoutFieldTrial) {
Åsa Persson45bbc8a2017-11-13 10:16:47 +0100412 // Resolution above max threshold.
413 InitEncode(kWidth + 1, kHeight);
414 EXPECT_EQ(1, fake_encoder_->init_encode_count_);
asapersson22c76c42017-08-16 00:53:59 -0700415 EncodeFrameAndVerifyLastName("fake-encoder");
Åsa Persson45bbc8a2017-11-13 10:16:47 +0100416
417 // Resolution at max threshold.
418 InitEncode(kWidth, kHeight);
asapersson22c76c42017-08-16 00:53:59 -0700419 EncodeFrameAndVerifyLastName("fake-encoder");
420}
421
Åsa Persson45bbc8a2017-11-13 10:16:47 +0100422TEST_F(ForcedFallbackTestEnabled, FallbackIfAtMaxResolutionLimit) {
423 // Resolution above max threshold.
424 InitEncode(kWidth + 1, kHeight);
425 EXPECT_EQ(1, fake_encoder_->init_encode_count_);
asapersson22c76c42017-08-16 00:53:59 -0700426 EncodeFrameAndVerifyLastName("fake-encoder");
Åsa Persson45bbc8a2017-11-13 10:16:47 +0100427
428 // Resolution at max threshold.
429 InitEncode(kWidth, kHeight);
asapersson22c76c42017-08-16 00:53:59 -0700430 EncodeFrameAndVerifyLastName("libvpx");
431}
432
Åsa Persson45bbc8a2017-11-13 10:16:47 +0100433TEST_F(ForcedFallbackTestEnabled, FallbackIsKeptWhenInitEncodeIsCalled) {
434 // Resolution above max threshold.
435 InitEncode(kWidth + 1, kHeight);
436 EXPECT_EQ(1, fake_encoder_->init_encode_count_);
asapersson22c76c42017-08-16 00:53:59 -0700437 EncodeFrameAndVerifyLastName("fake-encoder");
asapersson22c76c42017-08-16 00:53:59 -0700438
Åsa Persson45bbc8a2017-11-13 10:16:47 +0100439 // Resolution at max threshold.
440 InitEncode(kWidth, kHeight);
441 EncodeFrameAndVerifyLastName("libvpx");
asapersson22c76c42017-08-16 00:53:59 -0700442
Åsa Persson45bbc8a2017-11-13 10:16:47 +0100443 // Re-initialize encoder, still expect fallback.
444 InitEncode(kWidth / 2, kHeight / 2);
445 EXPECT_EQ(1, fake_encoder_->init_encode_count_); // No change.
asapersson22c76c42017-08-16 00:53:59 -0700446 EncodeFrameAndVerifyLastName("libvpx");
447}
448
Åsa Persson45bbc8a2017-11-13 10:16:47 +0100449TEST_F(ForcedFallbackTestEnabled, FallbackIsEndedWhenResolutionIsTooLarge) {
450 // Resolution above max threshold.
451 InitEncode(kWidth + 1, kHeight);
452 EXPECT_EQ(1, fake_encoder_->init_encode_count_);
asapersson22c76c42017-08-16 00:53:59 -0700453 EncodeFrameAndVerifyLastName("fake-encoder");
454
Åsa Persson45bbc8a2017-11-13 10:16:47 +0100455 // Resolution at max threshold.
456 InitEncode(kWidth, kHeight);
asapersson22c76c42017-08-16 00:53:59 -0700457 EncodeFrameAndVerifyLastName("libvpx");
Åsa Persson45bbc8a2017-11-13 10:16:47 +0100458
459 // Re-initialize encoder with a larger resolution, expect no fallback.
460 InitEncode(kWidth + 1, kHeight);
461 EXPECT_EQ(2, fake_encoder_->init_encode_count_);
462 EncodeFrameAndVerifyLastName("fake-encoder");
asapersson22c76c42017-08-16 00:53:59 -0700463}
464
Åsa Persson45bbc8a2017-11-13 10:16:47 +0100465TEST_F(ForcedFallbackTestEnabled, FallbackIsEndedForNonValidSettings) {
466 // Resolution at max threshold.
467 InitEncode(kWidth, kHeight);
468 EncodeFrameAndVerifyLastName("libvpx");
469
470 // Re-initialize encoder with invalid setting, expect no fallback.
471 codec_.VP8()->numberOfTemporalLayers = 2;
472 InitEncode(kWidth, kHeight);
473 EXPECT_EQ(1, fake_encoder_->init_encode_count_);
asapersson22c76c42017-08-16 00:53:59 -0700474 EncodeFrameAndVerifyLastName("fake-encoder");
Åsa Persson45bbc8a2017-11-13 10:16:47 +0100475
476 // Re-initialize encoder with valid setting but fallback disabled from now on.
477 codec_.VP8()->numberOfTemporalLayers = 1;
478 InitEncode(kWidth, kHeight);
479 EXPECT_EQ(2, fake_encoder_->init_encode_count_);
asapersson22c76c42017-08-16 00:53:59 -0700480 EncodeFrameAndVerifyLastName("fake-encoder");
481}
482
483TEST_F(ForcedFallbackTestEnabled, MultipleStartEndFallback) {
484 const int kNumRuns = 5;
Åsa Persson45bbc8a2017-11-13 10:16:47 +0100485 for (int i = 1; i <= kNumRuns; ++i) {
486 // Resolution at max threshold.
487 InitEncode(kWidth, kHeight);
asapersson22c76c42017-08-16 00:53:59 -0700488 EncodeFrameAndVerifyLastName("libvpx");
Åsa Persson45bbc8a2017-11-13 10:16:47 +0100489 // Resolution above max threshold.
490 InitEncode(kWidth + 1, kHeight);
491 EXPECT_EQ(i, fake_encoder_->init_encode_count_);
asapersson22c76c42017-08-16 00:53:59 -0700492 EncodeFrameAndVerifyLastName("fake-encoder");
493 }
494}
495
Åsa Persson45bbc8a2017-11-13 10:16:47 +0100496TEST_F(ForcedFallbackTestDisabled, GetScaleSettings) {
497 // Resolution above max threshold.
498 InitEncode(kWidth + 1, kHeight);
499 EXPECT_EQ(1, fake_encoder_->init_encode_count_);
asapersson22c76c42017-08-16 00:53:59 -0700500 EncodeFrameAndVerifyLastName("fake-encoder");
501
asapersson142fcc92017-08-17 08:58:54 -0700502 // Default min pixels per frame should be used.
503 const auto settings = fallback_wrapper_.GetScalingSettings();
504 EXPECT_TRUE(settings.enabled);
505 EXPECT_EQ(kDefaultMinPixelsPerFrame, settings.min_pixels_per_frame);
506}
507
Åsa Persson45bbc8a2017-11-13 10:16:47 +0100508TEST_F(ForcedFallbackTestEnabled, GetScaleSettingsWithNoFallback) {
509 // Resolution above max threshold.
510 InitEncode(kWidth + 1, kHeight);
asapersson142fcc92017-08-17 08:58:54 -0700511 EncodeFrameAndVerifyLastName("fake-encoder");
Åsa Persson45bbc8a2017-11-13 10:16:47 +0100512
513 // Configured min pixels per frame should be used.
514 const auto settings = fallback_wrapper_.GetScalingSettings();
515 EXPECT_TRUE(settings.enabled);
516 EXPECT_EQ(kMinPixelsPerFrame, settings.min_pixels_per_frame);
517 ASSERT_TRUE(settings.thresholds);
518 EXPECT_EQ(kLowThreshold, settings.thresholds->low);
519 EXPECT_EQ(kHighThreshold, settings.thresholds->high);
520}
521
522TEST_F(ForcedFallbackTestEnabled, GetScaleSettingsWithFallback) {
523 // Resolution at max threshold.
524 InitEncode(kWidth, kHeight);
asapersson142fcc92017-08-17 08:58:54 -0700525 EncodeFrameAndVerifyLastName("libvpx");
Åsa Persson45bbc8a2017-11-13 10:16:47 +0100526
asapersson142fcc92017-08-17 08:58:54 -0700527 // Configured min pixels per frame should be used.
528 const auto settings = fallback_wrapper_.GetScalingSettings();
529 EXPECT_TRUE(settings.enabled);
530 EXPECT_EQ(kMinPixelsPerFrame, settings.min_pixels_per_frame);
531}
532
Åsa Persson45bbc8a2017-11-13 10:16:47 +0100533TEST_F(ForcedFallbackTestEnabled, ScalingDisabledIfResizeOff) {
534 // Resolution at max threshold.
535 codec_.VP8()->automaticResizeOn = false;
536 InitEncode(kWidth, kHeight);
asapersson142fcc92017-08-17 08:58:54 -0700537 EncodeFrameAndVerifyLastName("libvpx");
538
Åsa Persson45bbc8a2017-11-13 10:16:47 +0100539 // Should be disabled for automatic resize off.
540 const auto settings = fallback_wrapper_.GetScalingSettings();
541 EXPECT_FALSE(settings.enabled);
asapersson142fcc92017-08-17 08:58:54 -0700542}
543
Peter Boström4d71ede2015-05-19 23:09:35 +0200544} // namespace webrtc