blob: f2c3ea61c46636af85979e7b94945f4aca5e5656 [file] [log] [blame]
Peter Boström6859ada2015-05-19 21:09:351/*
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 Kjellanderfe7633e2015-11-18 21:00:2114#include "webrtc/modules/video_coding/include/video_error_codes.h"
Peter Boström6859ada2015-05-19 21:09:3515
16namespace webrtc {
17
noahric006e3742015-10-22 06:54:5118const int kWidth = 320;
19const int kHeight = 240;
Peter Boström6859ada2015-05-19 21:09:3520const 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-Sanchez3ca60f32015-05-30 00:21:4035 int32_t Encode(const VideoFrame& frame,
Peter Boström6859ada2015-05-19 21:09:3536 const CodecSpecificInfo* codec_specific_info,
pbosb63d8ad2015-10-19 09:39:0637 const std::vector<FrameType>* frame_types) override {
Peter Boström6859ada2015-05-19 21:09:3538 ++encode_count_;
noahric006e3742015-10-22 06:54:5139 return encode_return_code_;
Peter Boström6859ada2015-05-19 21:09:3540 }
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öm020eb8a2015-06-05 09:08:0365 bool SupportsNativeHandle() const override {
66 ++supports_native_handle_count_;
67 return false;
68 }
69
Peter Boström8468abc2015-12-18 15:01:1170 const char* ImplementationName() const override {
71 return "fake-encoder";
72 }
73
Peter Boström6859ada2015-05-19 21:09:3574 int init_encode_count_ = 0;
75 int32_t init_encode_return_code_ = WEBRTC_VIDEO_CODEC_OK;
noahric006e3742015-10-22 06:54:5176 int32_t encode_return_code_ = WEBRTC_VIDEO_CODEC_OK;
Peter Boström6859ada2015-05-19 21:09:3577 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öm020eb8a2015-06-05 09:08:0383 mutable int supports_native_handle_count_ = 0;
Peter Boström6859ada2015-05-19 21:09:3584 };
85
86 class FakeEncodedImageCallback : public EncodedImageCallback {
87 public:
88 int32_t Encoded(const EncodedImage& encoded_image,
89 const CodecSpecificInfo* codec_specific_info,
90 const RTPFragmentationHeader* fragmentation) override {
91 return ++callback_count_;
92 }
93 int callback_count_ = 0;
94 };
95
96 void UtilizeFallbackEncoder();
noahric006e3742015-10-22 06:54:5197 void FallbackFromEncodeRequest();
98 void EncodeFrame();
Peter Boström6859ada2015-05-19 21:09:3599
100 FakeEncodedImageCallback callback_;
101 CountingFakeEncoder fake_encoder_;
102 VideoEncoderSoftwareFallbackWrapper fallback_wrapper_;
103 VideoCodec codec_ = {};
Miguel Casas-Sanchez3ca60f32015-05-30 00:21:40104 VideoFrame frame_;
Peter Boström6859ada2015-05-19 21:09:35105};
106
noahric006e3742015-10-22 06:54:51107void VideoEncoderSoftwareFallbackWrapperTest::EncodeFrame() {
108 frame_.CreateEmptyFrame(kWidth, kHeight, kWidth, (kWidth + 1) / 2,
109 (kWidth + 1) / 2);
nisse671d8052016-05-17 11:05:47110 memset(frame_.video_frame_buffer()->MutableDataY(), 16,
noahric006e3742015-10-22 06:54:51111 frame_.allocated_size(webrtc::kYPlane));
nisse671d8052016-05-17 11:05:47112 memset(frame_.video_frame_buffer()->MutableDataU(), 128,
noahric006e3742015-10-22 06:54:51113 frame_.allocated_size(webrtc::kUPlane));
nisse671d8052016-05-17 11:05:47114 memset(frame_.video_frame_buffer()->MutableDataV(), 128,
noahric006e3742015-10-22 06:54:51115 frame_.allocated_size(webrtc::kVPlane));
116
Peter Boström9511e462015-10-23 13:58:18117 std::vector<FrameType> types(1, kVideoFrameKey);
noahric006e3742015-10-22 06:54:51118 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK,
119 fallback_wrapper_.Encode(frame_, nullptr, &types));
120}
121
Peter Boström6859ada2015-05-19 21:09:35122void VideoEncoderSoftwareFallbackWrapperTest::UtilizeFallbackEncoder() {
Peter Boström6859ada2015-05-19 21:09:35123 fallback_wrapper_.RegisterEncodeCompleteCallback(&callback_);
124 EXPECT_EQ(&callback_, fake_encoder_.encode_complete_callback_);
125
126 // Register with failing fake encoder. Should succeed with VP8 fallback.
127 codec_.codecType = kVideoCodecVP8;
128 codec_.maxFramerate = 30;
129 codec_.width = kWidth;
130 codec_.height = kHeight;
131 fake_encoder_.init_encode_return_code_ = WEBRTC_VIDEO_CODEC_ERROR;
132 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK,
133 fallback_wrapper_.InitEncode(&codec_, 2, kMaxPayloadSize));
134 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, fallback_wrapper_.SetRates(300, 30));
135
noahric006e3742015-10-22 06:54:51136 int callback_count = callback_.callback_count_;
137 int encode_count = fake_encoder_.encode_count_;
138 EncodeFrame();
139 EXPECT_EQ(encode_count, fake_encoder_.encode_count_);
140 EXPECT_EQ(callback_count + 1, callback_.callback_count_);
141}
Peter Boström6859ada2015-05-19 21:09:35142
noahric006e3742015-10-22 06:54:51143void VideoEncoderSoftwareFallbackWrapperTest::FallbackFromEncodeRequest() {
144 fallback_wrapper_.RegisterEncodeCompleteCallback(&callback_);
145 codec_.codecType = kVideoCodecVP8;
146 codec_.maxFramerate = 30;
147 codec_.width = kWidth;
148 codec_.height = kHeight;
149 fallback_wrapper_.InitEncode(&codec_, 2, kMaxPayloadSize);
150 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, fallback_wrapper_.SetRates(300, 30));
151 EXPECT_EQ(1, fake_encoder_.init_encode_count_);
152
153 // Have the non-fallback encoder request a software fallback.
154 fake_encoder_.encode_return_code_ = WEBRTC_VIDEO_CODEC_FALLBACK_SOFTWARE;
155 int callback_count = callback_.callback_count_;
156 int encode_count = fake_encoder_.encode_count_;
157 EncodeFrame();
158 // Single encode request, which returned failure.
159 EXPECT_EQ(encode_count + 1, fake_encoder_.encode_count_);
160 EXPECT_EQ(callback_count + 1, callback_.callback_count_);
Peter Boström6859ada2015-05-19 21:09:35161}
162
163TEST_F(VideoEncoderSoftwareFallbackWrapperTest, InitializesEncoder) {
164 VideoCodec codec = {};
165 fallback_wrapper_.InitEncode(&codec, 2, kMaxPayloadSize);
166 EXPECT_EQ(1, fake_encoder_.init_encode_count_);
167}
168
noahric006e3742015-10-22 06:54:51169TEST_F(VideoEncoderSoftwareFallbackWrapperTest, EncodeRequestsFallback) {
170 FallbackFromEncodeRequest();
171 // After fallback, further encodes shouldn't hit the fake encoder.
172 int encode_count = fake_encoder_.encode_count_;
173 EncodeFrame();
174 EXPECT_EQ(encode_count, fake_encoder_.encode_count_);
175}
176
Peter Boström6859ada2015-05-19 21:09:35177TEST_F(VideoEncoderSoftwareFallbackWrapperTest, CanUtilizeFallbackEncoder) {
178 UtilizeFallbackEncoder();
179 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, fallback_wrapper_.Release());
180}
181
182TEST_F(VideoEncoderSoftwareFallbackWrapperTest,
noahric006e3742015-10-22 06:54:51183 InternalEncoderReleasedDuringFallback) {
Peter Boström6859ada2015-05-19 21:09:35184 EXPECT_EQ(0, fake_encoder_.release_count_);
noahric006e3742015-10-22 06:54:51185 UtilizeFallbackEncoder();
186 EXPECT_EQ(1, fake_encoder_.release_count_);
187 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, fallback_wrapper_.Release());
188 // No extra release when the fallback is released.
189 EXPECT_EQ(1, fake_encoder_.release_count_);
Peter Boström6859ada2015-05-19 21:09:35190}
191
192TEST_F(VideoEncoderSoftwareFallbackWrapperTest,
193 InternalEncoderNotEncodingDuringFallback) {
194 UtilizeFallbackEncoder();
noahric006e3742015-10-22 06:54:51195 int encode_count = fake_encoder_.encode_count_;
196 EncodeFrame();
197 EXPECT_EQ(encode_count, fake_encoder_.encode_count_);
Peter Boström6859ada2015-05-19 21:09:35198
199 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, fallback_wrapper_.Release());
200}
201
202TEST_F(VideoEncoderSoftwareFallbackWrapperTest,
203 CanRegisterCallbackWhileUsingFallbackEncoder) {
204 UtilizeFallbackEncoder();
205 // Registering an encode-complete callback should still work when fallback
206 // encoder is being used.
207 FakeEncodedImageCallback callback2;
208 fallback_wrapper_.RegisterEncodeCompleteCallback(&callback2);
209 EXPECT_EQ(&callback2, fake_encoder_.encode_complete_callback_);
210
211 // Encoding a frame using the fallback should arrive at the new callback.
Peter Boström9511e462015-10-23 13:58:18212 std::vector<FrameType> types(1, kVideoFrameKey);
Peter Boström6859ada2015-05-19 21:09:35213 frame_.set_timestamp(frame_.timestamp() + 1000);
214 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK,
215 fallback_wrapper_.Encode(frame_, nullptr, &types));
216
217 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, fallback_wrapper_.Release());
218}
219
220TEST_F(VideoEncoderSoftwareFallbackWrapperTest,
221 SetChannelParametersForwardedDuringFallback) {
222 UtilizeFallbackEncoder();
223 EXPECT_EQ(0, fake_encoder_.set_channel_parameters_count_);
224 fallback_wrapper_.SetChannelParameters(1, 1);
225 EXPECT_EQ(1, fake_encoder_.set_channel_parameters_count_);
226 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, fallback_wrapper_.Release());
227}
228
229TEST_F(VideoEncoderSoftwareFallbackWrapperTest,
230 SetRatesForwardedDuringFallback) {
231 UtilizeFallbackEncoder();
232 EXPECT_EQ(1, fake_encoder_.set_rates_count_);
233 fallback_wrapper_.SetRates(1, 1);
234 EXPECT_EQ(2, fake_encoder_.set_rates_count_);
235 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, fallback_wrapper_.Release());
236}
237
238TEST_F(VideoEncoderSoftwareFallbackWrapperTest,
239 OnDroppedFrameForwardedWithoutFallback) {
240 fallback_wrapper_.OnDroppedFrame();
241 EXPECT_EQ(1, fake_encoder_.on_dropped_frame_count_);
242}
243
244TEST_F(VideoEncoderSoftwareFallbackWrapperTest,
245 OnDroppedFrameNotForwardedDuringFallback) {
246 UtilizeFallbackEncoder();
247 fallback_wrapper_.OnDroppedFrame();
248 EXPECT_EQ(0, fake_encoder_.on_dropped_frame_count_);
249 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, fallback_wrapper_.Release());
250}
251
Peter Boström020eb8a2015-06-05 09:08:03252TEST_F(VideoEncoderSoftwareFallbackWrapperTest,
253 SupportsNativeHandleForwardedWithoutFallback) {
254 fallback_wrapper_.SupportsNativeHandle();
255 EXPECT_EQ(1, fake_encoder_.supports_native_handle_count_);
256}
257
258TEST_F(VideoEncoderSoftwareFallbackWrapperTest,
259 SupportsNativeHandleNotForwardedDuringFallback) {
260 UtilizeFallbackEncoder();
261 fallback_wrapper_.SupportsNativeHandle();
262 EXPECT_EQ(0, fake_encoder_.supports_native_handle_count_);
263 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, fallback_wrapper_.Release());
264}
265
Peter Boström8468abc2015-12-18 15:01:11266TEST_F(VideoEncoderSoftwareFallbackWrapperTest,
267 ReportsFallbackImplementationName) {
268 UtilizeFallbackEncoder();
269 // Hard coded expected value since libvpx is the software implementation name
270 // for VP8. Change accordingly if the underlying implementation does.
271 EXPECT_STREQ("libvpx (fallback from: fake-encoder)",
272 fallback_wrapper_.ImplementationName());
273}
274
Peter Boström6859ada2015-05-19 21:09:35275} // namespace webrtc