blob: 07b569c6813811dd5247b1e1420ce36c52b4dc1f [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ång566124a2018-04-23 12:32:22 +020087 int32_t SetRateAllocation(const VideoBitrateAllocation& bitrate_allocation,
Erik Språng08127a92016-11-16 16:41:30 +010088 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 {
Niels Möller225c7872018-02-22 15:03:53 +0100103 return VideoEncoder::ScalingSettings(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;
Erik Språng82fad3d2018-03-21 09:57:23 +0100174 rate_allocator_.reset(new SimulcastRateAllocator(codec_));
Erik Språng08127a92016-11-16 16:41:30 +0100175
magjedf52d34d2017-08-29 00:58:52 -0700176 fake_encoder_->init_encode_return_code_ = WEBRTC_VIDEO_CODEC_ERROR;
Peter Boström4d71ede2015-05-19 23:09:35 +0200177 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK,
asapersson22c76c42017-08-16 00:53:59 -0700178 fallback_wrapper_.InitEncode(&codec_, kNumCores, kMaxPayloadSize));
179 EXPECT_EQ(
180 WEBRTC_VIDEO_CODEC_OK,
181 fallback_wrapper_.SetRateAllocation(
182 rate_allocator_->GetAllocation(300000, kFramerate), kFramerate));
Peter Boström4d71ede2015-05-19 23:09:35 +0200183
noahricb1ce6632015-10-21 23:54:51 -0700184 int callback_count = callback_.callback_count_;
magjedf52d34d2017-08-29 00:58:52 -0700185 int encode_count = fake_encoder_->encode_count_;
noahricb1ce6632015-10-21 23:54:51 -0700186 EncodeFrame();
magjedf52d34d2017-08-29 00:58:52 -0700187 EXPECT_EQ(encode_count, fake_encoder_->encode_count_);
noahricb1ce6632015-10-21 23:54:51 -0700188 EXPECT_EQ(callback_count + 1, callback_.callback_count_);
189}
Peter Boström4d71ede2015-05-19 23:09:35 +0200190
noahricb1ce6632015-10-21 23:54:51 -0700191void VideoEncoderSoftwareFallbackWrapperTest::FallbackFromEncodeRequest() {
192 fallback_wrapper_.RegisterEncodeCompleteCallback(&callback_);
193 codec_.codecType = kVideoCodecVP8;
asapersson22c76c42017-08-16 00:53:59 -0700194 codec_.maxFramerate = kFramerate;
noahricb1ce6632015-10-21 23:54:51 -0700195 codec_.width = kWidth;
196 codec_.height = kHeight;
Erik Språng08127a92016-11-16 16:41:30 +0100197 codec_.VP8()->numberOfTemporalLayers = 1;
Erik Språng82fad3d2018-03-21 09:57:23 +0100198 rate_allocator_.reset(new SimulcastRateAllocator(codec_));
noahricb1ce6632015-10-21 23:54:51 -0700199 fallback_wrapper_.InitEncode(&codec_, 2, kMaxPayloadSize);
asapersson22c76c42017-08-16 00:53:59 -0700200 EXPECT_EQ(
201 WEBRTC_VIDEO_CODEC_OK,
202 fallback_wrapper_.SetRateAllocation(
203 rate_allocator_->GetAllocation(300000, kFramerate), kFramerate));
magjedf52d34d2017-08-29 00:58:52 -0700204 EXPECT_EQ(1, fake_encoder_->init_encode_count_);
noahricb1ce6632015-10-21 23:54:51 -0700205
206 // Have the non-fallback encoder request a software fallback.
magjedf52d34d2017-08-29 00:58:52 -0700207 fake_encoder_->encode_return_code_ = WEBRTC_VIDEO_CODEC_FALLBACK_SOFTWARE;
noahricb1ce6632015-10-21 23:54:51 -0700208 int callback_count = callback_.callback_count_;
magjedf52d34d2017-08-29 00:58:52 -0700209 int encode_count = fake_encoder_->encode_count_;
noahricb1ce6632015-10-21 23:54:51 -0700210 EncodeFrame();
211 // Single encode request, which returned failure.
magjedf52d34d2017-08-29 00:58:52 -0700212 EXPECT_EQ(encode_count + 1, fake_encoder_->encode_count_);
noahricb1ce6632015-10-21 23:54:51 -0700213 EXPECT_EQ(callback_count + 1, callback_.callback_count_);
Peter Boström4d71ede2015-05-19 23:09:35 +0200214}
215
216TEST_F(VideoEncoderSoftwareFallbackWrapperTest, InitializesEncoder) {
217 VideoCodec codec = {};
218 fallback_wrapper_.InitEncode(&codec, 2, kMaxPayloadSize);
magjedf52d34d2017-08-29 00:58:52 -0700219 EXPECT_EQ(1, fake_encoder_->init_encode_count_);
Peter Boström4d71ede2015-05-19 23:09:35 +0200220}
221
noahricb1ce6632015-10-21 23:54:51 -0700222TEST_F(VideoEncoderSoftwareFallbackWrapperTest, EncodeRequestsFallback) {
223 FallbackFromEncodeRequest();
224 // After fallback, further encodes shouldn't hit the fake encoder.
magjedf52d34d2017-08-29 00:58:52 -0700225 int encode_count = fake_encoder_->encode_count_;
noahricb1ce6632015-10-21 23:54:51 -0700226 EncodeFrame();
magjedf52d34d2017-08-29 00:58:52 -0700227 EXPECT_EQ(encode_count, fake_encoder_->encode_count_);
noahricb1ce6632015-10-21 23:54:51 -0700228}
229
Peter Boström4d71ede2015-05-19 23:09:35 +0200230TEST_F(VideoEncoderSoftwareFallbackWrapperTest, CanUtilizeFallbackEncoder) {
231 UtilizeFallbackEncoder();
232 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, fallback_wrapper_.Release());
233}
234
235TEST_F(VideoEncoderSoftwareFallbackWrapperTest,
noahricb1ce6632015-10-21 23:54:51 -0700236 InternalEncoderReleasedDuringFallback) {
magjedf52d34d2017-08-29 00:58:52 -0700237 EXPECT_EQ(0, fake_encoder_->release_count_);
noahricb1ce6632015-10-21 23:54:51 -0700238 UtilizeFallbackEncoder();
magjedf52d34d2017-08-29 00:58:52 -0700239 EXPECT_EQ(1, fake_encoder_->release_count_);
noahricb1ce6632015-10-21 23:54:51 -0700240 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, fallback_wrapper_.Release());
241 // No extra release when the fallback is released.
magjedf52d34d2017-08-29 00:58:52 -0700242 EXPECT_EQ(1, fake_encoder_->release_count_);
Peter Boström4d71ede2015-05-19 23:09:35 +0200243}
244
245TEST_F(VideoEncoderSoftwareFallbackWrapperTest,
246 InternalEncoderNotEncodingDuringFallback) {
247 UtilizeFallbackEncoder();
magjedf52d34d2017-08-29 00:58:52 -0700248 int encode_count = fake_encoder_->encode_count_;
noahricb1ce6632015-10-21 23:54:51 -0700249 EncodeFrame();
magjedf52d34d2017-08-29 00:58:52 -0700250 EXPECT_EQ(encode_count, fake_encoder_->encode_count_);
Peter Boström4d71ede2015-05-19 23:09:35 +0200251
252 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, fallback_wrapper_.Release());
253}
254
255TEST_F(VideoEncoderSoftwareFallbackWrapperTest,
256 CanRegisterCallbackWhileUsingFallbackEncoder) {
257 UtilizeFallbackEncoder();
258 // Registering an encode-complete callback should still work when fallback
259 // encoder is being used.
260 FakeEncodedImageCallback callback2;
261 fallback_wrapper_.RegisterEncodeCompleteCallback(&callback2);
magjedf52d34d2017-08-29 00:58:52 -0700262 EXPECT_EQ(&callback2, fake_encoder_->encode_complete_callback_);
Peter Boström4d71ede2015-05-19 23:09:35 +0200263
264 // Encoding a frame using the fallback should arrive at the new callback.
Peter Boström49e196a2015-10-23 15:58:18 +0200265 std::vector<FrameType> types(1, kVideoFrameKey);
nisse64ec8f82016-09-27 00:17:25 -0700266 frame_->set_timestamp(frame_->timestamp() + 1000);
Peter Boström4d71ede2015-05-19 23:09:35 +0200267 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK,
nisse64ec8f82016-09-27 00:17:25 -0700268 fallback_wrapper_.Encode(*frame_, nullptr, &types));
Peter Boström4d71ede2015-05-19 23:09:35 +0200269
270 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, fallback_wrapper_.Release());
271}
272
273TEST_F(VideoEncoderSoftwareFallbackWrapperTest,
274 SetChannelParametersForwardedDuringFallback) {
275 UtilizeFallbackEncoder();
magjedf52d34d2017-08-29 00:58:52 -0700276 EXPECT_EQ(0, fake_encoder_->set_channel_parameters_count_);
Peter Boström4d71ede2015-05-19 23:09:35 +0200277 fallback_wrapper_.SetChannelParameters(1, 1);
magjedf52d34d2017-08-29 00:58:52 -0700278 EXPECT_EQ(1, fake_encoder_->set_channel_parameters_count_);
Peter Boström4d71ede2015-05-19 23:09:35 +0200279 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, fallback_wrapper_.Release());
280}
281
282TEST_F(VideoEncoderSoftwareFallbackWrapperTest,
283 SetRatesForwardedDuringFallback) {
284 UtilizeFallbackEncoder();
magjedf52d34d2017-08-29 00:58:52 -0700285 EXPECT_EQ(1, fake_encoder_->set_rates_count_);
Erik Språng566124a2018-04-23 12:32:22 +0200286 fallback_wrapper_.SetRateAllocation(VideoBitrateAllocation(), 1);
magjedf52d34d2017-08-29 00:58:52 -0700287 EXPECT_EQ(2, fake_encoder_->set_rates_count_);
Peter Boström4d71ede2015-05-19 23:09:35 +0200288 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, fallback_wrapper_.Release());
289}
290
291TEST_F(VideoEncoderSoftwareFallbackWrapperTest,
Peter Boströmeb66e802015-06-05 11:08:03 +0200292 SupportsNativeHandleForwardedWithoutFallback) {
293 fallback_wrapper_.SupportsNativeHandle();
magjedf52d34d2017-08-29 00:58:52 -0700294 EXPECT_EQ(1, fake_encoder_->supports_native_handle_count_);
Peter Boströmeb66e802015-06-05 11:08:03 +0200295}
296
297TEST_F(VideoEncoderSoftwareFallbackWrapperTest,
298 SupportsNativeHandleNotForwardedDuringFallback) {
299 UtilizeFallbackEncoder();
300 fallback_wrapper_.SupportsNativeHandle();
magjedf52d34d2017-08-29 00:58:52 -0700301 EXPECT_EQ(0, fake_encoder_->supports_native_handle_count_);
Peter Boströmeb66e802015-06-05 11:08:03 +0200302 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, fallback_wrapper_.Release());
303}
304
perkj275afc52016-09-01 00:21:16 -0700305TEST_F(VideoEncoderSoftwareFallbackWrapperTest, ReportsImplementationName) {
asapersson142fcc92017-08-17 08:58:54 -0700306 codec_.width = kWidth;
307 codec_.height = kHeight;
perkj275afc52016-09-01 00:21:16 -0700308 fallback_wrapper_.RegisterEncodeCompleteCallback(&callback_);
asapersson142fcc92017-08-17 08:58:54 -0700309 fallback_wrapper_.InitEncode(&codec_, kNumCores, kMaxPayloadSize);
perkj275afc52016-09-01 00:21:16 -0700310 EncodeFrame();
311 CheckLastEncoderName("fake-encoder");
312}
313
Peter Boströmb7d9a972015-12-18 16:01:11 +0100314TEST_F(VideoEncoderSoftwareFallbackWrapperTest,
315 ReportsFallbackImplementationName) {
316 UtilizeFallbackEncoder();
317 // Hard coded expected value since libvpx is the software implementation name
318 // for VP8. Change accordingly if the underlying implementation does.
perkj275afc52016-09-01 00:21:16 -0700319 CheckLastEncoderName("libvpx");
Peter Boströmb7d9a972015-12-18 16:01:11 +0100320}
321
asapersson22c76c42017-08-16 00:53:59 -0700322namespace {
Åsa Persson45bbc8a2017-11-13 10:16:47 +0100323const int kBitrateKbps = 200;
asapersson142fcc92017-08-17 08:58:54 -0700324const int kMinPixelsPerFrame = 1;
Åsa Persson45bbc8a2017-11-13 10:16:47 +0100325const char kFieldTrial[] = "WebRTC-VP8-Forced-Fallback-Encoder-v2";
asapersson22c76c42017-08-16 00:53:59 -0700326} // namespace
327
328class ForcedFallbackTest : public VideoEncoderSoftwareFallbackWrapperTest {
329 public:
Steve Antone78bcb92017-10-31 09:53:08 -0700330 explicit ForcedFallbackTest(const std::string& field_trials)
asapersson22c76c42017-08-16 00:53:59 -0700331 : VideoEncoderSoftwareFallbackWrapperTest(field_trials) {}
332
333 ~ForcedFallbackTest() override {}
334
335 protected:
336 void SetUp() override {
337 clock_.SetTimeMicros(1234);
338 ConfigureVp8Codec();
asapersson22c76c42017-08-16 00:53:59 -0700339 }
340
341 void TearDown() override {
342 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, fallback_wrapper_.Release());
343 }
344
345 void ConfigureVp8Codec() {
346 fallback_wrapper_.RegisterEncodeCompleteCallback(&callback_);
asapersson22c76c42017-08-16 00:53:59 -0700347 codec_.codecType = kVideoCodecVP8;
348 codec_.maxFramerate = kFramerate;
349 codec_.width = kWidth;
350 codec_.height = kHeight;
351 codec_.VP8()->numberOfTemporalLayers = 1;
asapersson142fcc92017-08-17 08:58:54 -0700352 codec_.VP8()->automaticResizeOn = true;
353 codec_.VP8()->frameDroppingOn = true;
Erik Språng82fad3d2018-03-21 09:57:23 +0100354 rate_allocator_.reset(new SimulcastRateAllocator(codec_));
asapersson22c76c42017-08-16 00:53:59 -0700355 }
356
Åsa Persson45bbc8a2017-11-13 10:16:47 +0100357 void InitEncode(int width, int height) {
358 codec_.width = width;
359 codec_.height = height;
360 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, fallback_wrapper_.InitEncode(
361 &codec_, kNumCores, kMaxPayloadSize));
362 SetRateAllocation(kBitrateKbps);
363 }
364
asapersson22c76c42017-08-16 00:53:59 -0700365 void SetRateAllocation(uint32_t bitrate_kbps) {
366 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, fallback_wrapper_.SetRateAllocation(
367 rate_allocator_->GetAllocation(
368 bitrate_kbps * 1000, kFramerate),
369 kFramerate));
370 }
371
372 void EncodeFrameAndVerifyLastName(const char* expected_name) {
373 EncodeFrameAndVerifyLastName(expected_name, WEBRTC_VIDEO_CODEC_OK);
374 }
375
376 void EncodeFrameAndVerifyLastName(const char* expected_name,
377 int expected_ret) {
378 EncodeFrame(expected_ret);
379 CheckLastEncoderName(expected_name);
380 }
381
382 rtc::ScopedFakeClock clock_;
383};
384
385class ForcedFallbackTestEnabled : public ForcedFallbackTest {
386 public:
387 ForcedFallbackTestEnabled()
Steve Antone78bcb92017-10-31 09:53:08 -0700388 : ForcedFallbackTest(std::string(kFieldTrial) + "/Enabled-" +
Åsa Persson45bbc8a2017-11-13 10:16:47 +0100389 std::to_string(kMinPixelsPerFrame) + "," +
390 std::to_string(kWidth * kHeight) + ",30000/") {}
asapersson22c76c42017-08-16 00:53:59 -0700391};
392
393class ForcedFallbackTestDisabled : public ForcedFallbackTest {
394 public:
395 ForcedFallbackTestDisabled()
Steve Antone78bcb92017-10-31 09:53:08 -0700396 : ForcedFallbackTest(std::string(kFieldTrial) + "/Disabled/") {}
asapersson22c76c42017-08-16 00:53:59 -0700397};
398
399TEST_F(ForcedFallbackTestDisabled, NoFallbackWithoutFieldTrial) {
Åsa Persson45bbc8a2017-11-13 10:16:47 +0100400 // Resolution above max threshold.
401 InitEncode(kWidth + 1, kHeight);
402 EXPECT_EQ(1, fake_encoder_->init_encode_count_);
asapersson22c76c42017-08-16 00:53:59 -0700403 EncodeFrameAndVerifyLastName("fake-encoder");
Åsa Persson45bbc8a2017-11-13 10:16:47 +0100404
405 // Resolution at max threshold.
406 InitEncode(kWidth, kHeight);
asapersson22c76c42017-08-16 00:53:59 -0700407 EncodeFrameAndVerifyLastName("fake-encoder");
408}
409
Åsa Persson45bbc8a2017-11-13 10:16:47 +0100410TEST_F(ForcedFallbackTestEnabled, FallbackIfAtMaxResolutionLimit) {
411 // Resolution above max threshold.
412 InitEncode(kWidth + 1, kHeight);
413 EXPECT_EQ(1, fake_encoder_->init_encode_count_);
asapersson22c76c42017-08-16 00:53:59 -0700414 EncodeFrameAndVerifyLastName("fake-encoder");
Åsa Persson45bbc8a2017-11-13 10:16:47 +0100415
416 // Resolution at max threshold.
417 InitEncode(kWidth, kHeight);
asapersson22c76c42017-08-16 00:53:59 -0700418 EncodeFrameAndVerifyLastName("libvpx");
419}
420
Åsa Persson45bbc8a2017-11-13 10:16:47 +0100421TEST_F(ForcedFallbackTestEnabled, FallbackIsKeptWhenInitEncodeIsCalled) {
422 // Resolution above max threshold.
423 InitEncode(kWidth + 1, kHeight);
424 EXPECT_EQ(1, fake_encoder_->init_encode_count_);
asapersson22c76c42017-08-16 00:53:59 -0700425 EncodeFrameAndVerifyLastName("fake-encoder");
asapersson22c76c42017-08-16 00:53:59 -0700426
Åsa Persson45bbc8a2017-11-13 10:16:47 +0100427 // Resolution at max threshold.
428 InitEncode(kWidth, kHeight);
429 EncodeFrameAndVerifyLastName("libvpx");
asapersson22c76c42017-08-16 00:53:59 -0700430
Åsa Persson45bbc8a2017-11-13 10:16:47 +0100431 // Re-initialize encoder, still expect fallback.
432 InitEncode(kWidth / 2, kHeight / 2);
433 EXPECT_EQ(1, fake_encoder_->init_encode_count_); // No change.
asapersson22c76c42017-08-16 00:53:59 -0700434 EncodeFrameAndVerifyLastName("libvpx");
435}
436
Åsa Persson45bbc8a2017-11-13 10:16:47 +0100437TEST_F(ForcedFallbackTestEnabled, FallbackIsEndedWhenResolutionIsTooLarge) {
438 // Resolution above max threshold.
439 InitEncode(kWidth + 1, kHeight);
440 EXPECT_EQ(1, fake_encoder_->init_encode_count_);
asapersson22c76c42017-08-16 00:53:59 -0700441 EncodeFrameAndVerifyLastName("fake-encoder");
442
Åsa Persson45bbc8a2017-11-13 10:16:47 +0100443 // Resolution at max threshold.
444 InitEncode(kWidth, kHeight);
asapersson22c76c42017-08-16 00:53:59 -0700445 EncodeFrameAndVerifyLastName("libvpx");
Åsa Persson45bbc8a2017-11-13 10:16:47 +0100446
447 // Re-initialize encoder with a larger resolution, expect no fallback.
448 InitEncode(kWidth + 1, kHeight);
449 EXPECT_EQ(2, fake_encoder_->init_encode_count_);
450 EncodeFrameAndVerifyLastName("fake-encoder");
asapersson22c76c42017-08-16 00:53:59 -0700451}
452
Åsa Persson45bbc8a2017-11-13 10:16:47 +0100453TEST_F(ForcedFallbackTestEnabled, FallbackIsEndedForNonValidSettings) {
454 // Resolution at max threshold.
455 InitEncode(kWidth, kHeight);
456 EncodeFrameAndVerifyLastName("libvpx");
457
458 // Re-initialize encoder with invalid setting, expect no fallback.
459 codec_.VP8()->numberOfTemporalLayers = 2;
460 InitEncode(kWidth, kHeight);
461 EXPECT_EQ(1, fake_encoder_->init_encode_count_);
asapersson22c76c42017-08-16 00:53:59 -0700462 EncodeFrameAndVerifyLastName("fake-encoder");
Åsa Persson45bbc8a2017-11-13 10:16:47 +0100463
464 // Re-initialize encoder with valid setting but fallback disabled from now on.
465 codec_.VP8()->numberOfTemporalLayers = 1;
466 InitEncode(kWidth, kHeight);
467 EXPECT_EQ(2, fake_encoder_->init_encode_count_);
asapersson22c76c42017-08-16 00:53:59 -0700468 EncodeFrameAndVerifyLastName("fake-encoder");
469}
470
471TEST_F(ForcedFallbackTestEnabled, MultipleStartEndFallback) {
472 const int kNumRuns = 5;
Åsa Persson45bbc8a2017-11-13 10:16:47 +0100473 for (int i = 1; i <= kNumRuns; ++i) {
474 // Resolution at max threshold.
475 InitEncode(kWidth, kHeight);
asapersson22c76c42017-08-16 00:53:59 -0700476 EncodeFrameAndVerifyLastName("libvpx");
Åsa Persson45bbc8a2017-11-13 10:16:47 +0100477 // Resolution above max threshold.
478 InitEncode(kWidth + 1, kHeight);
479 EXPECT_EQ(i, fake_encoder_->init_encode_count_);
asapersson22c76c42017-08-16 00:53:59 -0700480 EncodeFrameAndVerifyLastName("fake-encoder");
481 }
482}
483
Åsa Persson45bbc8a2017-11-13 10:16:47 +0100484TEST_F(ForcedFallbackTestDisabled, GetScaleSettings) {
485 // Resolution above max threshold.
486 InitEncode(kWidth + 1, kHeight);
487 EXPECT_EQ(1, fake_encoder_->init_encode_count_);
asapersson22c76c42017-08-16 00:53:59 -0700488 EncodeFrameAndVerifyLastName("fake-encoder");
489
asapersson142fcc92017-08-17 08:58:54 -0700490 // Default min pixels per frame should be used.
491 const auto settings = fallback_wrapper_.GetScalingSettings();
Niels Möller225c7872018-02-22 15:03:53 +0100492 EXPECT_TRUE(settings.thresholds.has_value());
asapersson142fcc92017-08-17 08:58:54 -0700493 EXPECT_EQ(kDefaultMinPixelsPerFrame, settings.min_pixels_per_frame);
494}
495
Åsa Persson45bbc8a2017-11-13 10:16:47 +0100496TEST_F(ForcedFallbackTestEnabled, GetScaleSettingsWithNoFallback) {
497 // Resolution above max threshold.
498 InitEncode(kWidth + 1, kHeight);
asapersson142fcc92017-08-17 08:58:54 -0700499 EncodeFrameAndVerifyLastName("fake-encoder");
Åsa Persson45bbc8a2017-11-13 10:16:47 +0100500
501 // Configured min pixels per frame should be used.
502 const auto settings = fallback_wrapper_.GetScalingSettings();
Åsa Persson45bbc8a2017-11-13 10:16:47 +0100503 EXPECT_EQ(kMinPixelsPerFrame, settings.min_pixels_per_frame);
504 ASSERT_TRUE(settings.thresholds);
505 EXPECT_EQ(kLowThreshold, settings.thresholds->low);
506 EXPECT_EQ(kHighThreshold, settings.thresholds->high);
507}
508
509TEST_F(ForcedFallbackTestEnabled, GetScaleSettingsWithFallback) {
510 // Resolution at max threshold.
511 InitEncode(kWidth, kHeight);
asapersson142fcc92017-08-17 08:58:54 -0700512 EncodeFrameAndVerifyLastName("libvpx");
Åsa Persson45bbc8a2017-11-13 10:16:47 +0100513
asapersson142fcc92017-08-17 08:58:54 -0700514 // Configured min pixels per frame should be used.
515 const auto settings = fallback_wrapper_.GetScalingSettings();
Niels Möller225c7872018-02-22 15:03:53 +0100516 EXPECT_TRUE(settings.thresholds.has_value());
asapersson142fcc92017-08-17 08:58:54 -0700517 EXPECT_EQ(kMinPixelsPerFrame, settings.min_pixels_per_frame);
518}
519
Åsa Persson45bbc8a2017-11-13 10:16:47 +0100520TEST_F(ForcedFallbackTestEnabled, ScalingDisabledIfResizeOff) {
521 // Resolution at max threshold.
522 codec_.VP8()->automaticResizeOn = false;
523 InitEncode(kWidth, kHeight);
asapersson142fcc92017-08-17 08:58:54 -0700524 EncodeFrameAndVerifyLastName("libvpx");
525
Åsa Persson45bbc8a2017-11-13 10:16:47 +0100526 // Should be disabled for automatic resize off.
527 const auto settings = fallback_wrapper_.GetScalingSettings();
Niels Möller225c7872018-02-22 15:03:53 +0100528 EXPECT_FALSE(settings.thresholds.has_value());
asapersson142fcc92017-08-17 08:58:54 -0700529}
530
Peter Boström4d71ede2015-05-19 23:09:35 +0200531} // namespace webrtc