blob: e196587f050a06187db6adb450ab8a4b6695eb9a [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"
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() {
Magnus Jedvert7a721e82017-06-14 11:28:08 +0200128 rtc::scoped_refptr<I420Buffer> buffer = I420Buffer::Create(kWidth, kHeight);
nisseaf916892017-01-10 07:44:26 -0800129 I420Buffer::SetBlack(buffer);
nisse776870a2016-09-21 03:52:16 -0700130 std::vector<FrameType> types(1, kVideoFrameKey);
nisse64ec8f82016-09-27 00:17:25 -0700131
132 frame_.reset(new VideoFrame(buffer, 0, 0, webrtc::kVideoRotation_0));
noahricb1ce6632015-10-21 23:54:51 -0700133 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK,
nisse64ec8f82016-09-27 00:17:25 -0700134 fallback_wrapper_.Encode(*frame_, nullptr, &types));
noahricb1ce6632015-10-21 23:54:51 -0700135}
136
Peter Boström4d71ede2015-05-19 23:09:35 +0200137void VideoEncoderSoftwareFallbackWrapperTest::UtilizeFallbackEncoder() {
Peter Boström4d71ede2015-05-19 23:09:35 +0200138 fallback_wrapper_.RegisterEncodeCompleteCallback(&callback_);
139 EXPECT_EQ(&callback_, fake_encoder_.encode_complete_callback_);
140
141 // Register with failing fake encoder. Should succeed with VP8 fallback.
142 codec_.codecType = kVideoCodecVP8;
143 codec_.maxFramerate = 30;
144 codec_.width = kWidth;
145 codec_.height = kHeight;
Erik Språng08127a92016-11-16 16:41:30 +0100146 codec_.VP8()->numberOfTemporalLayers = 1;
147 std::unique_ptr<TemporalLayersFactory> tl_factory(
148 new TemporalLayersFactory());
149 codec_.VP8()->tl_factory = tl_factory.get();
150 rate_allocator_.reset(
151 new SimulcastRateAllocator(codec_, std::move(tl_factory)));
152
Peter Boström4d71ede2015-05-19 23:09:35 +0200153 fake_encoder_.init_encode_return_code_ = WEBRTC_VIDEO_CODEC_ERROR;
154 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK,
155 fallback_wrapper_.InitEncode(&codec_, 2, kMaxPayloadSize));
Erik Språng08127a92016-11-16 16:41:30 +0100156 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK,
157 fallback_wrapper_.SetRateAllocation(
158 rate_allocator_->GetAllocation(300000, 30), 30));
Peter Boström4d71ede2015-05-19 23:09:35 +0200159
noahricb1ce6632015-10-21 23:54:51 -0700160 int callback_count = callback_.callback_count_;
161 int encode_count = fake_encoder_.encode_count_;
162 EncodeFrame();
163 EXPECT_EQ(encode_count, fake_encoder_.encode_count_);
164 EXPECT_EQ(callback_count + 1, callback_.callback_count_);
165}
Peter Boström4d71ede2015-05-19 23:09:35 +0200166
noahricb1ce6632015-10-21 23:54:51 -0700167void VideoEncoderSoftwareFallbackWrapperTest::FallbackFromEncodeRequest() {
168 fallback_wrapper_.RegisterEncodeCompleteCallback(&callback_);
169 codec_.codecType = kVideoCodecVP8;
170 codec_.maxFramerate = 30;
171 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)));
noahricb1ce6632015-10-21 23:54:51 -0700179 fallback_wrapper_.InitEncode(&codec_, 2, kMaxPayloadSize);
Erik Språng08127a92016-11-16 16:41:30 +0100180 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK,
181 fallback_wrapper_.SetRateAllocation(
182 rate_allocator_->GetAllocation(300000, 30), 30));
noahricb1ce6632015-10-21 23:54:51 -0700183 EXPECT_EQ(1, fake_encoder_.init_encode_count_);
184
185 // Have the non-fallback encoder request a software fallback.
186 fake_encoder_.encode_return_code_ = WEBRTC_VIDEO_CODEC_FALLBACK_SOFTWARE;
187 int callback_count = callback_.callback_count_;
188 int encode_count = fake_encoder_.encode_count_;
189 EncodeFrame();
190 // Single encode request, which returned failure.
191 EXPECT_EQ(encode_count + 1, fake_encoder_.encode_count_);
192 EXPECT_EQ(callback_count + 1, callback_.callback_count_);
Peter Boström4d71ede2015-05-19 23:09:35 +0200193}
194
195TEST_F(VideoEncoderSoftwareFallbackWrapperTest, InitializesEncoder) {
196 VideoCodec codec = {};
197 fallback_wrapper_.InitEncode(&codec, 2, kMaxPayloadSize);
198 EXPECT_EQ(1, fake_encoder_.init_encode_count_);
199}
200
noahricb1ce6632015-10-21 23:54:51 -0700201TEST_F(VideoEncoderSoftwareFallbackWrapperTest, EncodeRequestsFallback) {
202 FallbackFromEncodeRequest();
203 // After fallback, further encodes shouldn't hit the fake encoder.
204 int encode_count = fake_encoder_.encode_count_;
205 EncodeFrame();
206 EXPECT_EQ(encode_count, fake_encoder_.encode_count_);
207}
208
Peter Boström4d71ede2015-05-19 23:09:35 +0200209TEST_F(VideoEncoderSoftwareFallbackWrapperTest, CanUtilizeFallbackEncoder) {
210 UtilizeFallbackEncoder();
211 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, fallback_wrapper_.Release());
212}
213
214TEST_F(VideoEncoderSoftwareFallbackWrapperTest,
noahricb1ce6632015-10-21 23:54:51 -0700215 InternalEncoderReleasedDuringFallback) {
Peter Boström4d71ede2015-05-19 23:09:35 +0200216 EXPECT_EQ(0, fake_encoder_.release_count_);
noahricb1ce6632015-10-21 23:54:51 -0700217 UtilizeFallbackEncoder();
218 EXPECT_EQ(1, fake_encoder_.release_count_);
219 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, fallback_wrapper_.Release());
220 // No extra release when the fallback is released.
221 EXPECT_EQ(1, fake_encoder_.release_count_);
Peter Boström4d71ede2015-05-19 23:09:35 +0200222}
223
224TEST_F(VideoEncoderSoftwareFallbackWrapperTest,
225 InternalEncoderNotEncodingDuringFallback) {
226 UtilizeFallbackEncoder();
noahricb1ce6632015-10-21 23:54:51 -0700227 int encode_count = fake_encoder_.encode_count_;
228 EncodeFrame();
229 EXPECT_EQ(encode_count, fake_encoder_.encode_count_);
Peter Boström4d71ede2015-05-19 23:09:35 +0200230
231 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, fallback_wrapper_.Release());
232}
233
234TEST_F(VideoEncoderSoftwareFallbackWrapperTest,
235 CanRegisterCallbackWhileUsingFallbackEncoder) {
236 UtilizeFallbackEncoder();
237 // Registering an encode-complete callback should still work when fallback
238 // encoder is being used.
239 FakeEncodedImageCallback callback2;
240 fallback_wrapper_.RegisterEncodeCompleteCallback(&callback2);
241 EXPECT_EQ(&callback2, fake_encoder_.encode_complete_callback_);
242
243 // Encoding a frame using the fallback should arrive at the new callback.
Peter Boström49e196a2015-10-23 15:58:18 +0200244 std::vector<FrameType> types(1, kVideoFrameKey);
nisse64ec8f82016-09-27 00:17:25 -0700245 frame_->set_timestamp(frame_->timestamp() + 1000);
Peter Boström4d71ede2015-05-19 23:09:35 +0200246 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK,
nisse64ec8f82016-09-27 00:17:25 -0700247 fallback_wrapper_.Encode(*frame_, nullptr, &types));
Peter Boström4d71ede2015-05-19 23:09:35 +0200248
249 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, fallback_wrapper_.Release());
250}
251
252TEST_F(VideoEncoderSoftwareFallbackWrapperTest,
253 SetChannelParametersForwardedDuringFallback) {
254 UtilizeFallbackEncoder();
255 EXPECT_EQ(0, fake_encoder_.set_channel_parameters_count_);
256 fallback_wrapper_.SetChannelParameters(1, 1);
257 EXPECT_EQ(1, fake_encoder_.set_channel_parameters_count_);
258 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, fallback_wrapper_.Release());
259}
260
261TEST_F(VideoEncoderSoftwareFallbackWrapperTest,
262 SetRatesForwardedDuringFallback) {
263 UtilizeFallbackEncoder();
264 EXPECT_EQ(1, fake_encoder_.set_rates_count_);
Erik Språng08127a92016-11-16 16:41:30 +0100265 fallback_wrapper_.SetRateAllocation(BitrateAllocation(), 1);
Peter Boström4d71ede2015-05-19 23:09:35 +0200266 EXPECT_EQ(2, fake_encoder_.set_rates_count_);
267 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, fallback_wrapper_.Release());
268}
269
270TEST_F(VideoEncoderSoftwareFallbackWrapperTest,
Peter Boströmeb66e802015-06-05 11:08:03 +0200271 SupportsNativeHandleForwardedWithoutFallback) {
272 fallback_wrapper_.SupportsNativeHandle();
273 EXPECT_EQ(1, fake_encoder_.supports_native_handle_count_);
274}
275
276TEST_F(VideoEncoderSoftwareFallbackWrapperTest,
277 SupportsNativeHandleNotForwardedDuringFallback) {
278 UtilizeFallbackEncoder();
279 fallback_wrapper_.SupportsNativeHandle();
280 EXPECT_EQ(0, fake_encoder_.supports_native_handle_count_);
281 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, fallback_wrapper_.Release());
282}
283
perkj275afc52016-09-01 00:21:16 -0700284TEST_F(VideoEncoderSoftwareFallbackWrapperTest, ReportsImplementationName) {
285 VideoCodec codec = {};
286 fallback_wrapper_.RegisterEncodeCompleteCallback(&callback_);
287 fallback_wrapper_.InitEncode(&codec, 2, kMaxPayloadSize);
288 EncodeFrame();
289 CheckLastEncoderName("fake-encoder");
290}
291
Peter Boströmb7d9a972015-12-18 16:01:11 +0100292TEST_F(VideoEncoderSoftwareFallbackWrapperTest,
293 ReportsFallbackImplementationName) {
294 UtilizeFallbackEncoder();
295 // Hard coded expected value since libvpx is the software implementation name
296 // for VP8. Change accordingly if the underlying implementation does.
perkj275afc52016-09-01 00:21:16 -0700297 CheckLastEncoderName("libvpx");
Peter Boströmb7d9a972015-12-18 16:01:11 +0100298}
299
Peter Boström4d71ede2015-05-19 23:09:35 +0200300} // namespace webrtc