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

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

Powered by Google App Engine
This is Rietveld 408576698