blob: 0616a5ffc5a36780f25a301983363dcc13a19e5a [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"
Erik Språng08127a92016-11-16 16:41:30 +010016#include "webrtc/base/checks.h"
17#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"
Erik Språng08127a92016-11-16 16:41:30 +010020#include "webrtc/modules/video_coding/utility/simulcast_rate_allocator.h"
kwibergac9f8762016-09-30 22:29:43 -070021#include "webrtc/test/gtest.h"
Peter Boström4d71ede2015-05-19 23:09:35 +020022
23namespace webrtc {
24
noahricb1ce6632015-10-21 23:54:51 -070025const int kWidth = 320;
26const int kHeight = 240;
Peter Boström4d71ede2015-05-19 23:09:35 +020027const size_t kMaxPayloadSize = 800;
28
29class VideoEncoderSoftwareFallbackWrapperTest : public ::testing::Test {
30 protected:
31 VideoEncoderSoftwareFallbackWrapperTest()
magjed509e4fe2016-11-18 01:34:11 -080032 : fallback_wrapper_(cricket::VideoCodec("VP8"), &fake_encoder_) {}
Peter Boström4d71ede2015-05-19 23:09:35 +020033
34 class CountingFakeEncoder : public VideoEncoder {
35 public:
36 int32_t InitEncode(const VideoCodec* codec_settings,
37 int32_t number_of_cores,
38 size_t max_payload_size) override {
39 ++init_encode_count_;
40 return init_encode_return_code_;
41 }
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -070042 int32_t Encode(const VideoFrame& frame,
Peter Boström4d71ede2015-05-19 23:09:35 +020043 const CodecSpecificInfo* codec_specific_info,
pbos22993e12015-10-19 02:39:06 -070044 const std::vector<FrameType>* frame_types) override {
Peter Boström4d71ede2015-05-19 23:09:35 +020045 ++encode_count_;
perkj275afc52016-09-01 00:21:16 -070046 if (encode_complete_callback_ &&
47 encode_return_code_ == WEBRTC_VIDEO_CODEC_OK) {
48 CodecSpecificInfo info;
49 info.codec_name = ImplementationName();
50 encode_complete_callback_->OnEncodedImage(EncodedImage(), &info,
51 nullptr);
52 }
noahricb1ce6632015-10-21 23:54:51 -070053 return encode_return_code_;
Peter Boström4d71ede2015-05-19 23:09:35 +020054 }
55
56 int32_t RegisterEncodeCompleteCallback(
57 EncodedImageCallback* callback) override {
58 encode_complete_callback_ = callback;
59 return WEBRTC_VIDEO_CODEC_OK;
60 }
61
62 int32_t Release() override {
63 ++release_count_;
64 return WEBRTC_VIDEO_CODEC_OK;
65 }
66
67 int32_t SetChannelParameters(uint32_t packet_loss, int64_t rtt) override {
68 ++set_channel_parameters_count_;
69 return WEBRTC_VIDEO_CODEC_OK;
70 }
71
Erik Språng08127a92016-11-16 16:41:30 +010072 int32_t SetRateAllocation(const BitrateAllocation& bitrate_allocation,
73 uint32_t framerate) override {
Peter Boström4d71ede2015-05-19 23:09:35 +020074 ++set_rates_count_;
75 return WEBRTC_VIDEO_CODEC_OK;
76 }
77
Peter Boströmeb66e802015-06-05 11:08:03 +020078 bool SupportsNativeHandle() const override {
79 ++supports_native_handle_count_;
80 return false;
81 }
82
Peter Boströmb7d9a972015-12-18 16:01:11 +010083 const char* ImplementationName() const override {
84 return "fake-encoder";
85 }
86
Peter Boström4d71ede2015-05-19 23:09:35 +020087 int init_encode_count_ = 0;
88 int32_t init_encode_return_code_ = WEBRTC_VIDEO_CODEC_OK;
noahricb1ce6632015-10-21 23:54:51 -070089 int32_t encode_return_code_ = WEBRTC_VIDEO_CODEC_OK;
Peter Boström4d71ede2015-05-19 23:09:35 +020090 int encode_count_ = 0;
91 EncodedImageCallback* encode_complete_callback_ = nullptr;
92 int release_count_ = 0;
93 int set_channel_parameters_count_ = 0;
94 int set_rates_count_ = 0;
Peter Boströmeb66e802015-06-05 11:08:03 +020095 mutable int supports_native_handle_count_ = 0;
Peter Boström4d71ede2015-05-19 23:09:35 +020096 };
97
98 class FakeEncodedImageCallback : public EncodedImageCallback {
99 public:
Sergey Ulanov525df3f2016-08-02 17:46:41 -0700100 Result OnEncodedImage(
101 const EncodedImage& encoded_image,
102 const CodecSpecificInfo* codec_specific_info,
103 const RTPFragmentationHeader* fragmentation) override {
104 ++callback_count_;
perkj275afc52016-09-01 00:21:16 -0700105 last_codec_name_ = codec_specific_info->codec_name;
Sergey Ulanov525df3f2016-08-02 17:46:41 -0700106 return Result(Result::OK, callback_count_);
Peter Boström4d71ede2015-05-19 23:09:35 +0200107 }
108 int callback_count_ = 0;
perkj275afc52016-09-01 00:21:16 -0700109 std::string last_codec_name_;
Peter Boström4d71ede2015-05-19 23:09:35 +0200110 };
111
112 void UtilizeFallbackEncoder();
noahricb1ce6632015-10-21 23:54:51 -0700113 void FallbackFromEncodeRequest();
114 void EncodeFrame();
perkj275afc52016-09-01 00:21:16 -0700115 void CheckLastEncoderName(const char* expected_name) {
116 EXPECT_STREQ(expected_name, callback_.last_codec_name_.c_str());
117 }
Peter Boström4d71ede2015-05-19 23:09:35 +0200118
119 FakeEncodedImageCallback callback_;
120 CountingFakeEncoder fake_encoder_;
121 VideoEncoderSoftwareFallbackWrapper fallback_wrapper_;
122 VideoCodec codec_ = {};
nisse64ec8f82016-09-27 00:17:25 -0700123 std::unique_ptr<VideoFrame> frame_;
Erik Språng08127a92016-11-16 16:41:30 +0100124 std::unique_ptr<SimulcastRateAllocator> rate_allocator_;
Peter Boström4d71ede2015-05-19 23:09:35 +0200125};
126
noahricb1ce6632015-10-21 23:54:51 -0700127void VideoEncoderSoftwareFallbackWrapperTest::EncodeFrame() {
nisse64ec8f82016-09-27 00:17:25 -0700128 rtc::scoped_refptr<I420Buffer> buffer = I420Buffer::Create(
129 kWidth, kHeight, kWidth, (kWidth + 1) / 2, (kWidth + 1) / 2);
nisseaf916892017-01-10 07:44:26 -0800130 I420Buffer::SetBlack(buffer);
nisse776870a2016-09-21 03:52:16 -0700131 std::vector<FrameType> types(1, kVideoFrameKey);
nisse64ec8f82016-09-27 00:17:25 -0700132
133 frame_.reset(new VideoFrame(buffer, 0, 0, webrtc::kVideoRotation_0));
noahricb1ce6632015-10-21 23:54:51 -0700134 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK,
nisse64ec8f82016-09-27 00:17:25 -0700135 fallback_wrapper_.Encode(*frame_, nullptr, &types));
noahricb1ce6632015-10-21 23:54:51 -0700136}
137
Peter Boström4d71ede2015-05-19 23:09:35 +0200138void VideoEncoderSoftwareFallbackWrapperTest::UtilizeFallbackEncoder() {
Peter Boström4d71ede2015-05-19 23:09:35 +0200139 fallback_wrapper_.RegisterEncodeCompleteCallback(&callback_);
140 EXPECT_EQ(&callback_, fake_encoder_.encode_complete_callback_);
141
142 // Register with failing fake encoder. Should succeed with VP8 fallback.
143 codec_.codecType = kVideoCodecVP8;
144 codec_.maxFramerate = 30;
145 codec_.width = kWidth;
146 codec_.height = kHeight;
Erik Språng08127a92016-11-16 16:41:30 +0100147 codec_.VP8()->numberOfTemporalLayers = 1;
148 std::unique_ptr<TemporalLayersFactory> tl_factory(
149 new TemporalLayersFactory());
150 codec_.VP8()->tl_factory = tl_factory.get();
151 rate_allocator_.reset(
152 new SimulcastRateAllocator(codec_, std::move(tl_factory)));
153
Peter Boström4d71ede2015-05-19 23:09:35 +0200154 fake_encoder_.init_encode_return_code_ = WEBRTC_VIDEO_CODEC_ERROR;
155 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK,
156 fallback_wrapper_.InitEncode(&codec_, 2, kMaxPayloadSize));
Erik Språng08127a92016-11-16 16:41:30 +0100157 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK,
158 fallback_wrapper_.SetRateAllocation(
159 rate_allocator_->GetAllocation(300000, 30), 30));
Peter Boström4d71ede2015-05-19 23:09:35 +0200160
noahricb1ce6632015-10-21 23:54:51 -0700161 int callback_count = callback_.callback_count_;
162 int encode_count = fake_encoder_.encode_count_;
163 EncodeFrame();
164 EXPECT_EQ(encode_count, fake_encoder_.encode_count_);
165 EXPECT_EQ(callback_count + 1, callback_.callback_count_);
166}
Peter Boström4d71ede2015-05-19 23:09:35 +0200167
noahricb1ce6632015-10-21 23:54:51 -0700168void VideoEncoderSoftwareFallbackWrapperTest::FallbackFromEncodeRequest() {
169 fallback_wrapper_.RegisterEncodeCompleteCallback(&callback_);
170 codec_.codecType = kVideoCodecVP8;
171 codec_.maxFramerate = 30;
172 codec_.width = kWidth;
173 codec_.height = kHeight;
Erik Språng08127a92016-11-16 16:41:30 +0100174 codec_.VP8()->numberOfTemporalLayers = 1;
175 std::unique_ptr<TemporalLayersFactory> tl_factory(
176 new TemporalLayersFactory());
177 codec_.VP8()->tl_factory = tl_factory.get();
178 rate_allocator_.reset(
179 new SimulcastRateAllocator(codec_, std::move(tl_factory)));
noahricb1ce6632015-10-21 23:54:51 -0700180 fallback_wrapper_.InitEncode(&codec_, 2, kMaxPayloadSize);
Erik Språng08127a92016-11-16 16:41:30 +0100181 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK,
182 fallback_wrapper_.SetRateAllocation(
183 rate_allocator_->GetAllocation(300000, 30), 30));
noahricb1ce6632015-10-21 23:54:51 -0700184 EXPECT_EQ(1, fake_encoder_.init_encode_count_);
185
186 // Have the non-fallback encoder request a software fallback.
187 fake_encoder_.encode_return_code_ = WEBRTC_VIDEO_CODEC_FALLBACK_SOFTWARE;
188 int callback_count = callback_.callback_count_;
189 int encode_count = fake_encoder_.encode_count_;
190 EncodeFrame();
191 // Single encode request, which returned failure.
192 EXPECT_EQ(encode_count + 1, fake_encoder_.encode_count_);
193 EXPECT_EQ(callback_count + 1, callback_.callback_count_);
Peter Boström4d71ede2015-05-19 23:09:35 +0200194}
195
196TEST_F(VideoEncoderSoftwareFallbackWrapperTest, InitializesEncoder) {
197 VideoCodec codec = {};
198 fallback_wrapper_.InitEncode(&codec, 2, kMaxPayloadSize);
199 EXPECT_EQ(1, fake_encoder_.init_encode_count_);
200}
201
noahricb1ce6632015-10-21 23:54:51 -0700202TEST_F(VideoEncoderSoftwareFallbackWrapperTest, EncodeRequestsFallback) {
203 FallbackFromEncodeRequest();
204 // After fallback, further encodes shouldn't hit the fake encoder.
205 int encode_count = fake_encoder_.encode_count_;
206 EncodeFrame();
207 EXPECT_EQ(encode_count, fake_encoder_.encode_count_);
208}
209
Peter Boström4d71ede2015-05-19 23:09:35 +0200210TEST_F(VideoEncoderSoftwareFallbackWrapperTest, CanUtilizeFallbackEncoder) {
211 UtilizeFallbackEncoder();
212 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, fallback_wrapper_.Release());
213}
214
215TEST_F(VideoEncoderSoftwareFallbackWrapperTest,
noahricb1ce6632015-10-21 23:54:51 -0700216 InternalEncoderReleasedDuringFallback) {
Peter Boström4d71ede2015-05-19 23:09:35 +0200217 EXPECT_EQ(0, fake_encoder_.release_count_);
noahricb1ce6632015-10-21 23:54:51 -0700218 UtilizeFallbackEncoder();
219 EXPECT_EQ(1, fake_encoder_.release_count_);
220 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, fallback_wrapper_.Release());
221 // No extra release when the fallback is released.
222 EXPECT_EQ(1, fake_encoder_.release_count_);
Peter Boström4d71ede2015-05-19 23:09:35 +0200223}
224
225TEST_F(VideoEncoderSoftwareFallbackWrapperTest,
226 InternalEncoderNotEncodingDuringFallback) {
227 UtilizeFallbackEncoder();
noahricb1ce6632015-10-21 23:54:51 -0700228 int encode_count = fake_encoder_.encode_count_;
229 EncodeFrame();
230 EXPECT_EQ(encode_count, fake_encoder_.encode_count_);
Peter Boström4d71ede2015-05-19 23:09:35 +0200231
232 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, fallback_wrapper_.Release());
233}
234
235TEST_F(VideoEncoderSoftwareFallbackWrapperTest,
236 CanRegisterCallbackWhileUsingFallbackEncoder) {
237 UtilizeFallbackEncoder();
238 // Registering an encode-complete callback should still work when fallback
239 // encoder is being used.
240 FakeEncodedImageCallback callback2;
241 fallback_wrapper_.RegisterEncodeCompleteCallback(&callback2);
242 EXPECT_EQ(&callback2, fake_encoder_.encode_complete_callback_);
243
244 // Encoding a frame using the fallback should arrive at the new callback.
Peter Boström49e196a2015-10-23 15:58:18 +0200245 std::vector<FrameType> types(1, kVideoFrameKey);
nisse64ec8f82016-09-27 00:17:25 -0700246 frame_->set_timestamp(frame_->timestamp() + 1000);
Peter Boström4d71ede2015-05-19 23:09:35 +0200247 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK,
nisse64ec8f82016-09-27 00:17:25 -0700248 fallback_wrapper_.Encode(*frame_, nullptr, &types));
Peter Boström4d71ede2015-05-19 23:09:35 +0200249
250 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, fallback_wrapper_.Release());
251}
252
253TEST_F(VideoEncoderSoftwareFallbackWrapperTest,
254 SetChannelParametersForwardedDuringFallback) {
255 UtilizeFallbackEncoder();
256 EXPECT_EQ(0, fake_encoder_.set_channel_parameters_count_);
257 fallback_wrapper_.SetChannelParameters(1, 1);
258 EXPECT_EQ(1, fake_encoder_.set_channel_parameters_count_);
259 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, fallback_wrapper_.Release());
260}
261
262TEST_F(VideoEncoderSoftwareFallbackWrapperTest,
263 SetRatesForwardedDuringFallback) {
264 UtilizeFallbackEncoder();
265 EXPECT_EQ(1, fake_encoder_.set_rates_count_);
Erik Språng08127a92016-11-16 16:41:30 +0100266 fallback_wrapper_.SetRateAllocation(BitrateAllocation(), 1);
Peter Boström4d71ede2015-05-19 23:09:35 +0200267 EXPECT_EQ(2, fake_encoder_.set_rates_count_);
268 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, fallback_wrapper_.Release());
269}
270
271TEST_F(VideoEncoderSoftwareFallbackWrapperTest,
Peter Boströmeb66e802015-06-05 11:08:03 +0200272 SupportsNativeHandleForwardedWithoutFallback) {
273 fallback_wrapper_.SupportsNativeHandle();
274 EXPECT_EQ(1, fake_encoder_.supports_native_handle_count_);
275}
276
277TEST_F(VideoEncoderSoftwareFallbackWrapperTest,
278 SupportsNativeHandleNotForwardedDuringFallback) {
279 UtilizeFallbackEncoder();
280 fallback_wrapper_.SupportsNativeHandle();
281 EXPECT_EQ(0, fake_encoder_.supports_native_handle_count_);
282 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, fallback_wrapper_.Release());
283}
284
perkj275afc52016-09-01 00:21:16 -0700285TEST_F(VideoEncoderSoftwareFallbackWrapperTest, ReportsImplementationName) {
286 VideoCodec codec = {};
287 fallback_wrapper_.RegisterEncodeCompleteCallback(&callback_);
288 fallback_wrapper_.InitEncode(&codec, 2, kMaxPayloadSize);
289 EncodeFrame();
290 CheckLastEncoderName("fake-encoder");
291}
292
Peter Boströmb7d9a972015-12-18 16:01:11 +0100293TEST_F(VideoEncoderSoftwareFallbackWrapperTest,
294 ReportsFallbackImplementationName) {
295 UtilizeFallbackEncoder();
296 // Hard coded expected value since libvpx is the software implementation name
297 // for VP8. Change accordingly if the underlying implementation does.
perkj275afc52016-09-01 00:21:16 -0700298 CheckLastEncoderName("libvpx");
Peter Boströmb7d9a972015-12-18 16:01:11 +0100299}
300
Peter Boström4d71ede2015-05-19 23:09:35 +0200301} // namespace webrtc