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

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

Issue 11198017: Add DecryptingAudioDecoder. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: rebase 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
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/buffers.h"
12 #include "media/base/data_buffer.h"
13 #include "media/base/decoder_buffer.h"
14 #include "media/base/decrypt_config.h"
15 #include "media/base/mock_callback.h"
16 #include "media/base/mock_filters.h"
17 #include "media/filters/decrypting_audio_decoder.h"
18 #include "media/filters/ffmpeg_decoder_unittest.h"
19 #include "testing/gmock/include/gmock/gmock.h"
20
21 using ::testing::_;
22 using ::testing::AtMost;
23 using ::testing::Invoke;
24 using ::testing::IsNull;
25 using ::testing::ReturnRef;
26 using ::testing::SaveArg;
27 using ::testing::StrictMock;
28
29 namespace media {
30
31 static const int kFakeAudioFrameSize = 16;
32 static const uint8 kFakeKeyId[] = { 0x4b, 0x65, 0x79, 0x20, 0x49, 0x44 };
33 static const uint8 kFakeIv[DecryptConfig::kDecryptionKeySize] = { 0 };
34
35 // Create a fake non-empty encrypted buffer.
36 static scoped_refptr<DecoderBuffer> CreateFakeEncryptedBuffer() {
37 const int buffer_size = 16; // Need a non-empty buffer;
38 scoped_refptr<DecoderBuffer> buffer(new DecoderBuffer(buffer_size));
39 buffer->SetDecryptConfig(scoped_ptr<DecryptConfig>(new DecryptConfig(
40 std::string(reinterpret_cast<const char*>(kFakeKeyId),
41 arraysize(kFakeKeyId)),
42 std::string(reinterpret_cast<const char*>(kFakeIv), arraysize(kFakeIv)),
43 0,
44 std::vector<SubsampleEntry>())));
45 return buffer;
46 }
47
48 // Use anonymous namespace here to prevent the actions to be defined multiple
49 // times across multiple test files. Sadly we can't use static for them.
50 namespace {
51
52 ACTION_P(ReturnBuffer, buffer) {
53 arg0.Run(buffer ? DemuxerStream::kOk : DemuxerStream::kAborted, buffer);
54 }
55
56 ACTION(ReturnConfigChanged) {
57 arg0.Run(DemuxerStream::kConfigChanged, scoped_refptr<DecoderBuffer>(NULL));
58 }
59
60 ACTION_P(RunCallback0, param) {
61 if (!arg0.is_null())
62 arg0.Run(param);
63 }
64
65 ACTION_P(RunCallback1, param) {
66 arg1.Run(param);
67 }
68
69 ACTION_P2(RunCallback2, param1, param2) {
70 arg1.Run(param1, param2);
71 }
72
73 ACTION_P2(ResetAndRunCallback, callback, param) {
74 base::ResetAndReturn(callback).Run(param);
75 }
76
77 MATCHER(IsNullCallback, "") {
78 return (arg.is_null());
79 }
80
81 } // namespace
82
83 class DecryptingAudioDecoderTest : public testing::Test {
84 public:
85 DecryptingAudioDecoderTest()
86 : decoder_(new StrictMock<DecryptingAudioDecoder>(
87 base::Bind(&Identity<scoped_refptr<base::MessageLoopProxy> >,
88 message_loop_.message_loop_proxy()),
89 base::Bind(
90 &DecryptingAudioDecoderTest::RequestDecryptorNotification,
91 base::Unretained(this)))),
92 decryptor_(new StrictMock<MockDecryptor>()),
93 demuxer_(new StrictMock<MockDemuxerStream>()),
94 encrypted_buffer_(CreateFakeEncryptedBuffer()),
95 decoded_frame_(new DataBuffer(kFakeAudioFrameSize)),
96 end_of_stream_frame_(new DataBuffer(0)),
97 decoded_frame_list_(1, decoded_frame_) {
98 }
99
100 void InitializeAndExpectStatus(const AudioDecoderConfig& config,
101 PipelineStatus status) {
102 EXPECT_CALL(*demuxer_, audio_decoder_config())
103 .WillRepeatedly(ReturnRef(config));
104
105 decoder_->Initialize(demuxer_, NewExpectedStatusCB(status),
106 base::Bind(&MockStatisticsCB::OnStatistics,
107 base::Unretained(&statistics_cb_)));
108 message_loop_.RunAllPending();
109 }
110
111 void Initialize() {
112 EXPECT_CALL(*decryptor_, InitializeAudioDecoderMock(_, _, _))
113 .Times(AtMost(1))
114 .WillOnce(DoAll(RunCallback1(true), SaveArg<2>(&key_added_cb_)));
115 EXPECT_CALL(*this, RequestDecryptorNotification(_))
116 .WillOnce(RunCallback0(decryptor_.get()));
117
118 config_.Initialize(kCodecVorbis, 16, CHANNEL_LAYOUT_STEREO, 44100,
119 NULL, 0, true, true);
120
121 InitializeAndExpectStatus(config_, PIPELINE_OK);
122 EXPECT_EQ(16, decoder_->bits_per_channel());
123 EXPECT_EQ(CHANNEL_LAYOUT_STEREO, decoder_->channel_layout());
124 EXPECT_EQ(44100, decoder_->samples_per_second());
125 }
126
127 void ReadAndExpectFrameReadyWith(
128 AudioDecoder::Status status,
129 const scoped_refptr<Buffer>& audio_frame) {
130 if (status != AudioDecoder::kOk)
131 EXPECT_CALL(*this, FrameReady(status, IsNull()));
132 else
133 EXPECT_CALL(*this, FrameReady(status, audio_frame));
134
135 decoder_->Read(base::Bind(&DecryptingAudioDecoderTest::FrameReady,
136 base::Unretained(this)));
137 message_loop_.RunAllPending();
138 }
139
140 // Sets up expectations and actions to put DecryptingAudioDecoder in an
141 // active normal decoding state.
142 void EnterNormalDecodingState() {
143 Decryptor::AudioBuffers end_of_stream_frames_(1, end_of_stream_frame_);
144
145 EXPECT_CALL(*demuxer_, Read(_))
146 .WillOnce(ReturnBuffer(encrypted_buffer_))
147 .WillRepeatedly(ReturnBuffer(DecoderBuffer::CreateEOSBuffer()));
148 EXPECT_CALL(*decryptor_, DecryptAndDecodeAudio(_, _))
149 .WillOnce(RunCallback2(Decryptor::kSuccess,
150 decoded_frame_list_))
151 .WillRepeatedly(RunCallback2(Decryptor::kSuccess,
152 end_of_stream_frames_));
153 EXPECT_CALL(statistics_cb_, OnStatistics(_));
154
155 ReadAndExpectFrameReadyWith(AudioDecoder::kOk, decoded_frame_);
156 }
157
158 // Sets up expectations and actions to put DecryptingAudioDecoder in an end
159 // of stream state. This function must be called after
160 // EnterNormalDecodingState() to work.
161 void EnterEndOfStreamState() {
162 ReadAndExpectFrameReadyWith(AudioDecoder::kOk, end_of_stream_frame_);
163 }
164
165 // Make the read callback pending by saving and not firing it.
166 void EnterPendingReadState() {
167 EXPECT_TRUE(pending_demuxer_read_cb_.is_null());
168 EXPECT_CALL(*demuxer_, Read(_))
169 .WillOnce(SaveArg<0>(&pending_demuxer_read_cb_));
170 decoder_->Read(base::Bind(&DecryptingAudioDecoderTest::FrameReady,
171 base::Unretained(this)));
172 message_loop_.RunAllPending();
173 // Make sure the Read() on the decoder triggers a Read() on the demuxer.
174 EXPECT_FALSE(pending_demuxer_read_cb_.is_null());
175 }
176
177 // Make the audio decode callback pending by saving and not firing it.
178 void EnterPendingDecodeState() {
179 EXPECT_TRUE(pending_audio_decode_cb_.is_null());
180 EXPECT_CALL(*demuxer_, Read(_))
181 .WillRepeatedly(ReturnBuffer(encrypted_buffer_));
182 EXPECT_CALL(*decryptor_, DecryptAndDecodeAudio(encrypted_buffer_, _))
183 .WillOnce(SaveArg<1>(&pending_audio_decode_cb_));
184
185 decoder_->Read(base::Bind(&DecryptingAudioDecoderTest::FrameReady,
186 base::Unretained(this)));
187 message_loop_.RunAllPending();
188 // Make sure the Read() on the decoder triggers a DecryptAndDecode() on the
189 // decryptor.
190 EXPECT_FALSE(pending_audio_decode_cb_.is_null());
191 }
192
193 void EnterWaitingForKeyState() {
194 EXPECT_CALL(*demuxer_, Read(_))
195 .WillRepeatedly(ReturnBuffer(encrypted_buffer_));
196 EXPECT_CALL(*decryptor_, DecryptAndDecodeAudio(_, _))
197 .WillRepeatedly(RunCallback2(Decryptor::kNoKey,
198 Decryptor::AudioBuffers()));
199 decoder_->Read(base::Bind(&DecryptingAudioDecoderTest::FrameReady,
200 base::Unretained(this)));
201 message_loop_.RunAllPending();
202 }
203
204 void AbortPendingAudioDecodeCB() {
205 if (!pending_audio_decode_cb_.is_null()) {
206 base::ResetAndReturn(&pending_audio_decode_cb_).Run(
207 Decryptor::kSuccess, Decryptor::AudioBuffers());
208 }
209 }
210
211 void Reset() {
212 EXPECT_CALL(*decryptor_, ResetDecoder(Decryptor::kAudio))
213 .WillRepeatedly(InvokeWithoutArgs(
214 this, &DecryptingAudioDecoderTest::AbortPendingAudioDecodeCB));
215
216 decoder_->Reset(NewExpectedClosure());
217 message_loop_.RunAllPending();
218 }
219
220 MOCK_METHOD1(RequestDecryptorNotification,
221 void(const DecryptingAudioDecoder::DecryptorNotificationCB&));
222
223 MOCK_METHOD2(FrameReady, void(AudioDecoder::Status,
224 const scoped_refptr<Buffer>&));
225
226 MessageLoop message_loop_;
227 scoped_refptr<StrictMock<DecryptingAudioDecoder> > decoder_;
228 scoped_ptr<StrictMock<MockDecryptor> > decryptor_;
229 scoped_refptr<StrictMock<MockDemuxerStream> > demuxer_;
230 MockStatisticsCB statistics_cb_;
231 AudioDecoderConfig config_;
232
233 DemuxerStream::ReadCB pending_demuxer_read_cb_;
234 Decryptor::DecoderInitCB pending_init_cb_;
235 Decryptor::KeyAddedCB key_added_cb_;
236 Decryptor::AudioDecodeCB pending_audio_decode_cb_;
237
238 // Constant buffer/frames to be returned by the |demuxer_| and |decryptor_|.
239 scoped_refptr<DecoderBuffer> encrypted_buffer_;
240 scoped_refptr<Buffer> decoded_frame_;
241 scoped_refptr<Buffer> end_of_stream_frame_;
242 Decryptor::AudioBuffers decoded_frame_list_;
243
244 private:
245 DISALLOW_COPY_AND_ASSIGN(DecryptingAudioDecoderTest);
246 };
247
248 TEST_F(DecryptingAudioDecoderTest, Initialize_Normal) {
249 Initialize();
250 }
251
252 // Ensure that DecryptingAudioDecoder only accepts encrypted audio.
253 TEST_F(DecryptingAudioDecoderTest, Initialize_UnencryptedAudioConfig) {
254 AudioDecoderConfig config(kCodecVorbis, 16, CHANNEL_LAYOUT_STEREO, 44100,
255 NULL, 0, false);
256
257 InitializeAndExpectStatus(config, DECODER_ERROR_NOT_SUPPORTED);
258 }
259
260 // Ensure decoder handles invalid audio configs without crashing.
261 TEST_F(DecryptingAudioDecoderTest, Initialize_InvalidAudioConfig) {
262 AudioDecoderConfig config(kUnknownAudioCodec, 0, CHANNEL_LAYOUT_STEREO, 0,
263 NULL, 0, true);
264
265 InitializeAndExpectStatus(config, PIPELINE_ERROR_DECODE);
266 }
267
268 // Ensure decoder handles unsupported audio configs without crashing.
269 TEST_F(DecryptingAudioDecoderTest, Initialize_UnsupportedAudioConfig) {
270 EXPECT_CALL(*decryptor_, InitializeAudioDecoderMock(_, _, _))
271 .WillOnce(RunCallback1(false));
272 EXPECT_CALL(*this, RequestDecryptorNotification(_))
273 .WillOnce(RunCallback0(decryptor_.get()));
274
275 AudioDecoderConfig config(kCodecVorbis, 16, CHANNEL_LAYOUT_STEREO, 44100,
276 NULL, 0, true);
277 InitializeAndExpectStatus(config, DECODER_ERROR_NOT_SUPPORTED);
278 }
279
280 // Test normal decrypt and decode case.
281 TEST_F(DecryptingAudioDecoderTest, DecryptAndDecode_Normal) {
282 Initialize();
283 EnterNormalDecodingState();
284 }
285
286 // Test the case where the decryptor returns error when doing decrypt and
287 // decode.
288 TEST_F(DecryptingAudioDecoderTest, DecryptAndDecode_DecodeError) {
289 Initialize();
290
291 EXPECT_CALL(*demuxer_, Read(_))
292 .WillRepeatedly(ReturnBuffer(encrypted_buffer_));
293 EXPECT_CALL(*decryptor_, DecryptAndDecodeAudio(_, _))
294 .WillRepeatedly(RunCallback2(Decryptor::kError,
295 Decryptor::AudioBuffers()));
296
297 ReadAndExpectFrameReadyWith(AudioDecoder::kDecodeError, NULL);
298 }
299
300 // Test the case where the decryptor returns kNeedMoreData to ask for more
301 // buffers before it can produce a frame.
302 TEST_F(DecryptingAudioDecoderTest, DecryptAndDecode_NeedMoreData) {
303 Initialize();
304
305 EXPECT_CALL(*demuxer_, Read(_))
306 .Times(2)
307 .WillRepeatedly(ReturnBuffer(encrypted_buffer_));
308 EXPECT_CALL(*decryptor_, DecryptAndDecodeAudio(_, _))
309 .WillOnce(RunCallback2(Decryptor::kNeedMoreData,
310 Decryptor::AudioBuffers()))
311 .WillRepeatedly(RunCallback2(Decryptor::kSuccess, decoded_frame_list_));
312 EXPECT_CALL(statistics_cb_, OnStatistics(_))
313 .Times(2);
314
315 ReadAndExpectFrameReadyWith(AudioDecoder::kOk, decoded_frame_);
316 }
317
318 // Test the case where the decryptor returns multiple decoded frames.
319 TEST_F(DecryptingAudioDecoderTest, DecryptAndDecode_MultipleFrames) {
320 Initialize();
321
322 scoped_refptr<Buffer> decoded_frame_a(new DataBuffer(kFakeAudioFrameSize));
323 scoped_refptr<Buffer> decoded_frame_b(new DataBuffer(kFakeAudioFrameSize));
324 decoded_frame_list_.push_back(decoded_frame_a);
325 decoded_frame_list_.push_back(decoded_frame_b);
326
327 EXPECT_CALL(*demuxer_, Read(_))
328 .WillOnce(ReturnBuffer(encrypted_buffer_));
329 EXPECT_CALL(*decryptor_, DecryptAndDecodeAudio(_, _))
330 .WillOnce(RunCallback2(Decryptor::kSuccess, decoded_frame_list_));
331 EXPECT_CALL(statistics_cb_, OnStatistics(_));
332
333 ReadAndExpectFrameReadyWith(AudioDecoder::kOk, decoded_frame_);
334 ReadAndExpectFrameReadyWith(AudioDecoder::kOk, decoded_frame_a);
335 ReadAndExpectFrameReadyWith(AudioDecoder::kOk, decoded_frame_b);
336 }
337
338 // Test the case where the decryptor receives end-of-stream buffer.
339 TEST_F(DecryptingAudioDecoderTest, DecryptAndDecode_EndOfStream) {
340 Initialize();
341 EnterNormalDecodingState();
342 EnterEndOfStreamState();
343 }
344
345 // Test the case where the decryptor returns multiple decoded frames, the last
346 // of which is end-of-stream frame.
347 TEST_F(DecryptingAudioDecoderTest, DecryptAndDecode_MultipleFramesWithEos) {
348 Initialize();
349
350 scoped_refptr<Buffer> decoded_frame_a(new DataBuffer(kFakeAudioFrameSize));
351 scoped_refptr<Buffer> decoded_frame_b(new DataBuffer(kFakeAudioFrameSize));
352 Decryptor::AudioBuffers second_decoded_frame_list;
353 second_decoded_frame_list.push_back(decoded_frame_a);
354 second_decoded_frame_list.push_back(decoded_frame_b);
355 second_decoded_frame_list.push_back(end_of_stream_frame_);
356
357 EXPECT_CALL(*demuxer_, Read(_))
358 .WillOnce(ReturnBuffer(encrypted_buffer_))
359 .WillOnce(ReturnBuffer(DecoderBuffer::CreateEOSBuffer()));
360 EXPECT_CALL(*decryptor_, DecryptAndDecodeAudio(_, _))
361 .WillOnce(RunCallback2(Decryptor::kSuccess, decoded_frame_list_))
362 .WillOnce(RunCallback2(Decryptor::kSuccess, second_decoded_frame_list));
363 // Expect only one OnStatistics() here because EOS input buffer doesn't
364 // trigger statistics reporting.
365 EXPECT_CALL(statistics_cb_, OnStatistics(_));
366
367 ReadAndExpectFrameReadyWith(AudioDecoder::kOk, decoded_frame_);
368 ReadAndExpectFrameReadyWith(AudioDecoder::kOk, decoded_frame_a);
369 ReadAndExpectFrameReadyWith(AudioDecoder::kOk, decoded_frame_b);
370 ReadAndExpectFrameReadyWith(AudioDecoder::kOk, end_of_stream_frame_);
371 }
372
373 // Test the case where the a key is added when the decryptor is in
374 // kWaitingForKey state.
375 TEST_F(DecryptingAudioDecoderTest, KeyAdded_DuringWaitingForKey) {
376 Initialize();
377 EnterWaitingForKeyState();
378
379 EXPECT_CALL(*decryptor_, DecryptAndDecodeAudio(_, _))
380 .WillRepeatedly(RunCallback2(Decryptor::kSuccess, decoded_frame_list_));
381 EXPECT_CALL(statistics_cb_, OnStatistics(_));
382 EXPECT_CALL(*this, FrameReady(AudioDecoder::kOk, decoded_frame_));
383 key_added_cb_.Run();
384 message_loop_.RunAllPending();
385 }
386
387 // Test the case where the a key is added when the decryptor is in
388 // kPendingDecode state.
389 TEST_F(DecryptingAudioDecoderTest, KeyAdded_DruingPendingDecode) {
390 Initialize();
391 EnterPendingDecodeState();
392
393 EXPECT_CALL(*decryptor_, DecryptAndDecodeAudio(_, _))
394 .WillRepeatedly(RunCallback2(Decryptor::kSuccess, decoded_frame_list_));
395 EXPECT_CALL(statistics_cb_, OnStatistics(_));
396 EXPECT_CALL(*this, FrameReady(AudioDecoder::kOk, decoded_frame_));
397 // The audio decode callback is returned after the correct decryption key is
398 // added.
399 key_added_cb_.Run();
400 base::ResetAndReturn(&pending_audio_decode_cb_).Run(
401 Decryptor::kNoKey, Decryptor::AudioBuffers());
402 message_loop_.RunAllPending();
403 }
404
405 // Test resetting when the decoder is in kIdle state but has not decoded any
406 // frame.
407 TEST_F(DecryptingAudioDecoderTest, Reset_DuringIdleAfterInitialization) {
408 Initialize();
409 Reset();
410 }
411
412 // Test resetting when the decoder is in kIdle state after it has decoded one
413 // frame.
414 TEST_F(DecryptingAudioDecoderTest, Reset_DuringIdleAfterDecodedOneFrame) {
415 Initialize();
416 EnterNormalDecodingState();
417 Reset();
418 }
419
420 // Test resetting when the decoder is in kPendingDemuxerRead state.
421 TEST_F(DecryptingAudioDecoderTest, Reset_DuringPendingDemuxerRead) {
422 Initialize();
423 EnterPendingReadState();
424
425 EXPECT_CALL(*this, FrameReady(AudioDecoder::kOk, IsNull()));
426
427 Reset();
428 base::ResetAndReturn(&pending_demuxer_read_cb_).Run(DemuxerStream::kOk,
429 encrypted_buffer_);
430 message_loop_.RunAllPending();
431 }
432
433 // Test resetting when the decoder is in kPendingDecode state.
434 TEST_F(DecryptingAudioDecoderTest, Reset_DuringPendingDecode) {
435 Initialize();
436 EnterPendingDecodeState();
437
438 EXPECT_CALL(*this, FrameReady(AudioDecoder::kOk, IsNull()));
439
440 Reset();
441 }
442
443 // Test resetting when the decoder is in kWaitingForKey state.
444 TEST_F(DecryptingAudioDecoderTest, Reset_DuringWaitingForKey) {
445 Initialize();
446 EnterWaitingForKeyState();
447
448 EXPECT_CALL(*this, FrameReady(AudioDecoder::kOk, IsNull()));
449
450 Reset();
451 }
452
453 // Test resetting when the decoder has hit end of stream and is in
454 // kDecodeFinished state.
455 TEST_F(DecryptingAudioDecoderTest, Reset_AfterDecodeFinished) {
456 Initialize();
457 EnterNormalDecodingState();
458 EnterEndOfStreamState();
459 Reset();
460 }
461
462 // Test resetting after the decoder has been reset.
463 TEST_F(DecryptingAudioDecoderTest, Reset_AfterReset) {
464 Initialize();
465 EnterNormalDecodingState();
466 Reset();
467 Reset();
468 }
469
470 // Test aborted read on the demuxer stream.
471 TEST_F(DecryptingAudioDecoderTest, DemuxerRead_Aborted) {
472 Initialize();
473
474 // ReturnBuffer() with NULL triggers aborted demuxer read.
475 EXPECT_CALL(*demuxer_, Read(_))
476 .WillOnce(ReturnBuffer(scoped_refptr<DecoderBuffer>()));
477
478 ReadAndExpectFrameReadyWith(AudioDecoder::kOk, NULL);
479 }
480
481 // Test aborted read on the demuxer stream when the decoder is being reset.
482 TEST_F(DecryptingAudioDecoderTest, DemuxerRead_AbortedDuringReset) {
483 Initialize();
484 EnterPendingReadState();
485
486 // Make sure we get a NULL audio frame returned.
487 EXPECT_CALL(*this, FrameReady(AudioDecoder::kOk, IsNull()));
488
489 Reset();
490 base::ResetAndReturn(&pending_demuxer_read_cb_).Run(DemuxerStream::kAborted,
491 NULL);
492 message_loop_.RunAllPending();
493 }
494
495 // Test config change on the demuxer stream.
496 TEST_F(DecryptingAudioDecoderTest, DemuxerRead_ConfigChanged) {
497 Initialize();
498
499 EXPECT_CALL(*demuxer_, Read(_))
500 .WillOnce(ReturnConfigChanged());
501
502 // TODO(xhwang): Update this test when kConfigChanged is supported in
503 // DecryptingAudioDecoder.
504 ReadAndExpectFrameReadyWith(AudioDecoder::kDecodeError, NULL);
505 }
506
507 } // namespace media
OLDNEW
« no previous file with comments | « media/filters/decrypting_audio_decoder.cc ('k') | media/filters/decrypting_video_decoder_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698