blob: e7d1fabea456565f757f9fd25fa8e1b90b751da7 [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
perkj275afc52016-09-01 00:21:16 -070015#include "webrtc/modules/video_coding/include/video_codec_interface.h"
Henrik Kjellander2557b862015-11-18 22:00:21 +010016#include "webrtc/modules/video_coding/include/video_error_codes.h"
kwibergac9f8762016-09-30 22:29:43 -070017#include "webrtc/test/gtest.h"
Peter Boström4d71ede2015-05-19 23:09:35 +020018
19namespace webrtc {
20
noahricb1ce6632015-10-21 23:54:51 -070021const int kWidth = 320;
22const int kHeight = 240;
Peter Boström4d71ede2015-05-19 23:09:35 +020023const size_t kMaxPayloadSize = 800;
24
25class VideoEncoderSoftwareFallbackWrapperTest : public ::testing::Test {
26 protected:
27 VideoEncoderSoftwareFallbackWrapperTest()
28 : fallback_wrapper_(kVideoCodecVP8, &fake_encoder_) {}
29
30 class CountingFakeEncoder : public VideoEncoder {
31 public:
32 int32_t InitEncode(const VideoCodec* codec_settings,
33 int32_t number_of_cores,
34 size_t max_payload_size) override {
35 ++init_encode_count_;
36 return init_encode_return_code_;
37 }
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -070038 int32_t Encode(const VideoFrame& frame,
Peter Boström4d71ede2015-05-19 23:09:35 +020039 const CodecSpecificInfo* codec_specific_info,
pbos22993e12015-10-19 02:39:06 -070040 const std::vector<FrameType>* frame_types) override {
Peter Boström4d71ede2015-05-19 23:09:35 +020041 ++encode_count_;
perkj275afc52016-09-01 00:21:16 -070042 if (encode_complete_callback_ &&
43 encode_return_code_ == WEBRTC_VIDEO_CODEC_OK) {
44 CodecSpecificInfo info;
45 info.codec_name = ImplementationName();
46 encode_complete_callback_->OnEncodedImage(EncodedImage(), &info,
47 nullptr);
48 }
noahricb1ce6632015-10-21 23:54:51 -070049 return encode_return_code_;
Peter Boström4d71ede2015-05-19 23:09:35 +020050 }
51
52 int32_t RegisterEncodeCompleteCallback(
53 EncodedImageCallback* callback) override {
54 encode_complete_callback_ = callback;
55 return WEBRTC_VIDEO_CODEC_OK;
56 }
57
58 int32_t Release() override {
59 ++release_count_;
60 return WEBRTC_VIDEO_CODEC_OK;
61 }
62
63 int32_t SetChannelParameters(uint32_t packet_loss, int64_t rtt) override {
64 ++set_channel_parameters_count_;
65 return WEBRTC_VIDEO_CODEC_OK;
66 }
67
sprang1369c832016-11-10 08:30:33 -080068 int32_t SetRates(uint32_t bitrate, uint32_t framerate) override {
Peter Boström4d71ede2015-05-19 23:09:35 +020069 ++set_rates_count_;
70 return WEBRTC_VIDEO_CODEC_OK;
71 }
72
73 void OnDroppedFrame() override { ++on_dropped_frame_count_; }
74
Peter Boströmeb66e802015-06-05 11:08:03 +020075 bool SupportsNativeHandle() const override {
76 ++supports_native_handle_count_;
77 return false;
78 }
79
Peter Boströmb7d9a972015-12-18 16:01:11 +010080 const char* ImplementationName() const override {
81 return "fake-encoder";
82 }
83
Peter Boström4d71ede2015-05-19 23:09:35 +020084 int init_encode_count_ = 0;
85 int32_t init_encode_return_code_ = WEBRTC_VIDEO_CODEC_OK;
noahricb1ce6632015-10-21 23:54:51 -070086 int32_t encode_return_code_ = WEBRTC_VIDEO_CODEC_OK;
Peter Boström4d71ede2015-05-19 23:09:35 +020087 int encode_count_ = 0;
88 EncodedImageCallback* encode_complete_callback_ = nullptr;
89 int release_count_ = 0;
90 int set_channel_parameters_count_ = 0;
91 int set_rates_count_ = 0;
92 int on_dropped_frame_count_ = 0;
Peter Boströmeb66e802015-06-05 11:08:03 +020093 mutable int supports_native_handle_count_ = 0;
Peter Boström4d71ede2015-05-19 23:09:35 +020094 };
95
96 class FakeEncodedImageCallback : public EncodedImageCallback {
97 public:
Sergey Ulanov525df3f2016-08-02 17:46:41 -070098 Result OnEncodedImage(
99 const EncodedImage& encoded_image,
100 const CodecSpecificInfo* codec_specific_info,
101 const RTPFragmentationHeader* fragmentation) override {
102 ++callback_count_;
perkj275afc52016-09-01 00:21:16 -0700103 last_codec_name_ = codec_specific_info->codec_name;
Sergey Ulanov525df3f2016-08-02 17:46:41 -0700104 return Result(Result::OK, callback_count_);
Peter Boström4d71ede2015-05-19 23:09:35 +0200105 }
106 int callback_count_ = 0;
perkj275afc52016-09-01 00:21:16 -0700107 std::string last_codec_name_;
Peter Boström4d71ede2015-05-19 23:09:35 +0200108 };
109
110 void UtilizeFallbackEncoder();
noahricb1ce6632015-10-21 23:54:51 -0700111 void FallbackFromEncodeRequest();
112 void EncodeFrame();
perkj275afc52016-09-01 00:21:16 -0700113 void CheckLastEncoderName(const char* expected_name) {
114 EXPECT_STREQ(expected_name, callback_.last_codec_name_.c_str());
115 }
Peter Boström4d71ede2015-05-19 23:09:35 +0200116
117 FakeEncodedImageCallback callback_;
118 CountingFakeEncoder fake_encoder_;
119 VideoEncoderSoftwareFallbackWrapper fallback_wrapper_;
120 VideoCodec codec_ = {};
nisse64ec8f82016-09-27 00:17:25 -0700121 std::unique_ptr<VideoFrame> frame_;
Peter Boström4d71ede2015-05-19 23:09:35 +0200122};
123
noahricb1ce6632015-10-21 23:54:51 -0700124void VideoEncoderSoftwareFallbackWrapperTest::EncodeFrame() {
nisse64ec8f82016-09-27 00:17:25 -0700125 rtc::scoped_refptr<I420Buffer> buffer = I420Buffer::Create(
126 kWidth, kHeight, kWidth, (kWidth + 1) / 2, (kWidth + 1) / 2);
127 buffer->SetToBlack();
nisse776870a2016-09-21 03:52:16 -0700128 std::vector<FrameType> types(1, kVideoFrameKey);
nisse64ec8f82016-09-27 00:17:25 -0700129
130 frame_.reset(new VideoFrame(buffer, 0, 0, webrtc::kVideoRotation_0));
noahricb1ce6632015-10-21 23:54:51 -0700131 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK,
nisse64ec8f82016-09-27 00:17:25 -0700132 fallback_wrapper_.Encode(*frame_, nullptr, &types));
noahricb1ce6632015-10-21 23:54:51 -0700133}
134
Peter Boström4d71ede2015-05-19 23:09:35 +0200135void VideoEncoderSoftwareFallbackWrapperTest::UtilizeFallbackEncoder() {
Peter Boström4d71ede2015-05-19 23:09:35 +0200136 fallback_wrapper_.RegisterEncodeCompleteCallback(&callback_);
137 EXPECT_EQ(&callback_, fake_encoder_.encode_complete_callback_);
138
139 // Register with failing fake encoder. Should succeed with VP8 fallback.
140 codec_.codecType = kVideoCodecVP8;
141 codec_.maxFramerate = 30;
142 codec_.width = kWidth;
143 codec_.height = kHeight;
144 fake_encoder_.init_encode_return_code_ = WEBRTC_VIDEO_CODEC_ERROR;
145 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK,
146 fallback_wrapper_.InitEncode(&codec_, 2, kMaxPayloadSize));
sprang1369c832016-11-10 08:30:33 -0800147 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, fallback_wrapper_.SetRates(300, 30));
Peter Boström4d71ede2015-05-19 23:09:35 +0200148
noahricb1ce6632015-10-21 23:54:51 -0700149 int callback_count = callback_.callback_count_;
150 int encode_count = fake_encoder_.encode_count_;
151 EncodeFrame();
152 EXPECT_EQ(encode_count, fake_encoder_.encode_count_);
153 EXPECT_EQ(callback_count + 1, callback_.callback_count_);
154}
Peter Boström4d71ede2015-05-19 23:09:35 +0200155
noahricb1ce6632015-10-21 23:54:51 -0700156void VideoEncoderSoftwareFallbackWrapperTest::FallbackFromEncodeRequest() {
157 fallback_wrapper_.RegisterEncodeCompleteCallback(&callback_);
158 codec_.codecType = kVideoCodecVP8;
159 codec_.maxFramerate = 30;
160 codec_.width = kWidth;
161 codec_.height = kHeight;
162 fallback_wrapper_.InitEncode(&codec_, 2, kMaxPayloadSize);
sprang1369c832016-11-10 08:30:33 -0800163 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, fallback_wrapper_.SetRates(300, 30));
noahricb1ce6632015-10-21 23:54:51 -0700164 EXPECT_EQ(1, fake_encoder_.init_encode_count_);
165
166 // Have the non-fallback encoder request a software fallback.
167 fake_encoder_.encode_return_code_ = WEBRTC_VIDEO_CODEC_FALLBACK_SOFTWARE;
168 int callback_count = callback_.callback_count_;
169 int encode_count = fake_encoder_.encode_count_;
170 EncodeFrame();
171 // Single encode request, which returned failure.
172 EXPECT_EQ(encode_count + 1, fake_encoder_.encode_count_);
173 EXPECT_EQ(callback_count + 1, callback_.callback_count_);
Peter Boström4d71ede2015-05-19 23:09:35 +0200174}
175
176TEST_F(VideoEncoderSoftwareFallbackWrapperTest, InitializesEncoder) {
177 VideoCodec codec = {};
178 fallback_wrapper_.InitEncode(&codec, 2, kMaxPayloadSize);
179 EXPECT_EQ(1, fake_encoder_.init_encode_count_);
180}
181
noahricb1ce6632015-10-21 23:54:51 -0700182TEST_F(VideoEncoderSoftwareFallbackWrapperTest, EncodeRequestsFallback) {
183 FallbackFromEncodeRequest();
184 // After fallback, further encodes shouldn't hit the fake encoder.
185 int encode_count = fake_encoder_.encode_count_;
186 EncodeFrame();
187 EXPECT_EQ(encode_count, fake_encoder_.encode_count_);
188}
189
Peter Boström4d71ede2015-05-19 23:09:35 +0200190TEST_F(VideoEncoderSoftwareFallbackWrapperTest, CanUtilizeFallbackEncoder) {
191 UtilizeFallbackEncoder();
192 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, fallback_wrapper_.Release());
193}
194
195TEST_F(VideoEncoderSoftwareFallbackWrapperTest,
noahricb1ce6632015-10-21 23:54:51 -0700196 InternalEncoderReleasedDuringFallback) {
Peter Boström4d71ede2015-05-19 23:09:35 +0200197 EXPECT_EQ(0, fake_encoder_.release_count_);
noahricb1ce6632015-10-21 23:54:51 -0700198 UtilizeFallbackEncoder();
199 EXPECT_EQ(1, fake_encoder_.release_count_);
200 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, fallback_wrapper_.Release());
201 // No extra release when the fallback is released.
202 EXPECT_EQ(1, fake_encoder_.release_count_);
Peter Boström4d71ede2015-05-19 23:09:35 +0200203}
204
205TEST_F(VideoEncoderSoftwareFallbackWrapperTest,
206 InternalEncoderNotEncodingDuringFallback) {
207 UtilizeFallbackEncoder();
noahricb1ce6632015-10-21 23:54:51 -0700208 int encode_count = fake_encoder_.encode_count_;
209 EncodeFrame();
210 EXPECT_EQ(encode_count, fake_encoder_.encode_count_);
Peter Boström4d71ede2015-05-19 23:09:35 +0200211
212 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, fallback_wrapper_.Release());
213}
214
215TEST_F(VideoEncoderSoftwareFallbackWrapperTest,
216 CanRegisterCallbackWhileUsingFallbackEncoder) {
217 UtilizeFallbackEncoder();
218 // Registering an encode-complete callback should still work when fallback
219 // encoder is being used.
220 FakeEncodedImageCallback callback2;
221 fallback_wrapper_.RegisterEncodeCompleteCallback(&callback2);
222 EXPECT_EQ(&callback2, fake_encoder_.encode_complete_callback_);
223
224 // Encoding a frame using the fallback should arrive at the new callback.
Peter Boström49e196a2015-10-23 15:58:18 +0200225 std::vector<FrameType> types(1, kVideoFrameKey);
nisse64ec8f82016-09-27 00:17:25 -0700226 frame_->set_timestamp(frame_->timestamp() + 1000);
Peter Boström4d71ede2015-05-19 23:09:35 +0200227 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK,
nisse64ec8f82016-09-27 00:17:25 -0700228 fallback_wrapper_.Encode(*frame_, nullptr, &types));
Peter Boström4d71ede2015-05-19 23:09:35 +0200229
230 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, fallback_wrapper_.Release());
231}
232
233TEST_F(VideoEncoderSoftwareFallbackWrapperTest,
234 SetChannelParametersForwardedDuringFallback) {
235 UtilizeFallbackEncoder();
236 EXPECT_EQ(0, fake_encoder_.set_channel_parameters_count_);
237 fallback_wrapper_.SetChannelParameters(1, 1);
238 EXPECT_EQ(1, fake_encoder_.set_channel_parameters_count_);
239 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, fallback_wrapper_.Release());
240}
241
242TEST_F(VideoEncoderSoftwareFallbackWrapperTest,
243 SetRatesForwardedDuringFallback) {
244 UtilizeFallbackEncoder();
245 EXPECT_EQ(1, fake_encoder_.set_rates_count_);
sprang1369c832016-11-10 08:30:33 -0800246 fallback_wrapper_.SetRates(1, 1);
Peter Boström4d71ede2015-05-19 23:09:35 +0200247 EXPECT_EQ(2, fake_encoder_.set_rates_count_);
248 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, fallback_wrapper_.Release());
249}
250
251TEST_F(VideoEncoderSoftwareFallbackWrapperTest,
252 OnDroppedFrameForwardedWithoutFallback) {
253 fallback_wrapper_.OnDroppedFrame();
254 EXPECT_EQ(1, fake_encoder_.on_dropped_frame_count_);
255}
256
257TEST_F(VideoEncoderSoftwareFallbackWrapperTest,
258 OnDroppedFrameNotForwardedDuringFallback) {
259 UtilizeFallbackEncoder();
260 fallback_wrapper_.OnDroppedFrame();
261 EXPECT_EQ(0, fake_encoder_.on_dropped_frame_count_);
262 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, fallback_wrapper_.Release());
263}
264
Peter Boströmeb66e802015-06-05 11:08:03 +0200265TEST_F(VideoEncoderSoftwareFallbackWrapperTest,
266 SupportsNativeHandleForwardedWithoutFallback) {
267 fallback_wrapper_.SupportsNativeHandle();
268 EXPECT_EQ(1, fake_encoder_.supports_native_handle_count_);
269}
270
271TEST_F(VideoEncoderSoftwareFallbackWrapperTest,
272 SupportsNativeHandleNotForwardedDuringFallback) {
273 UtilizeFallbackEncoder();
274 fallback_wrapper_.SupportsNativeHandle();
275 EXPECT_EQ(0, fake_encoder_.supports_native_handle_count_);
276 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, fallback_wrapper_.Release());
277}
278
perkj275afc52016-09-01 00:21:16 -0700279TEST_F(VideoEncoderSoftwareFallbackWrapperTest, ReportsImplementationName) {
280 VideoCodec codec = {};
281 fallback_wrapper_.RegisterEncodeCompleteCallback(&callback_);
282 fallback_wrapper_.InitEncode(&codec, 2, kMaxPayloadSize);
283 EncodeFrame();
284 CheckLastEncoderName("fake-encoder");
285}
286
Peter Boströmb7d9a972015-12-18 16:01:11 +0100287TEST_F(VideoEncoderSoftwareFallbackWrapperTest,
288 ReportsFallbackImplementationName) {
289 UtilizeFallbackEncoder();
290 // Hard coded expected value since libvpx is the software implementation name
291 // for VP8. Change accordingly if the underlying implementation does.
perkj275afc52016-09-01 00:21:16 -0700292 CheckLastEncoderName("libvpx");
Peter Boströmb7d9a972015-12-18 16:01:11 +0100293}
294
Peter Boström4d71ede2015-05-19 23:09:35 +0200295} // namespace webrtc