blob: ac006bb872a0515e77b9788c47bebf0292057781 [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
11#include "webrtc/video_encoder.h"
12
13#include "testing/gtest/include/gtest/gtest.h"
Henrik Kjellander2557b862015-11-18 22:00:21 +010014#include "webrtc/modules/video_coding/include/video_error_codes.h"
Peter Boström4d71ede2015-05-19 23:09:35 +020015
16namespace webrtc {
17
noahricb1ce6632015-10-21 23:54:51 -070018const int kWidth = 320;
19const int kHeight = 240;
Peter Boström4d71ede2015-05-19 23:09:35 +020020const size_t kMaxPayloadSize = 800;
21
22class VideoEncoderSoftwareFallbackWrapperTest : public ::testing::Test {
23 protected:
24 VideoEncoderSoftwareFallbackWrapperTest()
25 : fallback_wrapper_(kVideoCodecVP8, &fake_encoder_) {}
26
27 class CountingFakeEncoder : public VideoEncoder {
28 public:
29 int32_t InitEncode(const VideoCodec* codec_settings,
30 int32_t number_of_cores,
31 size_t max_payload_size) override {
32 ++init_encode_count_;
33 return init_encode_return_code_;
34 }
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -070035 int32_t Encode(const VideoFrame& frame,
Peter Boström4d71ede2015-05-19 23:09:35 +020036 const CodecSpecificInfo* codec_specific_info,
pbos22993e12015-10-19 02:39:06 -070037 const std::vector<FrameType>* frame_types) override {
Peter Boström4d71ede2015-05-19 23:09:35 +020038 ++encode_count_;
noahricb1ce6632015-10-21 23:54:51 -070039 return encode_return_code_;
Peter Boström4d71ede2015-05-19 23:09:35 +020040 }
41
42 int32_t RegisterEncodeCompleteCallback(
43 EncodedImageCallback* callback) override {
44 encode_complete_callback_ = callback;
45 return WEBRTC_VIDEO_CODEC_OK;
46 }
47
48 int32_t Release() override {
49 ++release_count_;
50 return WEBRTC_VIDEO_CODEC_OK;
51 }
52
53 int32_t SetChannelParameters(uint32_t packet_loss, int64_t rtt) override {
54 ++set_channel_parameters_count_;
55 return WEBRTC_VIDEO_CODEC_OK;
56 }
57
58 int32_t SetRates(uint32_t bitrate, uint32_t framerate) override {
59 ++set_rates_count_;
60 return WEBRTC_VIDEO_CODEC_OK;
61 }
62
63 void OnDroppedFrame() override { ++on_dropped_frame_count_; }
64
Peter Boströmeb66e802015-06-05 11:08:03 +020065 bool SupportsNativeHandle() const override {
66 ++supports_native_handle_count_;
67 return false;
68 }
69
Peter Boströmb7d9a972015-12-18 16:01:11 +010070 const char* ImplementationName() const override {
71 return "fake-encoder";
72 }
73
Peter Boström4d71ede2015-05-19 23:09:35 +020074 int init_encode_count_ = 0;
75 int32_t init_encode_return_code_ = WEBRTC_VIDEO_CODEC_OK;
noahricb1ce6632015-10-21 23:54:51 -070076 int32_t encode_return_code_ = WEBRTC_VIDEO_CODEC_OK;
Peter Boström4d71ede2015-05-19 23:09:35 +020077 int encode_count_ = 0;
78 EncodedImageCallback* encode_complete_callback_ = nullptr;
79 int release_count_ = 0;
80 int set_channel_parameters_count_ = 0;
81 int set_rates_count_ = 0;
82 int on_dropped_frame_count_ = 0;
Peter Boströmeb66e802015-06-05 11:08:03 +020083 mutable int supports_native_handle_count_ = 0;
Peter Boström4d71ede2015-05-19 23:09:35 +020084 };
85
86 class FakeEncodedImageCallback : public EncodedImageCallback {
87 public:
Sergey Ulanov525df3f2016-08-02 17:46:41 -070088 Result OnEncodedImage(
89 const EncodedImage& encoded_image,
90 const CodecSpecificInfo* codec_specific_info,
91 const RTPFragmentationHeader* fragmentation) override {
92 ++callback_count_;
93 return Result(Result::OK, callback_count_);
Peter Boström4d71ede2015-05-19 23:09:35 +020094 }
95 int callback_count_ = 0;
96 };
97
98 void UtilizeFallbackEncoder();
noahricb1ce6632015-10-21 23:54:51 -070099 void FallbackFromEncodeRequest();
100 void EncodeFrame();
Peter Boström4d71ede2015-05-19 23:09:35 +0200101
102 FakeEncodedImageCallback callback_;
103 CountingFakeEncoder fake_encoder_;
104 VideoEncoderSoftwareFallbackWrapper fallback_wrapper_;
105 VideoCodec codec_ = {};
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -0700106 VideoFrame frame_;
Peter Boström4d71ede2015-05-19 23:09:35 +0200107};
108
noahricb1ce6632015-10-21 23:54:51 -0700109void VideoEncoderSoftwareFallbackWrapperTest::EncodeFrame() {
110 frame_.CreateEmptyFrame(kWidth, kHeight, kWidth, (kWidth + 1) / 2,
111 (kWidth + 1) / 2);
nissec9c142f2016-05-17 04:05:47 -0700112 memset(frame_.video_frame_buffer()->MutableDataY(), 16,
noahricb1ce6632015-10-21 23:54:51 -0700113 frame_.allocated_size(webrtc::kYPlane));
nissec9c142f2016-05-17 04:05:47 -0700114 memset(frame_.video_frame_buffer()->MutableDataU(), 128,
noahricb1ce6632015-10-21 23:54:51 -0700115 frame_.allocated_size(webrtc::kUPlane));
nissec9c142f2016-05-17 04:05:47 -0700116 memset(frame_.video_frame_buffer()->MutableDataV(), 128,
noahricb1ce6632015-10-21 23:54:51 -0700117 frame_.allocated_size(webrtc::kVPlane));
118
Peter Boström49e196a2015-10-23 15:58:18 +0200119 std::vector<FrameType> types(1, kVideoFrameKey);
noahricb1ce6632015-10-21 23:54:51 -0700120 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK,
121 fallback_wrapper_.Encode(frame_, nullptr, &types));
122}
123
Peter Boström4d71ede2015-05-19 23:09:35 +0200124void VideoEncoderSoftwareFallbackWrapperTest::UtilizeFallbackEncoder() {
Peter Boström4d71ede2015-05-19 23:09:35 +0200125 fallback_wrapper_.RegisterEncodeCompleteCallback(&callback_);
126 EXPECT_EQ(&callback_, fake_encoder_.encode_complete_callback_);
127
128 // Register with failing fake encoder. Should succeed with VP8 fallback.
129 codec_.codecType = kVideoCodecVP8;
130 codec_.maxFramerate = 30;
131 codec_.width = kWidth;
132 codec_.height = kHeight;
133 fake_encoder_.init_encode_return_code_ = WEBRTC_VIDEO_CODEC_ERROR;
134 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK,
135 fallback_wrapper_.InitEncode(&codec_, 2, kMaxPayloadSize));
136 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, fallback_wrapper_.SetRates(300, 30));
137
noahricb1ce6632015-10-21 23:54:51 -0700138 int callback_count = callback_.callback_count_;
139 int encode_count = fake_encoder_.encode_count_;
140 EncodeFrame();
141 EXPECT_EQ(encode_count, fake_encoder_.encode_count_);
142 EXPECT_EQ(callback_count + 1, callback_.callback_count_);
143}
Peter Boström4d71ede2015-05-19 23:09:35 +0200144
noahricb1ce6632015-10-21 23:54:51 -0700145void VideoEncoderSoftwareFallbackWrapperTest::FallbackFromEncodeRequest() {
146 fallback_wrapper_.RegisterEncodeCompleteCallback(&callback_);
147 codec_.codecType = kVideoCodecVP8;
148 codec_.maxFramerate = 30;
149 codec_.width = kWidth;
150 codec_.height = kHeight;
151 fallback_wrapper_.InitEncode(&codec_, 2, kMaxPayloadSize);
152 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, fallback_wrapper_.SetRates(300, 30));
153 EXPECT_EQ(1, fake_encoder_.init_encode_count_);
154
155 // Have the non-fallback encoder request a software fallback.
156 fake_encoder_.encode_return_code_ = WEBRTC_VIDEO_CODEC_FALLBACK_SOFTWARE;
157 int callback_count = callback_.callback_count_;
158 int encode_count = fake_encoder_.encode_count_;
159 EncodeFrame();
160 // Single encode request, which returned failure.
161 EXPECT_EQ(encode_count + 1, fake_encoder_.encode_count_);
162 EXPECT_EQ(callback_count + 1, callback_.callback_count_);
Peter Boström4d71ede2015-05-19 23:09:35 +0200163}
164
165TEST_F(VideoEncoderSoftwareFallbackWrapperTest, InitializesEncoder) {
166 VideoCodec codec = {};
167 fallback_wrapper_.InitEncode(&codec, 2, kMaxPayloadSize);
168 EXPECT_EQ(1, fake_encoder_.init_encode_count_);
169}
170
noahricb1ce6632015-10-21 23:54:51 -0700171TEST_F(VideoEncoderSoftwareFallbackWrapperTest, EncodeRequestsFallback) {
172 FallbackFromEncodeRequest();
173 // After fallback, further encodes shouldn't hit the fake encoder.
174 int encode_count = fake_encoder_.encode_count_;
175 EncodeFrame();
176 EXPECT_EQ(encode_count, fake_encoder_.encode_count_);
177}
178
Peter Boström4d71ede2015-05-19 23:09:35 +0200179TEST_F(VideoEncoderSoftwareFallbackWrapperTest, CanUtilizeFallbackEncoder) {
180 UtilizeFallbackEncoder();
181 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, fallback_wrapper_.Release());
182}
183
184TEST_F(VideoEncoderSoftwareFallbackWrapperTest,
noahricb1ce6632015-10-21 23:54:51 -0700185 InternalEncoderReleasedDuringFallback) {
Peter Boström4d71ede2015-05-19 23:09:35 +0200186 EXPECT_EQ(0, fake_encoder_.release_count_);
noahricb1ce6632015-10-21 23:54:51 -0700187 UtilizeFallbackEncoder();
188 EXPECT_EQ(1, fake_encoder_.release_count_);
189 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, fallback_wrapper_.Release());
190 // No extra release when the fallback is released.
191 EXPECT_EQ(1, fake_encoder_.release_count_);
Peter Boström4d71ede2015-05-19 23:09:35 +0200192}
193
194TEST_F(VideoEncoderSoftwareFallbackWrapperTest,
195 InternalEncoderNotEncodingDuringFallback) {
196 UtilizeFallbackEncoder();
noahricb1ce6632015-10-21 23:54:51 -0700197 int encode_count = fake_encoder_.encode_count_;
198 EncodeFrame();
199 EXPECT_EQ(encode_count, fake_encoder_.encode_count_);
Peter Boström4d71ede2015-05-19 23:09:35 +0200200
201 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, fallback_wrapper_.Release());
202}
203
204TEST_F(VideoEncoderSoftwareFallbackWrapperTest,
205 CanRegisterCallbackWhileUsingFallbackEncoder) {
206 UtilizeFallbackEncoder();
207 // Registering an encode-complete callback should still work when fallback
208 // encoder is being used.
209 FakeEncodedImageCallback callback2;
210 fallback_wrapper_.RegisterEncodeCompleteCallback(&callback2);
211 EXPECT_EQ(&callback2, fake_encoder_.encode_complete_callback_);
212
213 // Encoding a frame using the fallback should arrive at the new callback.
Peter Boström49e196a2015-10-23 15:58:18 +0200214 std::vector<FrameType> types(1, kVideoFrameKey);
Peter Boström4d71ede2015-05-19 23:09:35 +0200215 frame_.set_timestamp(frame_.timestamp() + 1000);
216 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK,
217 fallback_wrapper_.Encode(frame_, nullptr, &types));
218
219 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, fallback_wrapper_.Release());
220}
221
222TEST_F(VideoEncoderSoftwareFallbackWrapperTest,
223 SetChannelParametersForwardedDuringFallback) {
224 UtilizeFallbackEncoder();
225 EXPECT_EQ(0, fake_encoder_.set_channel_parameters_count_);
226 fallback_wrapper_.SetChannelParameters(1, 1);
227 EXPECT_EQ(1, fake_encoder_.set_channel_parameters_count_);
228 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, fallback_wrapper_.Release());
229}
230
231TEST_F(VideoEncoderSoftwareFallbackWrapperTest,
232 SetRatesForwardedDuringFallback) {
233 UtilizeFallbackEncoder();
234 EXPECT_EQ(1, fake_encoder_.set_rates_count_);
235 fallback_wrapper_.SetRates(1, 1);
236 EXPECT_EQ(2, fake_encoder_.set_rates_count_);
237 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, fallback_wrapper_.Release());
238}
239
240TEST_F(VideoEncoderSoftwareFallbackWrapperTest,
241 OnDroppedFrameForwardedWithoutFallback) {
242 fallback_wrapper_.OnDroppedFrame();
243 EXPECT_EQ(1, fake_encoder_.on_dropped_frame_count_);
244}
245
246TEST_F(VideoEncoderSoftwareFallbackWrapperTest,
247 OnDroppedFrameNotForwardedDuringFallback) {
248 UtilizeFallbackEncoder();
249 fallback_wrapper_.OnDroppedFrame();
250 EXPECT_EQ(0, fake_encoder_.on_dropped_frame_count_);
251 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, fallback_wrapper_.Release());
252}
253
Peter Boströmeb66e802015-06-05 11:08:03 +0200254TEST_F(VideoEncoderSoftwareFallbackWrapperTest,
255 SupportsNativeHandleForwardedWithoutFallback) {
256 fallback_wrapper_.SupportsNativeHandle();
257 EXPECT_EQ(1, fake_encoder_.supports_native_handle_count_);
258}
259
260TEST_F(VideoEncoderSoftwareFallbackWrapperTest,
261 SupportsNativeHandleNotForwardedDuringFallback) {
262 UtilizeFallbackEncoder();
263 fallback_wrapper_.SupportsNativeHandle();
264 EXPECT_EQ(0, fake_encoder_.supports_native_handle_count_);
265 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, fallback_wrapper_.Release());
266}
267
Peter Boströmb7d9a972015-12-18 16:01:11 +0100268TEST_F(VideoEncoderSoftwareFallbackWrapperTest,
269 ReportsFallbackImplementationName) {
270 UtilizeFallbackEncoder();
271 // Hard coded expected value since libvpx is the software implementation name
272 // for VP8. Change accordingly if the underlying implementation does.
273 EXPECT_STREQ("libvpx (fallback from: fake-encoder)",
274 fallback_wrapper_.ImplementationName());
275}
276
Peter Boström4d71ede2015-05-19 23:09:35 +0200277} // namespace webrtc