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

Side by Side Diff: media/filters/decrypting_video_decoder_unittest.cc

Issue 10969028: Add video decoding methods in Decryptor and add DecryptingVideoDecoder. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: reorder methods in the unittest Created 8 years, 2 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 | Annotate | Revision Log
« no previous file with comments | « media/filters/decrypting_video_decoder.cc ('k') | media/filters/ffmpeg_video_decoder.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright (c) 2012 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 <string>
6 #include <vector>
7
8 #include "base/bind.h"
9 #include "base/callback_helpers.h"
10 #include "base/message_loop.h"
11 #include "media/base/decoder_buffer.h"
12 #include "media/base/decrypt_config.h"
13 #include "media/base/mock_callback.h"
14 #include "media/base/mock_filters.h"
15 #include "media/base/video_frame.h"
16 #include "media/filters/ffmpeg_decoder_unittest.h"
17 #include "media/filters/decrypting_video_decoder.h"
18 #include "testing/gmock/include/gmock/gmock.h"
19
20 using ::testing::_;
21 using ::testing::Invoke;
22 using ::testing::IsNull;
23 using ::testing::ReturnRef;
24 using ::testing::SaveArg;
25 using ::testing::StrictMock;
26
27 namespace media {
28
29 static const VideoFrame::Format kVideoFormat = VideoFrame::YV12;
30 static const gfx::Size kCodedSize(320, 240);
31 static const gfx::Rect kVisibleRect(320, 240);
32 static const gfx::Size kNaturalSize(320, 240);
33 static const uint8 kFakeKeyId[] = { 0x4b, 0x65, 0x79, 0x20, 0x49, 0x44 };
34 static const uint8 kFakeIv[DecryptConfig::kDecryptionKeySize] = { 0 };
35
36 // Create a fake non-empty encrypted buffer.
37 static scoped_refptr<DecoderBuffer> CreateFakeEncryptedBuffer() {
38 const int buffer_size = 16; // Need a non-empty buffer;
39 scoped_refptr<DecoderBuffer> buffer(new DecoderBuffer(buffer_size));
40 buffer->SetDecryptConfig(scoped_ptr<DecryptConfig>(new DecryptConfig(
41 std::string(reinterpret_cast<const char*>(kFakeKeyId),
42 arraysize(kFakeKeyId)),
43 std::string(reinterpret_cast<const char*>(kFakeIv), arraysize(kFakeIv)),
44 0,
45 std::vector<SubsampleEntry>())));
46 return buffer;
47 }
48
49 ACTION_P(ReturnBuffer, buffer) {
50 arg0.Run(buffer ? DemuxerStream::kOk : DemuxerStream::kAborted, buffer);
51 }
52
53 ACTION(ReturnConfigChanged) {
54 arg0.Run(DemuxerStream::kConfigChanged, scoped_refptr<DecoderBuffer>(NULL));
55 }
56
57 ACTION_P(RunCallback1, param) {
58 arg1.Run(param);
59 }
60
61 ACTION_P2(RunCallback2, param1, param2) {
62 arg1.Run(param1, param2);
63 }
64
65 class DecryptingVideoDecoderTest : public testing::Test {
66 public:
67 DecryptingVideoDecoderTest()
68 : decryptor_(new StrictMock<MockDecryptor>()),
69 decoder_(new StrictMock<DecryptingVideoDecoder>(
70 base::Bind(&Identity<scoped_refptr<base::MessageLoopProxy> >,
71 message_loop_.message_loop_proxy()),
72 decryptor_.get())),
73 demuxer_(new StrictMock<MockDemuxerStream>()),
74 encrypted_buffer_(CreateFakeEncryptedBuffer()),
75 decoded_video_frame_(VideoFrame::CreateBlackFrame(kCodedSize)),
76 null_video_frame_(scoped_refptr<VideoFrame>()),
77 end_of_stream_video_frame_(VideoFrame::CreateEmptyFrame()) {
78 }
79
80 virtual ~DecryptingVideoDecoderTest() {
81 Stop();
82 }
83
84 void InitializeAndExpectStatus(const VideoDecoderConfig& config,
85 PipelineStatus status) {
86 EXPECT_CALL(*demuxer_, video_decoder_config())
87 .WillRepeatedly(ReturnRef(config));
88
89 decoder_->Initialize(demuxer_, NewExpectedStatusCB(status),
90 base::Bind(&MockStatisticsCB::OnStatistics,
91 base::Unretained(&statistics_cb_)));
92 message_loop_.RunAllPending();
93 }
94
95 void Initialize() {
96 EXPECT_CALL(*decryptor_, InitializeVideoDecoder(_, _))
97 .WillOnce(RunCallback1(true));
98
99 config_.Initialize(kCodecVP8, VIDEO_CODEC_PROFILE_UNKNOWN, kVideoFormat,
100 kCodedSize, kVisibleRect, kNaturalSize,
101 NULL, 0, true, true);
102
103 InitializeAndExpectStatus(config_, PIPELINE_OK);
104 }
105
106 void ReadAndExpectFrameReadyWith(
107 VideoDecoder::Status status,
108 const scoped_refptr<VideoFrame>& video_frame) {
109 EXPECT_CALL(*this, FrameReady(status, video_frame));
110
111 decoder_->Read(base::Bind(&DecryptingVideoDecoderTest::FrameReady,
112 base::Unretained(this)));
113 message_loop_.RunAllPending();
114 }
115
116 // Sets up expectations and actions to put DecryptingVideoDecoder in an
117 // active normal decoding state.
118 void EnterNormalDecodingState() {
119 EXPECT_CALL(*demuxer_, Read(_))
120 .WillOnce(ReturnBuffer(encrypted_buffer_))
121 .WillRepeatedly(ReturnBuffer(DecoderBuffer::CreateEOSBuffer()));
122 EXPECT_CALL(*decryptor_, DecryptAndDecodeVideo(_, _))
123 .WillOnce(RunCallback2(Decryptor::kSuccess, decoded_video_frame_))
124 .WillRepeatedly(RunCallback2(Decryptor::kSuccess,
125 end_of_stream_video_frame_));
126 EXPECT_CALL(statistics_cb_, OnStatistics(_));
127
128 ReadAndExpectFrameReadyWith(VideoDecoder::kOk, decoded_video_frame_);
129 }
130
131 // Sets up expectations and actions to put DecryptingVideoDecoder in an end
132 // of stream state. This function must be called after
133 // EnterNormalDecodingState() to work.
134 void EnterEndOfStreamState() {
135 ReadAndExpectFrameReadyWith(VideoDecoder::kOk, end_of_stream_video_frame_);
136 }
137
138 // Make the read callback pending by saving and not firing it.
139 void EnterPendingReadState() {
140 EXPECT_TRUE(pending_demuxer_read_cb_.is_null());
141 EXPECT_CALL(*demuxer_, Read(_))
142 .WillOnce(SaveArg<0>(&pending_demuxer_read_cb_));
143 decoder_->Read(base::Bind(&DecryptingVideoDecoderTest::FrameReady,
144 base::Unretained(this)));
145 message_loop_.RunAllPending();
146 // Make sure the Read() on the decoder triggers a Read() on the demuxer.
147 EXPECT_FALSE(pending_demuxer_read_cb_.is_null());
148 }
149
150 // Make the video decode callback pending by saving and not firing it.
151 void EnterPendingDecryptAndDecodeState() {
152 EXPECT_TRUE(pending_video_decode_cb_.is_null());
153 EXPECT_CALL(*demuxer_, Read(_))
154 .WillRepeatedly(ReturnBuffer(encrypted_buffer_));
155 EXPECT_CALL(*decryptor_, DecryptAndDecodeVideo(encrypted_buffer_, _))
156 .WillOnce(SaveArg<1>(&pending_video_decode_cb_));
157
158 decoder_->Read(base::Bind(&DecryptingVideoDecoderTest::FrameReady,
159 base::Unretained(this)));
160 message_loop_.RunAllPending();
161 // Make sure the Read() on the decoder triggers a DecryptAndDecode() on the
162 // decryptor.
163 EXPECT_FALSE(pending_video_decode_cb_.is_null());
164 }
165
166 void AbortPendingVideoDecodeCB() {
167 if (!pending_video_decode_cb_.is_null()) {
168 base::ResetAndReturn(&pending_video_decode_cb_).Run(
169 Decryptor::kSuccess, scoped_refptr<VideoFrame>(NULL));
170 }
171 }
172
173 void AbortAllPendingCBs() {
174 if (!pending_init_cb_.is_null()) {
175 ASSERT_TRUE(pending_video_decode_cb_.is_null());
176 base::ResetAndReturn(&pending_init_cb_).Run(false);
177 return;
178 }
179
180 AbortPendingVideoDecodeCB();
181 }
182
183 void Reset() {
184 EXPECT_CALL(*decryptor_, CancelDecryptAndDecodeVideo())
185 .WillOnce(Invoke(
186 this, &DecryptingVideoDecoderTest::AbortPendingVideoDecodeCB));
187
188 decoder_->Reset(NewExpectedClosure());
189 message_loop_.RunAllPending();
190 }
191
192 void Stop() {
193 EXPECT_CALL(*decryptor_, StopVideoDecoder())
194 .WillOnce(Invoke(
195 this, &DecryptingVideoDecoderTest::AbortAllPendingCBs));
196
197 decoder_->Stop(NewExpectedClosure());
198 message_loop_.RunAllPending();
199 }
200
201 MOCK_METHOD2(FrameReady, void(VideoDecoder::Status,
202 const scoped_refptr<VideoFrame>&));
203
204 MessageLoop message_loop_;
205 scoped_ptr<StrictMock<MockDecryptor> > decryptor_;
206 scoped_refptr<StrictMock<DecryptingVideoDecoder> > decoder_;
207 scoped_refptr<StrictMock<MockDemuxerStream> > demuxer_;
208 MockStatisticsCB statistics_cb_;
209 VideoDecoderConfig config_;
210
211 DemuxerStream::ReadCB pending_demuxer_read_cb_;
212 Decryptor::DecoderInitCB pending_init_cb_;
213 Decryptor::VideoDecodeCB pending_video_decode_cb_;
214
215 // Constant buffer/frames to be returned by the |demuxer_| and |decryptor_|.
216 scoped_refptr<DecoderBuffer> encrypted_buffer_;
217 scoped_refptr<VideoFrame> decoded_video_frame_;
218 scoped_refptr<VideoFrame> null_video_frame_;
219 scoped_refptr<VideoFrame> end_of_stream_video_frame_;
220
221 private:
222 DISALLOW_COPY_AND_ASSIGN(DecryptingVideoDecoderTest);
223 };
224
225 TEST_F(DecryptingVideoDecoderTest, Initialize_Normal) {
226 Initialize();
227 }
228
229 // Ensure that DecryptingVideoDecoder only accepts encrypted video.
230 TEST_F(DecryptingVideoDecoderTest, Initialize_UnencryptedVideoConfig) {
231 VideoDecoderConfig config(kCodecVP8, VIDEO_CODEC_PROFILE_UNKNOWN,
232 kVideoFormat,
233 kCodedSize, kVisibleRect, kNaturalSize,
234 NULL, 0, false);
235
236 InitializeAndExpectStatus(config, DECODER_ERROR_NOT_SUPPORTED);
237 }
238
239 // Ensure decoder handles invalid video configs without crashing.
240 TEST_F(DecryptingVideoDecoderTest, Initialize_InvalidVideoConfig) {
241 VideoDecoderConfig config(kCodecVP8, VIDEO_CODEC_PROFILE_UNKNOWN,
242 VideoFrame::INVALID,
243 kCodedSize, kVisibleRect, kNaturalSize,
244 NULL, 0, true);
245
246 InitializeAndExpectStatus(config, PIPELINE_ERROR_DECODE);
247 }
248
249 // Ensure decoder handles unsupported video configs without crashing.
250 TEST_F(DecryptingVideoDecoderTest, Initialize_UnsupportedVideoConfig) {
251 EXPECT_CALL(*decryptor_, InitializeVideoDecoder(_, _))
252 .WillOnce(RunCallback1(false));
253
254 VideoDecoderConfig config(kCodecVP8, VIDEO_CODEC_PROFILE_UNKNOWN,
255 kVideoFormat,
256 kCodedSize, kVisibleRect, kNaturalSize,
257 NULL, 0, true);
258
259 InitializeAndExpectStatus(config, DECODER_ERROR_NOT_SUPPORTED);
260 }
261
262 // Test normal decrypt and decode case.
263 TEST_F(DecryptingVideoDecoderTest, DecryptAndDecode_Normal) {
264 Initialize();
265 EnterNormalDecodingState();
266 }
267
268 // Test the case where the decryptor returns error when doing decrypt and
269 // decode.
270 TEST_F(DecryptingVideoDecoderTest, DecryptAndDecode_DecodeError) {
271 Initialize();
272
273 EXPECT_CALL(*demuxer_, Read(_))
274 .WillRepeatedly(ReturnBuffer(encrypted_buffer_));
275 EXPECT_CALL(*decryptor_, DecryptAndDecodeVideo(_, _))
276 .WillRepeatedly(RunCallback2(Decryptor::kError,
277 scoped_refptr<VideoFrame>(NULL)));
278
279 ReadAndExpectFrameReadyWith(VideoDecoder::kDecodeError, null_video_frame_);
280 }
281
282 // Test the case where the decryptor does not have the decryption key to do
283 // decrypt and decode.
284 TEST_F(DecryptingVideoDecoderTest, DecryptAndDecode_NoKey) {
285 Initialize();
286
287 EXPECT_CALL(*demuxer_, Read(_))
288 .WillRepeatedly(ReturnBuffer(encrypted_buffer_));
289 EXPECT_CALL(*decryptor_, DecryptAndDecodeVideo(_, _))
290 .WillRepeatedly(RunCallback2(Decryptor::kNoKey, null_video_frame_));
291
292 ReadAndExpectFrameReadyWith(VideoDecoder::kDecodeError, null_video_frame_);
293 }
294
295 // Test the case where the decryptor returns kNeedMoreData to ask for more
296 // buffers before it can produce a frame.
297 TEST_F(DecryptingVideoDecoderTest, DecryptAndDecode_NeedMoreData) {
298 Initialize();
299
300 EXPECT_CALL(*demuxer_, Read(_))
301 .Times(2)
302 .WillRepeatedly(ReturnBuffer(encrypted_buffer_));
303 EXPECT_CALL(*decryptor_, DecryptAndDecodeVideo(_, _))
304 .WillOnce(RunCallback2(Decryptor::kNeedMoreData,
305 scoped_refptr<VideoFrame>()))
306 .WillRepeatedly(RunCallback2(Decryptor::kSuccess, decoded_video_frame_));
307 EXPECT_CALL(statistics_cb_, OnStatistics(_))
308 .Times(2);
309
310 ReadAndExpectFrameReadyWith(VideoDecoder::kOk, decoded_video_frame_);
311 }
312
313 // Test the case where the decryptor receives end-of-stream buffer.
314 TEST_F(DecryptingVideoDecoderTest, DecryptAndDecode_EndOfStream) {
315 Initialize();
316 EnterNormalDecodingState();
317 EnterEndOfStreamState();
318 }
319
320 // Test resetting when decoder has initialized but has not decoded any frame.
321 TEST_F(DecryptingVideoDecoderTest, Reset_Initialized) {
322 Initialize();
323 Reset();
324 }
325
326 // Test resetting when decoder has decoded single frame.
327 TEST_F(DecryptingVideoDecoderTest, Reset_Decoding) {
328 Initialize();
329 EnterNormalDecodingState();
330 Reset();
331 }
332
333 // Test resetting when decoder has hit end of stream.
334 TEST_F(DecryptingVideoDecoderTest, Reset_EndOfStream) {
335 Initialize();
336 EnterNormalDecodingState();
337 EnterEndOfStreamState();
338 Reset();
339 }
340
341 // Test resetting after the decoder has been reset.
342 TEST_F(DecryptingVideoDecoderTest, Reset_AfterReset) {
343 Initialize();
344 EnterNormalDecodingState();
345 Reset();
346 Reset();
347 }
348
349 // Test resetting when there is a pending read on the demuxer.
350 TEST_F(DecryptingVideoDecoderTest, Reset_DuringPendingDemuxerRead) {
351 Initialize();
352 EnterPendingReadState();
353
354 EXPECT_CALL(*this, FrameReady(VideoDecoder::kOk, IsNull()));
355
356 Reset();
357 base::ResetAndReturn(&pending_demuxer_read_cb_).Run(DemuxerStream::kOk,
358 encrypted_buffer_);
359 message_loop_.RunAllPending();
360 }
361
362 // Test resetting when there is a pending video decode callback on the
363 // decryptor.
364 TEST_F(DecryptingVideoDecoderTest, Reset_DuringPendingDecryptAndDecode) {
365 Initialize();
366 EnterPendingDecryptAndDecodeState();
367
368 EXPECT_CALL(*this, FrameReady(VideoDecoder::kOk, IsNull()));
369
370 Reset();
371 }
372
373 // Test stopping when decoder has initialized but has not decoded any frame.
374 TEST_F(DecryptingVideoDecoderTest, Stop_Initialized) {
375 Initialize();
376 Stop();
377 }
378
379 // Test stopping when decoder has decoded single frame.
380 TEST_F(DecryptingVideoDecoderTest, Stop_Decoding) {
381 Initialize();
382 EnterNormalDecodingState();
383 Stop();
384 }
385
386 // Test stopping when decoder has hit end of stream.
387 TEST_F(DecryptingVideoDecoderTest, Stop_EndOfStream) {
388 Initialize();
389 EnterNormalDecodingState();
390 EnterEndOfStreamState();
391 Stop();
392 }
393
394 // Test stopping when there is a pending read on the demuxer.
395 TEST_F(DecryptingVideoDecoderTest, Stop_DuringPendingInitialize) {
396 EXPECT_CALL(*decryptor_, InitializeVideoDecoder(_, _))
397 .WillOnce(SaveArg<1>(&pending_init_cb_));
398
399 config_.Initialize(kCodecVP8, VIDEO_CODEC_PROFILE_UNKNOWN, kVideoFormat,
400 kCodedSize, kVisibleRect, kNaturalSize, NULL, 0, true,
401 true);
402 InitializeAndExpectStatus(config_, DECODER_ERROR_NOT_SUPPORTED);
403 EXPECT_FALSE(pending_init_cb_.is_null());
404
405 Stop();
406 }
407
408 // Test stopping when there is a pending read on the demuxer.
409 TEST_F(DecryptingVideoDecoderTest, Stop_DuringPendingDemuxerRead) {
410 Initialize();
411 EnterPendingReadState();
412
413 EXPECT_CALL(*this, FrameReady(VideoDecoder::kOk, IsNull()));
414
415 Stop();
416 base::ResetAndReturn(&pending_demuxer_read_cb_).Run(DemuxerStream::kOk,
417 encrypted_buffer_);
418 message_loop_.RunAllPending();
419 }
420
421 // Test stopping when there is a pending video decode callback on the
422 // decryptor.
423 TEST_F(DecryptingVideoDecoderTest, Stop_DuringPendingDecryptAndDecode) {
424 Initialize();
425 EnterPendingDecryptAndDecodeState();
426
427 EXPECT_CALL(*this, FrameReady(VideoDecoder::kOk, IsNull()));
428
429 Stop();
430 }
431
432 // Test stopping when there is a pending reset on the decoder.
433 // Reset is pending because it cannot complete when the video decode callback
434 // is pending.
435 TEST_F(DecryptingVideoDecoderTest, Stop_DuringPendingReset) {
436 Initialize();
437 EnterPendingDecryptAndDecodeState();
438
439 EXPECT_CALL(*decryptor_, CancelDecryptAndDecodeVideo());
440 EXPECT_CALL(*this, FrameReady(VideoDecoder::kOk, IsNull()));
441
442 decoder_->Reset(NewExpectedClosure());
443 Stop();
444 }
445
446 // Test stopping after the decoder has been reset.
447 TEST_F(DecryptingVideoDecoderTest, Stop_AfterReset) {
448 Initialize();
449 EnterNormalDecodingState();
450 Reset();
451 Stop();
452 }
453
454 // Test stopping after the decoder has been stopped.
455 TEST_F(DecryptingVideoDecoderTest, Stop_AfterStop) {
456 Initialize();
457 EnterNormalDecodingState();
458 Stop();
459 Stop();
460 }
461
462 // Test aborted read on the demuxer stream.
463 TEST_F(DecryptingVideoDecoderTest, AbortPendingDemuxerRead) {
464 Initialize();
465
466 // ReturnBuffer() with NULL triggers aborted demuxer read.
467 EXPECT_CALL(*demuxer_, Read(_))
468 .WillOnce(ReturnBuffer(scoped_refptr<DecoderBuffer>()));
469
470 ReadAndExpectFrameReadyWith(VideoDecoder::kOk, null_video_frame_);
471 }
472
473 // Test aborted read on the demuxer stream when the decoder is being reset.
474 TEST_F(DecryptingVideoDecoderTest, AbortPendingDemuxerReadDuringReset) {
475 Initialize();
476 EnterPendingReadState();
477
478 // Make sure we get a NULL video frame returned.
479 EXPECT_CALL(*this, FrameReady(VideoDecoder::kOk, IsNull()));
480
481 Reset();
482 base::ResetAndReturn(&pending_demuxer_read_cb_).Run(DemuxerStream::kAborted,
483 NULL);
484 message_loop_.RunAllPending();
485 }
486
487 // Test config change on the demuxer stream.
488 TEST_F(DecryptingVideoDecoderTest, ConfigChanged) {
489 Initialize();
490
491 EXPECT_CALL(*demuxer_, Read(_))
492 .WillOnce(ReturnConfigChanged());
493
494 // TODO(xhwang): Update this test when kConfigChanged is supported in
495 // DecryptingVideoDecoder.
496 ReadAndExpectFrameReadyWith(VideoDecoder::kDecodeError, null_video_frame_);
497 }
498
499 } // namespace media
OLDNEW
« no previous file with comments | « media/filters/decrypting_video_decoder.cc ('k') | media/filters/ffmpeg_video_decoder.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698