blob: acfc4de23db8aa0223526ea24aea6c6137768955 [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
18const size_t kMaxPayloadSize = 800;
19
20class VideoEncoderSoftwareFallbackWrapperTest : public ::testing::Test {
21 protected:
22 VideoEncoderSoftwareFallbackWrapperTest()
23 : fallback_wrapper_(kVideoCodecVP8, &fake_encoder_) {}
24
25 class CountingFakeEncoder : public VideoEncoder {
26 public:
27 int32_t InitEncode(const VideoCodec* codec_settings,
28 int32_t number_of_cores,
29 size_t max_payload_size) override {
30 ++init_encode_count_;
31 return init_encode_return_code_;
32 }
33 int32_t Encode(const I420VideoFrame& frame,
34 const CodecSpecificInfo* codec_specific_info,
35 const std::vector<VideoFrameType>* frame_types) override {
36 ++encode_count_;
37 return WEBRTC_VIDEO_CODEC_OK;
38 }
39
40 int32_t RegisterEncodeCompleteCallback(
41 EncodedImageCallback* callback) override {
42 encode_complete_callback_ = callback;
43 return WEBRTC_VIDEO_CODEC_OK;
44 }
45
46 int32_t Release() override {
47 ++release_count_;
48 return WEBRTC_VIDEO_CODEC_OK;
49 }
50
51 int32_t SetChannelParameters(uint32_t packet_loss, int64_t rtt) override {
52 ++set_channel_parameters_count_;
53 return WEBRTC_VIDEO_CODEC_OK;
54 }
55
56 int32_t SetRates(uint32_t bitrate, uint32_t framerate) override {
57 ++set_rates_count_;
58 return WEBRTC_VIDEO_CODEC_OK;
59 }
60
61 void OnDroppedFrame() override { ++on_dropped_frame_count_; }
62
63 int init_encode_count_ = 0;
64 int32_t init_encode_return_code_ = WEBRTC_VIDEO_CODEC_OK;
65 int encode_count_ = 0;
66 EncodedImageCallback* encode_complete_callback_ = nullptr;
67 int release_count_ = 0;
68 int set_channel_parameters_count_ = 0;
69 int set_rates_count_ = 0;
70 int on_dropped_frame_count_ = 0;
71 };
72
73 class FakeEncodedImageCallback : public EncodedImageCallback {
74 public:
75 int32_t Encoded(const EncodedImage& encoded_image,
76 const CodecSpecificInfo* codec_specific_info,
77 const RTPFragmentationHeader* fragmentation) override {
78 return ++callback_count_;
79 }
80 int callback_count_ = 0;
81 };
82
83 void UtilizeFallbackEncoder();
84
85 FakeEncodedImageCallback callback_;
86 CountingFakeEncoder fake_encoder_;
87 VideoEncoderSoftwareFallbackWrapper fallback_wrapper_;
88 VideoCodec codec_ = {};
89 I420VideoFrame frame_;
90};
91
92void VideoEncoderSoftwareFallbackWrapperTest::UtilizeFallbackEncoder() {
93 static const int kWidth = 320;
94 static const int kHeight = 240;
95 fallback_wrapper_.RegisterEncodeCompleteCallback(&callback_);
96 EXPECT_EQ(&callback_, fake_encoder_.encode_complete_callback_);
97
98 // Register with failing fake encoder. Should succeed with VP8 fallback.
99 codec_.codecType = kVideoCodecVP8;
100 codec_.maxFramerate = 30;
101 codec_.width = kWidth;
102 codec_.height = kHeight;
103 fake_encoder_.init_encode_return_code_ = WEBRTC_VIDEO_CODEC_ERROR;
104 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK,
105 fallback_wrapper_.InitEncode(&codec_, 2, kMaxPayloadSize));
106 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, fallback_wrapper_.SetRates(300, 30));
107
108 frame_.CreateEmptyFrame(kWidth, kHeight, kWidth, (kWidth + 1) / 2,
109 (kWidth + 1) / 2);
110 memset(frame_.buffer(webrtc::kYPlane), 16,
111 frame_.allocated_size(webrtc::kYPlane));
112 memset(frame_.buffer(webrtc::kUPlane), 128,
113 frame_.allocated_size(webrtc::kUPlane));
114 memset(frame_.buffer(webrtc::kVPlane), 128,
115 frame_.allocated_size(webrtc::kVPlane));
116
117 std::vector<VideoFrameType> types(1, kKeyFrame);
118 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK,
119 fallback_wrapper_.Encode(frame_, nullptr, &types));
120 EXPECT_EQ(0, fake_encoder_.encode_count_);
121 EXPECT_GT(callback_.callback_count_, 0);
122}
123
124TEST_F(VideoEncoderSoftwareFallbackWrapperTest, InitializesEncoder) {
125 VideoCodec codec = {};
126 fallback_wrapper_.InitEncode(&codec, 2, kMaxPayloadSize);
127 EXPECT_EQ(1, fake_encoder_.init_encode_count_);
128}
129
130TEST_F(VideoEncoderSoftwareFallbackWrapperTest, CanUtilizeFallbackEncoder) {
131 UtilizeFallbackEncoder();
132 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, fallback_wrapper_.Release());
133}
134
135TEST_F(VideoEncoderSoftwareFallbackWrapperTest,
136 InternalEncoderNotReleasedDuringFallback) {
137 UtilizeFallbackEncoder();
138 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, fallback_wrapper_.Release());
139 EXPECT_EQ(0, fake_encoder_.release_count_);
140}
141
142TEST_F(VideoEncoderSoftwareFallbackWrapperTest,
143 InternalEncoderNotEncodingDuringFallback) {
144 UtilizeFallbackEncoder();
145 EXPECT_EQ(0, fake_encoder_.encode_count_);
146
147 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, fallback_wrapper_.Release());
148}
149
150TEST_F(VideoEncoderSoftwareFallbackWrapperTest,
151 CanRegisterCallbackWhileUsingFallbackEncoder) {
152 UtilizeFallbackEncoder();
153 // Registering an encode-complete callback should still work when fallback
154 // encoder is being used.
155 FakeEncodedImageCallback callback2;
156 fallback_wrapper_.RegisterEncodeCompleteCallback(&callback2);
157 EXPECT_EQ(&callback2, fake_encoder_.encode_complete_callback_);
158
159 // Encoding a frame using the fallback should arrive at the new callback.
160 std::vector<VideoFrameType> types(1, kKeyFrame);
161 frame_.set_timestamp(frame_.timestamp() + 1000);
162 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK,
163 fallback_wrapper_.Encode(frame_, nullptr, &types));
164
165 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, fallback_wrapper_.Release());
166}
167
168TEST_F(VideoEncoderSoftwareFallbackWrapperTest,
169 SetChannelParametersForwardedDuringFallback) {
170 UtilizeFallbackEncoder();
171 EXPECT_EQ(0, fake_encoder_.set_channel_parameters_count_);
172 fallback_wrapper_.SetChannelParameters(1, 1);
173 EXPECT_EQ(1, fake_encoder_.set_channel_parameters_count_);
174 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, fallback_wrapper_.Release());
175}
176
177TEST_F(VideoEncoderSoftwareFallbackWrapperTest,
178 SetRatesForwardedDuringFallback) {
179 UtilizeFallbackEncoder();
180 EXPECT_EQ(1, fake_encoder_.set_rates_count_);
181 fallback_wrapper_.SetRates(1, 1);
182 EXPECT_EQ(2, fake_encoder_.set_rates_count_);
183 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, fallback_wrapper_.Release());
184}
185
186TEST_F(VideoEncoderSoftwareFallbackWrapperTest,
187 OnDroppedFrameForwardedWithoutFallback) {
188 fallback_wrapper_.OnDroppedFrame();
189 EXPECT_EQ(1, fake_encoder_.on_dropped_frame_count_);
190}
191
192TEST_F(VideoEncoderSoftwareFallbackWrapperTest,
193 OnDroppedFrameNotForwardedDuringFallback) {
194 UtilizeFallbackEncoder();
195 fallback_wrapper_.OnDroppedFrame();
196 EXPECT_EQ(0, fake_encoder_.on_dropped_frame_count_);
197 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, fallback_wrapper_.Release());
198}
199
200} // namespace webrtc