Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(429)

Side by Side Diff: content/renderer/media/rtc_video_decoder_unittest.cc

Issue 2095393002: Add posciak and wuchengli to WebRTC HW decoder and encoder files (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: remove duplicated owners Created 4 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include <stdint.h>
6 #include <string.h>
7
8 #include "base/bind.h"
9 #include "base/location.h"
10 #include "base/single_thread_task_runner.h"
11 #include "base/synchronization/waitable_event.h"
12 #include "base/threading/thread.h"
13 #include "base/threading/thread_task_runner_handle.h"
14 #include "content/renderer/media/rtc_video_decoder.h"
15 #include "media/base/gmock_callback_support.h"
16 #include "media/renderers/mock_gpu_video_accelerator_factories.h"
17 #include "media/video/mock_video_decode_accelerator.h"
18 #include "testing/gtest/include/gtest/gtest.h"
19
20 #if defined(OS_WIN)
21 #include "base/command_line.h"
22 #include "content/public/common/content_switches.h"
23 #endif // defined(OS_WIN)
24
25 using ::testing::_;
26 using ::testing::Invoke;
27 using ::testing::Return;
28 using ::testing::SaveArg;
29 using ::testing::Values;
30 using ::testing::WithArgs;
31
32 namespace content {
33
34 namespace {
35
36 static const int kMinResolutionWidth = 16;
37 static const int kMinResolutionHeight = 16;
38 static const int kMaxResolutionWidth = 1920;
39 static const int kMaxResolutionHeight = 1088;
40
41 } // namespace
42
43 // TODO(wuchengli): add MockSharedMemory so more functions can be tested.
44 class RTCVideoDecoderTest
45 : public ::testing::TestWithParam<webrtc::VideoCodecType>,
46 webrtc::DecodedImageCallback {
47 public:
48 RTCVideoDecoderTest()
49 : mock_gpu_factories_(
50 new media::MockGpuVideoAcceleratorFactories(nullptr)),
51 vda_thread_("vda_thread"),
52 idle_waiter_(base::WaitableEvent::ResetPolicy::AUTOMATIC,
53 base::WaitableEvent::InitialState::NOT_SIGNALED) {
54 memset(&codec_, 0, sizeof(codec_));
55 }
56
57 void SetUp() override {
58 ASSERT_TRUE(vda_thread_.Start());
59 vda_task_runner_ = vda_thread_.task_runner();
60 mock_vda_ = new media::MockVideoDecodeAccelerator;
61
62 media::VideoDecodeAccelerator::SupportedProfile supported_profile;
63 supported_profile.min_resolution.SetSize(kMinResolutionWidth,
64 kMinResolutionHeight);
65 supported_profile.max_resolution.SetSize(kMaxResolutionWidth,
66 kMaxResolutionHeight);
67 supported_profile.profile = media::H264PROFILE_MAIN;
68 capabilities_.supported_profiles.push_back(supported_profile);
69 supported_profile.profile = media::VP8PROFILE_ANY;
70 capabilities_.supported_profiles.push_back(supported_profile);
71
72 EXPECT_CALL(*mock_gpu_factories_.get(), GetTaskRunner())
73 .WillRepeatedly(Return(vda_task_runner_));
74 EXPECT_CALL(*mock_gpu_factories_.get(),
75 GetVideoDecodeAcceleratorCapabilities())
76 .WillRepeatedly(Return(capabilities_));
77 EXPECT_CALL(*mock_gpu_factories_.get(), DoCreateVideoDecodeAccelerator())
78 .WillRepeatedly(Return(mock_vda_));
79 EXPECT_CALL(*mock_vda_, Initialize(_, _))
80 .Times(1)
81 .WillRepeatedly(Return(true));
82 EXPECT_CALL(*mock_vda_, Destroy()).Times(1);
83
84 #if defined(OS_WIN)
85 base::CommandLine::ForCurrentProcess()->AppendSwitch(
86 switches::kEnableWin7WebRtcHWH264Decoding);
87 #endif // defined(OS_WIN)
88 }
89
90 void TearDown() override {
91 DVLOG(2) << "TearDown";
92 EXPECT_TRUE(vda_thread_.IsRunning());
93 RunUntilIdle(); // Wait until all callbascks complete.
94 vda_task_runner_->DeleteSoon(FROM_HERE, rtc_decoder_.release());
95 // Make sure the decoder is released before stopping the thread.
96 RunUntilIdle();
97 vda_thread_.Stop();
98 }
99
100 int32_t Decoded(webrtc::VideoFrame& decoded_image) override {
101 DVLOG(2) << "Decoded";
102 EXPECT_EQ(vda_task_runner_, base::ThreadTaskRunnerHandle::Get());
103 return WEBRTC_VIDEO_CODEC_OK;
104 }
105
106 void CreateDecoder(webrtc::VideoCodecType codec_type) {
107 DVLOG(2) << "CreateDecoder";
108 codec_.codecType = codec_type;
109 rtc_decoder_ =
110 RTCVideoDecoder::Create(codec_type, mock_gpu_factories_.get());
111 }
112
113 void Initialize() {
114 DVLOG(2) << "Initialize";
115 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, rtc_decoder_->InitDecode(&codec_, 1));
116 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK,
117 rtc_decoder_->RegisterDecodeCompleteCallback(this));
118 }
119
120 void NotifyResetDone() {
121 DVLOG(2) << "NotifyResetDone";
122 vda_task_runner_->PostTask(
123 FROM_HERE,
124 base::Bind(&RTCVideoDecoder::NotifyResetDone,
125 base::Unretained(rtc_decoder_.get())));
126 }
127
128 void NotifyError(media::VideoDecodeAccelerator::Error error) {
129 DVLOG(2) << "NotifyError";
130 vda_task_runner_->PostTask(
131 FROM_HERE,
132 base::Bind(&RTCVideoDecoder::NotifyError,
133 base::Unretained(rtc_decoder_.get()), error));
134 }
135
136 void RunUntilIdle() {
137 DVLOG(2) << "RunUntilIdle";
138 vda_task_runner_->PostTask(FROM_HERE,
139 base::Bind(&base::WaitableEvent::Signal,
140 base::Unretained(&idle_waiter_)));
141 idle_waiter_.Wait();
142 }
143
144 void SetUpResetVDA() {
145 mock_vda_after_reset_ = new media::MockVideoDecodeAccelerator;
146 EXPECT_CALL(*mock_gpu_factories_.get(), DoCreateVideoDecodeAccelerator())
147 .WillRepeatedly(Return(mock_vda_after_reset_));
148 EXPECT_CALL(*mock_vda_after_reset_, Initialize(_, _))
149 .Times(1)
150 .WillRepeatedly(Return(true));
151 EXPECT_CALL(*mock_vda_after_reset_, Destroy()).Times(1);
152 }
153
154 protected:
155 std::unique_ptr<media::MockGpuVideoAcceleratorFactories> mock_gpu_factories_;
156 media::MockVideoDecodeAccelerator* mock_vda_;
157 media::MockVideoDecodeAccelerator* mock_vda_after_reset_;
158 std::unique_ptr<RTCVideoDecoder> rtc_decoder_;
159 webrtc::VideoCodec codec_;
160 base::Thread vda_thread_;
161 media::VideoDecodeAccelerator::Capabilities capabilities_;
162
163 private:
164 scoped_refptr<base::SingleThreadTaskRunner> vda_task_runner_;
165
166 base::Lock lock_;
167 base::WaitableEvent idle_waiter_;
168 };
169
170 TEST_F(RTCVideoDecoderTest, CreateReturnsNullOnUnsupportedCodec) {
171 CreateDecoder(webrtc::kVideoCodecVP8);
172 std::unique_ptr<RTCVideoDecoder> null_rtc_decoder(RTCVideoDecoder::Create(
173 webrtc::kVideoCodecI420, mock_gpu_factories_.get()));
174 EXPECT_EQ(NULL, null_rtc_decoder.get());
175 }
176
177 TEST_P(RTCVideoDecoderTest, CreateAndInitSucceeds) {
178 const webrtc::VideoCodecType codec_type = GetParam();
179 CreateDecoder(codec_type);
180 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, rtc_decoder_->InitDecode(&codec_, 1));
181 }
182
183 TEST_F(RTCVideoDecoderTest, InitDecodeReturnsErrorOnFeedbackMode) {
184 CreateDecoder(webrtc::kVideoCodecVP8);
185 codec_.codecSpecific.VP8.feedbackModeOn = true;
186 EXPECT_EQ(WEBRTC_VIDEO_CODEC_ERROR, rtc_decoder_->InitDecode(&codec_, 1));
187 }
188
189 TEST_F(RTCVideoDecoderTest, DecodeReturnsErrorWithoutInitDecode) {
190 CreateDecoder(webrtc::kVideoCodecVP8);
191 webrtc::EncodedImage input_image;
192 EXPECT_EQ(WEBRTC_VIDEO_CODEC_UNINITIALIZED,
193 rtc_decoder_->Decode(input_image, false, nullptr, nullptr, 0));
194 }
195
196 TEST_F(RTCVideoDecoderTest, DecodeReturnsErrorOnIncompleteFrame) {
197 CreateDecoder(webrtc::kVideoCodecVP8);
198 Initialize();
199 webrtc::EncodedImage input_image;
200 input_image._completeFrame = false;
201 EXPECT_EQ(WEBRTC_VIDEO_CODEC_ERROR,
202 rtc_decoder_->Decode(input_image, false, nullptr, nullptr, 0));
203 }
204
205 TEST_F(RTCVideoDecoderTest, DecodeReturnsErrorOnMissingFrames) {
206 CreateDecoder(webrtc::kVideoCodecVP8);
207 Initialize();
208 webrtc::EncodedImage input_image;
209 input_image._completeFrame = true;
210 bool missingFrames = true;
211 EXPECT_EQ(
212 WEBRTC_VIDEO_CODEC_ERROR,
213 rtc_decoder_->Decode(input_image, missingFrames, nullptr, nullptr, 0));
214 }
215
216 TEST_F(RTCVideoDecoderTest, ReleaseReturnsOk) {
217 CreateDecoder(webrtc::kVideoCodecVP8);
218 Initialize();
219 EXPECT_CALL(*mock_vda_, Reset())
220 .WillOnce(Invoke(this, &RTCVideoDecoderTest::NotifyResetDone));
221 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, rtc_decoder_->Release());
222 }
223
224 TEST_F(RTCVideoDecoderTest, InitDecodeAfterRelease) {
225 CreateDecoder(webrtc::kVideoCodecVP8);
226 EXPECT_CALL(*mock_vda_, Reset())
227 .WillRepeatedly(Invoke(this, &RTCVideoDecoderTest::NotifyResetDone));
228 Initialize();
229 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, rtc_decoder_->Release());
230 Initialize();
231 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, rtc_decoder_->Release());
232 }
233
234 TEST_F(RTCVideoDecoderTest, IsBufferAfterReset) {
235 CreateDecoder(webrtc::kVideoCodecVP8);
236 EXPECT_TRUE(rtc_decoder_->IsBufferAfterReset(0, RTCVideoDecoder::ID_INVALID));
237 EXPECT_TRUE(rtc_decoder_->IsBufferAfterReset(RTCVideoDecoder::ID_LAST,
238 RTCVideoDecoder::ID_INVALID));
239 EXPECT_FALSE(rtc_decoder_->IsBufferAfterReset(RTCVideoDecoder::ID_HALF - 2,
240 RTCVideoDecoder::ID_HALF + 2));
241 EXPECT_TRUE(rtc_decoder_->IsBufferAfterReset(RTCVideoDecoder::ID_HALF + 2,
242 RTCVideoDecoder::ID_HALF - 2));
243
244 EXPECT_FALSE(rtc_decoder_->IsBufferAfterReset(0, 0));
245 EXPECT_TRUE(rtc_decoder_->IsBufferAfterReset(0, RTCVideoDecoder::ID_LAST));
246 EXPECT_FALSE(
247 rtc_decoder_->IsBufferAfterReset(0, RTCVideoDecoder::ID_HALF - 2));
248 EXPECT_TRUE(
249 rtc_decoder_->IsBufferAfterReset(0, RTCVideoDecoder::ID_HALF + 2));
250
251 EXPECT_FALSE(rtc_decoder_->IsBufferAfterReset(RTCVideoDecoder::ID_LAST, 0));
252 EXPECT_FALSE(rtc_decoder_->IsBufferAfterReset(RTCVideoDecoder::ID_LAST,
253 RTCVideoDecoder::ID_HALF - 2));
254 EXPECT_TRUE(rtc_decoder_->IsBufferAfterReset(RTCVideoDecoder::ID_LAST,
255 RTCVideoDecoder::ID_HALF + 2));
256 EXPECT_FALSE(rtc_decoder_->IsBufferAfterReset(RTCVideoDecoder::ID_LAST,
257 RTCVideoDecoder::ID_LAST));
258 }
259
260 TEST_F(RTCVideoDecoderTest, IsFirstBufferAfterReset) {
261 CreateDecoder(webrtc::kVideoCodecVP8);
262 EXPECT_TRUE(
263 rtc_decoder_->IsFirstBufferAfterReset(0, RTCVideoDecoder::ID_INVALID));
264 EXPECT_FALSE(
265 rtc_decoder_->IsFirstBufferAfterReset(1, RTCVideoDecoder::ID_INVALID));
266 EXPECT_FALSE(rtc_decoder_->IsFirstBufferAfterReset(0, 0));
267 EXPECT_TRUE(rtc_decoder_->IsFirstBufferAfterReset(1, 0));
268 EXPECT_FALSE(rtc_decoder_->IsFirstBufferAfterReset(2, 0));
269
270 EXPECT_FALSE(rtc_decoder_->IsFirstBufferAfterReset(RTCVideoDecoder::ID_HALF,
271 RTCVideoDecoder::ID_HALF));
272 EXPECT_TRUE(rtc_decoder_->IsFirstBufferAfterReset(
273 RTCVideoDecoder::ID_HALF + 1, RTCVideoDecoder::ID_HALF));
274 EXPECT_FALSE(rtc_decoder_->IsFirstBufferAfterReset(
275 RTCVideoDecoder::ID_HALF + 2, RTCVideoDecoder::ID_HALF));
276
277 EXPECT_FALSE(rtc_decoder_->IsFirstBufferAfterReset(RTCVideoDecoder::ID_LAST,
278 RTCVideoDecoder::ID_LAST));
279 EXPECT_TRUE(
280 rtc_decoder_->IsFirstBufferAfterReset(0, RTCVideoDecoder::ID_LAST));
281 EXPECT_FALSE(
282 rtc_decoder_->IsFirstBufferAfterReset(1, RTCVideoDecoder::ID_LAST));
283 }
284
285
286 TEST_P(RTCVideoDecoderTest, GetVDAErrorCounterForTesting) {
287 const webrtc::VideoCodecType codec_type = GetParam();
288 CreateDecoder(codec_type);
289 Initialize();
290
291 webrtc::EncodedImage input_image;
292 input_image._completeFrame = true;
293 input_image._encodedWidth = kMinResolutionWidth;
294 input_image._encodedHeight = kMaxResolutionHeight;
295 input_image._frameType = webrtc::kVideoFrameDelta;
296 EXPECT_EQ(WEBRTC_VIDEO_CODEC_ERROR,
297 rtc_decoder_->Decode(input_image, false, nullptr, nullptr, 0));
298 RunUntilIdle();
299
300 // Notify the decoder about a platform error.
301 NotifyError(media::VideoDecodeAccelerator::PLATFORM_FAILURE);
302 RunUntilIdle();
303 EXPECT_EQ(1, rtc_decoder_->GetVDAErrorCounterForTesting());
304
305 // Expect decode call to reset decoder, and set up a new VDA to track it.
306 SetUpResetVDA();
307 EXPECT_EQ(WEBRTC_VIDEO_CODEC_ERROR,
308 rtc_decoder_->Decode(input_image, false, nullptr, nullptr, 0));
309 EXPECT_EQ(1, rtc_decoder_->GetVDAErrorCounterForTesting());
310
311 // Decoder expects a keyframe after reset, so drops any other frames.
312 EXPECT_EQ(WEBRTC_VIDEO_CODEC_ERROR,
313 rtc_decoder_->Decode(input_image, false, nullptr, nullptr, 0));
314 EXPECT_EQ(1, rtc_decoder_->GetVDAErrorCounterForTesting());
315
316 // Decoder resets error counter after a successfull decode.
317 input_image._frameType = webrtc::kVideoFrameKey;
318 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK,
319 rtc_decoder_->Decode(input_image, false, nullptr, nullptr, 10));
320 EXPECT_EQ(0, rtc_decoder_->GetVDAErrorCounterForTesting());
321 }
322
323 INSTANTIATE_TEST_CASE_P(CodecProfiles,
324 RTCVideoDecoderTest,
325 Values(webrtc::kVideoCodecVP8,
326 webrtc::kVideoCodecH264));
327
328 } // content
OLDNEW
« no previous file with comments | « content/renderer/media/rtc_video_decoder_factory.cc ('k') | content/renderer/media/rtc_video_encoder.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698