blob: f84835620bf51eb94bc9e98f04fc8ac9d6372f04 [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"
14#include "webrtc/modules/video_coding/codecs/interface/video_error_codes.h"
15
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öm4d71ede2015-05-19 23:09:35 +020070 int init_encode_count_ = 0;
71 int32_t init_encode_return_code_ = WEBRTC_VIDEO_CODEC_OK;
noahricb1ce6632015-10-21 23:54:51 -070072 int32_t encode_return_code_ = WEBRTC_VIDEO_CODEC_OK;
Peter Boström4d71ede2015-05-19 23:09:35 +020073 int encode_count_ = 0;
74 EncodedImageCallback* encode_complete_callback_ = nullptr;
75 int release_count_ = 0;
76 int set_channel_parameters_count_ = 0;
77 int set_rates_count_ = 0;
78 int on_dropped_frame_count_ = 0;
Peter Boströmeb66e802015-06-05 11:08:03 +020079 mutable int supports_native_handle_count_ = 0;
Peter Boström4d71ede2015-05-19 23:09:35 +020080 };
81
82 class FakeEncodedImageCallback : public EncodedImageCallback {
83 public:
84 int32_t Encoded(const EncodedImage& encoded_image,
85 const CodecSpecificInfo* codec_specific_info,
86 const RTPFragmentationHeader* fragmentation) override {
87 return ++callback_count_;
88 }
89 int callback_count_ = 0;
90 };
91
92 void UtilizeFallbackEncoder();
noahricb1ce6632015-10-21 23:54:51 -070093 void FallbackFromEncodeRequest();
94 void EncodeFrame();
Peter Boström4d71ede2015-05-19 23:09:35 +020095
96 FakeEncodedImageCallback callback_;
97 CountingFakeEncoder fake_encoder_;
98 VideoEncoderSoftwareFallbackWrapper fallback_wrapper_;
99 VideoCodec codec_ = {};
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -0700100 VideoFrame frame_;
Peter Boström4d71ede2015-05-19 23:09:35 +0200101};
102
noahricb1ce6632015-10-21 23:54:51 -0700103void VideoEncoderSoftwareFallbackWrapperTest::EncodeFrame() {
104 frame_.CreateEmptyFrame(kWidth, kHeight, kWidth, (kWidth + 1) / 2,
105 (kWidth + 1) / 2);
106 memset(frame_.buffer(webrtc::kYPlane), 16,
107 frame_.allocated_size(webrtc::kYPlane));
108 memset(frame_.buffer(webrtc::kUPlane), 128,
109 frame_.allocated_size(webrtc::kUPlane));
110 memset(frame_.buffer(webrtc::kVPlane), 128,
111 frame_.allocated_size(webrtc::kVPlane));
112
113 std::vector<FrameType> types(1, kKeyFrame);
114 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK,
115 fallback_wrapper_.Encode(frame_, nullptr, &types));
116}
117
Peter Boström4d71ede2015-05-19 23:09:35 +0200118void VideoEncoderSoftwareFallbackWrapperTest::UtilizeFallbackEncoder() {
Peter Boström4d71ede2015-05-19 23:09:35 +0200119 fallback_wrapper_.RegisterEncodeCompleteCallback(&callback_);
120 EXPECT_EQ(&callback_, fake_encoder_.encode_complete_callback_);
121
122 // Register with failing fake encoder. Should succeed with VP8 fallback.
123 codec_.codecType = kVideoCodecVP8;
124 codec_.maxFramerate = 30;
125 codec_.width = kWidth;
126 codec_.height = kHeight;
127 fake_encoder_.init_encode_return_code_ = WEBRTC_VIDEO_CODEC_ERROR;
128 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK,
129 fallback_wrapper_.InitEncode(&codec_, 2, kMaxPayloadSize));
130 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, fallback_wrapper_.SetRates(300, 30));
131
noahricb1ce6632015-10-21 23:54:51 -0700132 int callback_count = callback_.callback_count_;
133 int encode_count = fake_encoder_.encode_count_;
134 EncodeFrame();
135 EXPECT_EQ(encode_count, fake_encoder_.encode_count_);
136 EXPECT_EQ(callback_count + 1, callback_.callback_count_);
137}
Peter Boström4d71ede2015-05-19 23:09:35 +0200138
noahricb1ce6632015-10-21 23:54:51 -0700139void VideoEncoderSoftwareFallbackWrapperTest::FallbackFromEncodeRequest() {
140 fallback_wrapper_.RegisterEncodeCompleteCallback(&callback_);
141 codec_.codecType = kVideoCodecVP8;
142 codec_.maxFramerate = 30;
143 codec_.width = kWidth;
144 codec_.height = kHeight;
145 fallback_wrapper_.InitEncode(&codec_, 2, kMaxPayloadSize);
146 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, fallback_wrapper_.SetRates(300, 30));
147 EXPECT_EQ(1, fake_encoder_.init_encode_count_);
148
149 // Have the non-fallback encoder request a software fallback.
150 fake_encoder_.encode_return_code_ = WEBRTC_VIDEO_CODEC_FALLBACK_SOFTWARE;
151 int callback_count = callback_.callback_count_;
152 int encode_count = fake_encoder_.encode_count_;
153 EncodeFrame();
154 // Single encode request, which returned failure.
155 EXPECT_EQ(encode_count + 1, fake_encoder_.encode_count_);
156 EXPECT_EQ(callback_count + 1, callback_.callback_count_);
Peter Boström4d71ede2015-05-19 23:09:35 +0200157}
158
159TEST_F(VideoEncoderSoftwareFallbackWrapperTest, InitializesEncoder) {
160 VideoCodec codec = {};
161 fallback_wrapper_.InitEncode(&codec, 2, kMaxPayloadSize);
162 EXPECT_EQ(1, fake_encoder_.init_encode_count_);
163}
164
noahricb1ce6632015-10-21 23:54:51 -0700165TEST_F(VideoEncoderSoftwareFallbackWrapperTest, EncodeRequestsFallback) {
166 FallbackFromEncodeRequest();
167 // After fallback, further encodes shouldn't hit the fake encoder.
168 int encode_count = fake_encoder_.encode_count_;
169 EncodeFrame();
170 EXPECT_EQ(encode_count, fake_encoder_.encode_count_);
171}
172
Peter Boström4d71ede2015-05-19 23:09:35 +0200173TEST_F(VideoEncoderSoftwareFallbackWrapperTest, CanUtilizeFallbackEncoder) {
174 UtilizeFallbackEncoder();
175 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, fallback_wrapper_.Release());
176}
177
178TEST_F(VideoEncoderSoftwareFallbackWrapperTest,
noahricb1ce6632015-10-21 23:54:51 -0700179 InternalEncoderReleasedDuringFallback) {
Peter Boström4d71ede2015-05-19 23:09:35 +0200180 EXPECT_EQ(0, fake_encoder_.release_count_);
noahricb1ce6632015-10-21 23:54:51 -0700181 UtilizeFallbackEncoder();
182 EXPECT_EQ(1, fake_encoder_.release_count_);
183 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, fallback_wrapper_.Release());
184 // No extra release when the fallback is released.
185 EXPECT_EQ(1, fake_encoder_.release_count_);
Peter Boström4d71ede2015-05-19 23:09:35 +0200186}
187
188TEST_F(VideoEncoderSoftwareFallbackWrapperTest,
189 InternalEncoderNotEncodingDuringFallback) {
190 UtilizeFallbackEncoder();
noahricb1ce6632015-10-21 23:54:51 -0700191 int encode_count = fake_encoder_.encode_count_;
192 EncodeFrame();
193 EXPECT_EQ(encode_count, fake_encoder_.encode_count_);
Peter Boström4d71ede2015-05-19 23:09:35 +0200194
195 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, fallback_wrapper_.Release());
196}
197
198TEST_F(VideoEncoderSoftwareFallbackWrapperTest,
199 CanRegisterCallbackWhileUsingFallbackEncoder) {
200 UtilizeFallbackEncoder();
201 // Registering an encode-complete callback should still work when fallback
202 // encoder is being used.
203 FakeEncodedImageCallback callback2;
204 fallback_wrapper_.RegisterEncodeCompleteCallback(&callback2);
205 EXPECT_EQ(&callback2, fake_encoder_.encode_complete_callback_);
206
207 // Encoding a frame using the fallback should arrive at the new callback.
pbos22993e12015-10-19 02:39:06 -0700208 std::vector<FrameType> types(1, kKeyFrame);
Peter Boström4d71ede2015-05-19 23:09:35 +0200209 frame_.set_timestamp(frame_.timestamp() + 1000);
210 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK,
211 fallback_wrapper_.Encode(frame_, nullptr, &types));
212
213 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, fallback_wrapper_.Release());
214}
215
216TEST_F(VideoEncoderSoftwareFallbackWrapperTest,
217 SetChannelParametersForwardedDuringFallback) {
218 UtilizeFallbackEncoder();
219 EXPECT_EQ(0, fake_encoder_.set_channel_parameters_count_);
220 fallback_wrapper_.SetChannelParameters(1, 1);
221 EXPECT_EQ(1, fake_encoder_.set_channel_parameters_count_);
222 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, fallback_wrapper_.Release());
223}
224
225TEST_F(VideoEncoderSoftwareFallbackWrapperTest,
226 SetRatesForwardedDuringFallback) {
227 UtilizeFallbackEncoder();
228 EXPECT_EQ(1, fake_encoder_.set_rates_count_);
229 fallback_wrapper_.SetRates(1, 1);
230 EXPECT_EQ(2, fake_encoder_.set_rates_count_);
231 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, fallback_wrapper_.Release());
232}
233
234TEST_F(VideoEncoderSoftwareFallbackWrapperTest,
235 OnDroppedFrameForwardedWithoutFallback) {
236 fallback_wrapper_.OnDroppedFrame();
237 EXPECT_EQ(1, fake_encoder_.on_dropped_frame_count_);
238}
239
240TEST_F(VideoEncoderSoftwareFallbackWrapperTest,
241 OnDroppedFrameNotForwardedDuringFallback) {
242 UtilizeFallbackEncoder();
243 fallback_wrapper_.OnDroppedFrame();
244 EXPECT_EQ(0, fake_encoder_.on_dropped_frame_count_);
245 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, fallback_wrapper_.Release());
246}
247
Peter Boströmeb66e802015-06-05 11:08:03 +0200248TEST_F(VideoEncoderSoftwareFallbackWrapperTest,
249 SupportsNativeHandleForwardedWithoutFallback) {
250 fallback_wrapper_.SupportsNativeHandle();
251 EXPECT_EQ(1, fake_encoder_.supports_native_handle_count_);
252}
253
254TEST_F(VideoEncoderSoftwareFallbackWrapperTest,
255 SupportsNativeHandleNotForwardedDuringFallback) {
256 UtilizeFallbackEncoder();
257 fallback_wrapper_.SupportsNativeHandle();
258 EXPECT_EQ(0, fake_encoder_.supports_native_handle_count_);
259 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, fallback_wrapper_.Release());
260}
261
Peter Boström4d71ede2015-05-19 23:09:35 +0200262} // namespace webrtc