[go: nahoru, domu]

blob: 1aa39e707779e283b3eb445eb6ef5b4e0d7d1db0 [file] [log] [blame]
xhwang@chromium.org97a9ce42012-10-19 10:06:431// 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"
xhwang@chromium.org8b10f2222012-11-13 05:49:4815#include "media/base/gmock_callback_support.h"
xhwang@chromium.org97a9ce42012-10-19 10:06:4316#include "media/base/mock_filters.h"
scherkus@chromium.org1848da02012-12-06 06:58:3817#include "media/base/test_helpers.h"
xhwang@chromium.org97a9ce42012-10-19 10:06:4318#include "media/filters/decrypting_audio_decoder.h"
xhwang@chromium.org97a9ce42012-10-19 10:06:4319#include "testing/gmock/include/gmock/gmock.h"
20
21using ::testing::_;
22using ::testing::AtMost;
xhwang@chromium.org97a9ce42012-10-19 10:06:4323using ::testing::IsNull;
24using ::testing::ReturnRef;
25using ::testing::SaveArg;
26using ::testing::StrictMock;
27
28namespace media {
29
30static const int kFakeAudioFrameSize = 16;
31static const uint8 kFakeKeyId[] = { 0x4b, 0x65, 0x79, 0x20, 0x49, 0x44 };
32static const uint8 kFakeIv[DecryptConfig::kDecryptionKeySize] = { 0 };
33
34// Create a fake non-empty encrypted buffer.
35static scoped_refptr<DecoderBuffer> CreateFakeEncryptedBuffer() {
36 const int buffer_size = 16; // Need a non-empty buffer;
37 scoped_refptr<DecoderBuffer> buffer(new DecoderBuffer(buffer_size));
38 buffer->SetDecryptConfig(scoped_ptr<DecryptConfig>(new DecryptConfig(
39 std::string(reinterpret_cast<const char*>(kFakeKeyId),
40 arraysize(kFakeKeyId)),
41 std::string(reinterpret_cast<const char*>(kFakeIv), arraysize(kFakeIv)),
42 0,
43 std::vector<SubsampleEntry>())));
44 return buffer;
45}
46
47// Use anonymous namespace here to prevent the actions to be defined multiple
48// times across multiple test files. Sadly we can't use static for them.
49namespace {
50
51ACTION_P(ReturnBuffer, buffer) {
52 arg0.Run(buffer ? DemuxerStream::kOk : DemuxerStream::kAborted, buffer);
53}
54
xhwang@chromium.org8b10f2222012-11-13 05:49:4855ACTION_P(RunCallbackIfNotNull, param) {
xhwang@chromium.org97a9ce42012-10-19 10:06:4356 if (!arg0.is_null())
57 arg0.Run(param);
xhwang@chromium.org97a9ce42012-10-19 10:06:4358}
59
60ACTION_P2(ResetAndRunCallback, callback, param) {
61 base::ResetAndReturn(callback).Run(param);
62}
63
xhwang@chromium.org8b10f2222012-11-13 05:49:4864MATCHER(IsEndOfStream, "end of stream") {
xhwang@chromium.org8f5a9a52012-10-23 20:49:2065 return (arg->IsEndOfStream());
66}
67
xhwang@chromium.org97a9ce42012-10-19 10:06:4368} // namespace
69
70class DecryptingAudioDecoderTest : public testing::Test {
71 public:
72 DecryptingAudioDecoderTest()
xhwang@chromium.org2b454ff82012-11-15 03:57:5873 : decoder_(new DecryptingAudioDecoder(
scherkus@chromium.org8c076cb2012-11-28 21:06:1674 message_loop_.message_loop_proxy(),
xhwang@chromium.org97a9ce42012-10-19 10:06:4375 base::Bind(
76 &DecryptingAudioDecoderTest::RequestDecryptorNotification,
77 base::Unretained(this)))),
78 decryptor_(new StrictMock<MockDecryptor>()),
79 demuxer_(new StrictMock<MockDemuxerStream>()),
80 encrypted_buffer_(CreateFakeEncryptedBuffer()),
xhwang@chromium.orgecbb9762012-10-24 22:33:5481 decoded_frame_(NULL),
xhwang@chromium.org97a9ce42012-10-19 10:06:4382 end_of_stream_frame_(new DataBuffer(0)),
xhwang@chromium.orgecbb9762012-10-24 22:33:5483 decoded_frame_list_() {
xhwang@chromium.org2b454ff82012-11-15 03:57:5884 scoped_refptr<DataBuffer> data_buffer = new DataBuffer(kFakeAudioFrameSize);
85 data_buffer->SetDataSize(kFakeAudioFrameSize);
86 // |decoded_frame_| contains random data.
87 decoded_frame_ = data_buffer;
xhwang@chromium.orgecbb9762012-10-24 22:33:5488 decoded_frame_list_.push_back(decoded_frame_);
xhwang@chromium.org97a9ce42012-10-19 10:06:4389 }
90
91 void InitializeAndExpectStatus(const AudioDecoderConfig& config,
92 PipelineStatus status) {
93 EXPECT_CALL(*demuxer_, audio_decoder_config())
94 .WillRepeatedly(ReturnRef(config));
95
96 decoder_->Initialize(demuxer_, NewExpectedStatusCB(status),
97 base::Bind(&MockStatisticsCB::OnStatistics,
98 base::Unretained(&statistics_cb_)));
xhwang@chromium.org643d5442012-11-14 05:08:3299 message_loop_.RunUntilIdle();
xhwang@chromium.org97a9ce42012-10-19 10:06:43100 }
101
102 void Initialize() {
xhwang@chromium.org82d7abd2012-11-02 23:04:03103 EXPECT_CALL(*decryptor_, InitializeAudioDecoderMock(_, _))
xhwang@chromium.org97a9ce42012-10-19 10:06:43104 .Times(AtMost(1))
xhwang@chromium.org8b10f2222012-11-13 05:49:48105 .WillOnce(RunCallback<1>(true));
xhwang@chromium.org97a9ce42012-10-19 10:06:43106 EXPECT_CALL(*this, RequestDecryptorNotification(_))
xhwang@chromium.org8b10f2222012-11-13 05:49:48107 .WillOnce(RunCallbackIfNotNull(decryptor_.get()));
xhwang@chromium.orgabd36b3af2012-12-22 03:42:02108 EXPECT_CALL(*decryptor_, RegisterNewKeyCB(Decryptor::kAudio, _))
xhwang@chromium.org82d7abd2012-11-02 23:04:03109 .WillOnce(SaveArg<1>(&key_added_cb_));
xhwang@chromium.org97a9ce42012-10-19 10:06:43110
xhwang@chromium.org7c39486c2013-01-06 15:36:09111 config_.Initialize(kCodecVorbis, kSampleFormatPlanarF32,
112 CHANNEL_LAYOUT_STEREO, 44100, NULL, 0, true, true);
113 InitializeAndExpectStatus(config_, PIPELINE_OK);
xhwang@chromium.org97a9ce42012-10-19 10:06:43114
xhwang@chromium.org7c39486c2013-01-06 15:36:09115 EXPECT_EQ(config_.bits_per_channel(), decoder_->bits_per_channel());
116 EXPECT_EQ(config_.channel_layout(), decoder_->channel_layout());
117 EXPECT_EQ(config_.samples_per_second(), decoder_->samples_per_second());
xhwang@chromium.org97a9ce42012-10-19 10:06:43118 }
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()));
xhwang@chromium.org8f5a9a52012-10-23 20:49:20125 else if (audio_frame->IsEndOfStream())
126 EXPECT_CALL(*this, FrameReady(status, IsEndOfStream()));
xhwang@chromium.org97a9ce42012-10-19 10:06:43127 else
128 EXPECT_CALL(*this, FrameReady(status, audio_frame));
129
130 decoder_->Read(base::Bind(&DecryptingAudioDecoderTest::FrameReady,
131 base::Unretained(this)));
xhwang@chromium.org643d5442012-11-14 05:08:32132 message_loop_.RunUntilIdle();
xhwang@chromium.org97a9ce42012-10-19 10:06:43133 }
134
135 // Sets up expectations and actions to put DecryptingAudioDecoder in an
136 // active normal decoding state.
137 void EnterNormalDecodingState() {
138 Decryptor::AudioBuffers end_of_stream_frames_(1, end_of_stream_frame_);
139
140 EXPECT_CALL(*demuxer_, Read(_))
141 .WillOnce(ReturnBuffer(encrypted_buffer_))
142 .WillRepeatedly(ReturnBuffer(DecoderBuffer::CreateEOSBuffer()));
143 EXPECT_CALL(*decryptor_, DecryptAndDecodeAudio(_, _))
xhwang@chromium.org8b10f2222012-11-13 05:49:48144 .WillOnce(RunCallback<1>(Decryptor::kSuccess, decoded_frame_list_))
145 .WillRepeatedly(RunCallback<1>(Decryptor::kNeedMoreData,
146 Decryptor::AudioBuffers()));
xhwang@chromium.org97a9ce42012-10-19 10:06:43147 EXPECT_CALL(statistics_cb_, OnStatistics(_));
148
149 ReadAndExpectFrameReadyWith(AudioDecoder::kOk, decoded_frame_);
150 }
151
152 // Sets up expectations and actions to put DecryptingAudioDecoder in an end
153 // of stream state. This function must be called after
154 // EnterNormalDecodingState() to work.
155 void EnterEndOfStreamState() {
156 ReadAndExpectFrameReadyWith(AudioDecoder::kOk, end_of_stream_frame_);
157 }
158
159 // Make the read callback pending by saving and not firing it.
160 void EnterPendingReadState() {
161 EXPECT_TRUE(pending_demuxer_read_cb_.is_null());
162 EXPECT_CALL(*demuxer_, Read(_))
163 .WillOnce(SaveArg<0>(&pending_demuxer_read_cb_));
164 decoder_->Read(base::Bind(&DecryptingAudioDecoderTest::FrameReady,
165 base::Unretained(this)));
xhwang@chromium.org643d5442012-11-14 05:08:32166 message_loop_.RunUntilIdle();
xhwang@chromium.org97a9ce42012-10-19 10:06:43167 // Make sure the Read() on the decoder triggers a Read() on the demuxer.
168 EXPECT_FALSE(pending_demuxer_read_cb_.is_null());
169 }
170
171 // Make the audio decode callback pending by saving and not firing it.
172 void EnterPendingDecodeState() {
173 EXPECT_TRUE(pending_audio_decode_cb_.is_null());
174 EXPECT_CALL(*demuxer_, Read(_))
175 .WillRepeatedly(ReturnBuffer(encrypted_buffer_));
176 EXPECT_CALL(*decryptor_, DecryptAndDecodeAudio(encrypted_buffer_, _))
177 .WillOnce(SaveArg<1>(&pending_audio_decode_cb_));
178
179 decoder_->Read(base::Bind(&DecryptingAudioDecoderTest::FrameReady,
180 base::Unretained(this)));
xhwang@chromium.org643d5442012-11-14 05:08:32181 message_loop_.RunUntilIdle();
xhwang@chromium.org97a9ce42012-10-19 10:06:43182 // Make sure the Read() on the decoder triggers a DecryptAndDecode() on the
183 // decryptor.
184 EXPECT_FALSE(pending_audio_decode_cb_.is_null());
185 }
186
187 void EnterWaitingForKeyState() {
188 EXPECT_CALL(*demuxer_, Read(_))
189 .WillRepeatedly(ReturnBuffer(encrypted_buffer_));
xhwang@chromium.org2b454ff82012-11-15 03:57:58190 EXPECT_CALL(*decryptor_, DecryptAndDecodeAudio(encrypted_buffer_, _))
xhwang@chromium.org8b10f2222012-11-13 05:49:48191 .WillRepeatedly(RunCallback<1>(Decryptor::kNoKey,
192 Decryptor::AudioBuffers()));
xhwang@chromium.org97a9ce42012-10-19 10:06:43193 decoder_->Read(base::Bind(&DecryptingAudioDecoderTest::FrameReady,
194 base::Unretained(this)));
xhwang@chromium.org643d5442012-11-14 05:08:32195 message_loop_.RunUntilIdle();
xhwang@chromium.org97a9ce42012-10-19 10:06:43196 }
197
198 void AbortPendingAudioDecodeCB() {
199 if (!pending_audio_decode_cb_.is_null()) {
200 base::ResetAndReturn(&pending_audio_decode_cb_).Run(
201 Decryptor::kSuccess, Decryptor::AudioBuffers());
202 }
203 }
204
205 void Reset() {
206 EXPECT_CALL(*decryptor_, ResetDecoder(Decryptor::kAudio))
207 .WillRepeatedly(InvokeWithoutArgs(
208 this, &DecryptingAudioDecoderTest::AbortPendingAudioDecodeCB));
209
210 decoder_->Reset(NewExpectedClosure());
xhwang@chromium.org643d5442012-11-14 05:08:32211 message_loop_.RunUntilIdle();
xhwang@chromium.org97a9ce42012-10-19 10:06:43212 }
213
xhwang@chromium.orgdaede9b92012-12-14 00:57:25214 MOCK_METHOD1(RequestDecryptorNotification, void(const DecryptorReadyCB&));
xhwang@chromium.org97a9ce42012-10-19 10:06:43215
216 MOCK_METHOD2(FrameReady, void(AudioDecoder::Status,
217 const scoped_refptr<Buffer>&));
218
219 MessageLoop message_loop_;
xhwang@chromium.org2b454ff82012-11-15 03:57:58220 scoped_refptr<DecryptingAudioDecoder> decoder_;
xhwang@chromium.org97a9ce42012-10-19 10:06:43221 scoped_ptr<StrictMock<MockDecryptor> > decryptor_;
222 scoped_refptr<StrictMock<MockDemuxerStream> > demuxer_;
223 MockStatisticsCB statistics_cb_;
xhwang@chromium.org7c39486c2013-01-06 15:36:09224 AudioDecoderConfig config_;
xhwang@chromium.org97a9ce42012-10-19 10:06:43225
226 DemuxerStream::ReadCB pending_demuxer_read_cb_;
227 Decryptor::DecoderInitCB pending_init_cb_;
xhwang@chromium.orgabd36b3af2012-12-22 03:42:02228 Decryptor::NewKeyCB key_added_cb_;
xhwang@chromium.org97a9ce42012-10-19 10:06:43229 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
241TEST_F(DecryptingAudioDecoderTest, Initialize_Normal) {
242 Initialize();
243}
244
245// Ensure that DecryptingAudioDecoder only accepts encrypted audio.
246TEST_F(DecryptingAudioDecoderTest, Initialize_UnencryptedAudioConfig) {
dalecurtis@google.comb5eca3c2013-01-04 20:20:15247 AudioDecoderConfig config(kCodecVorbis, kSampleFormatPlanarF32,
248 CHANNEL_LAYOUT_STEREO, 44100, NULL, 0, false);
xhwang@chromium.org97a9ce42012-10-19 10:06:43249
250 InitializeAndExpectStatus(config, DECODER_ERROR_NOT_SUPPORTED);
251}
252
253// Ensure decoder handles invalid audio configs without crashing.
254TEST_F(DecryptingAudioDecoderTest, Initialize_InvalidAudioConfig) {
dalecurtis@google.comb5eca3c2013-01-04 20:20:15255 AudioDecoderConfig config(kUnknownAudioCodec, kUnknownSampleFormat,
256 CHANNEL_LAYOUT_STEREO, 0, NULL, 0, true);
xhwang@chromium.org97a9ce42012-10-19 10:06:43257
258 InitializeAndExpectStatus(config, PIPELINE_ERROR_DECODE);
259}
260
261// Ensure decoder handles unsupported audio configs without crashing.
262TEST_F(DecryptingAudioDecoderTest, Initialize_UnsupportedAudioConfig) {
xhwang@chromium.org82d7abd2012-11-02 23:04:03263 EXPECT_CALL(*decryptor_, InitializeAudioDecoderMock(_, _))
xhwang@chromium.org8b10f2222012-11-13 05:49:48264 .WillOnce(RunCallback<1>(false));
xhwang@chromium.org97a9ce42012-10-19 10:06:43265 EXPECT_CALL(*this, RequestDecryptorNotification(_))
xhwang@chromium.org8b10f2222012-11-13 05:49:48266 .WillOnce(RunCallbackIfNotNull(decryptor_.get()));
xhwang@chromium.org97a9ce42012-10-19 10:06:43267
dalecurtis@google.comb5eca3c2013-01-04 20:20:15268 AudioDecoderConfig config(kCodecVorbis, kSampleFormatPlanarF32,
269 CHANNEL_LAYOUT_STEREO, 44100, NULL, 0, true);
xhwang@chromium.org97a9ce42012-10-19 10:06:43270 InitializeAndExpectStatus(config, DECODER_ERROR_NOT_SUPPORTED);
271}
272
273// Test normal decrypt and decode case.
274TEST_F(DecryptingAudioDecoderTest, DecryptAndDecode_Normal) {
275 Initialize();
276 EnterNormalDecodingState();
277}
278
279// Test the case where the decryptor returns error when doing decrypt and
280// decode.
281TEST_F(DecryptingAudioDecoderTest, DecryptAndDecode_DecodeError) {
282 Initialize();
283
284 EXPECT_CALL(*demuxer_, Read(_))
285 .WillRepeatedly(ReturnBuffer(encrypted_buffer_));
286 EXPECT_CALL(*decryptor_, DecryptAndDecodeAudio(_, _))
xhwang@chromium.org8b10f2222012-11-13 05:49:48287 .WillRepeatedly(RunCallback<1>(Decryptor::kError,
288 Decryptor::AudioBuffers()));
xhwang@chromium.org97a9ce42012-10-19 10:06:43289
290 ReadAndExpectFrameReadyWith(AudioDecoder::kDecodeError, NULL);
291}
292
293// Test the case where the decryptor returns kNeedMoreData to ask for more
294// buffers before it can produce a frame.
295TEST_F(DecryptingAudioDecoderTest, DecryptAndDecode_NeedMoreData) {
296 Initialize();
297
298 EXPECT_CALL(*demuxer_, Read(_))
299 .Times(2)
300 .WillRepeatedly(ReturnBuffer(encrypted_buffer_));
301 EXPECT_CALL(*decryptor_, DecryptAndDecodeAudio(_, _))
xhwang@chromium.org8b10f2222012-11-13 05:49:48302 .WillOnce(RunCallback<1>(Decryptor::kNeedMoreData,
303 Decryptor::AudioBuffers()))
304 .WillRepeatedly(RunCallback<1>(Decryptor::kSuccess, decoded_frame_list_));
xhwang@chromium.org97a9ce42012-10-19 10:06:43305 EXPECT_CALL(statistics_cb_, OnStatistics(_))
306 .Times(2);
307
308 ReadAndExpectFrameReadyWith(AudioDecoder::kOk, decoded_frame_);
309}
310
311// Test the case where the decryptor returns multiple decoded frames.
312TEST_F(DecryptingAudioDecoderTest, DecryptAndDecode_MultipleFrames) {
313 Initialize();
314
xhwang@chromium.orgecbb9762012-10-24 22:33:54315 scoped_refptr<DataBuffer> frame_a = new DataBuffer(kFakeAudioFrameSize);
316 frame_a->SetDataSize(kFakeAudioFrameSize);
317 scoped_refptr<DataBuffer> frame_b = new DataBuffer(kFakeAudioFrameSize);
318 frame_b->SetDataSize(kFakeAudioFrameSize);
319 decoded_frame_list_.push_back(frame_a);
320 decoded_frame_list_.push_back(frame_b);
xhwang@chromium.org97a9ce42012-10-19 10:06:43321
322 EXPECT_CALL(*demuxer_, Read(_))
323 .WillOnce(ReturnBuffer(encrypted_buffer_));
324 EXPECT_CALL(*decryptor_, DecryptAndDecodeAudio(_, _))
xhwang@chromium.org8b10f2222012-11-13 05:49:48325 .WillOnce(RunCallback<1>(Decryptor::kSuccess, decoded_frame_list_));
xhwang@chromium.org97a9ce42012-10-19 10:06:43326 EXPECT_CALL(statistics_cb_, OnStatistics(_));
327
328 ReadAndExpectFrameReadyWith(AudioDecoder::kOk, decoded_frame_);
xhwang@chromium.orgecbb9762012-10-24 22:33:54329 ReadAndExpectFrameReadyWith(AudioDecoder::kOk, frame_a);
330 ReadAndExpectFrameReadyWith(AudioDecoder::kOk, frame_b);
xhwang@chromium.org97a9ce42012-10-19 10:06:43331}
332
333// Test the case where the decryptor receives end-of-stream buffer.
334TEST_F(DecryptingAudioDecoderTest, DecryptAndDecode_EndOfStream) {
335 Initialize();
336 EnterNormalDecodingState();
337 EnterEndOfStreamState();
xhwang@chromium.org97a9ce42012-10-19 10:06:43338}
339
xhwang@chromium.org7c39486c2013-01-06 15:36:09340// Test aborted read on the demuxer stream.
341TEST_F(DecryptingAudioDecoderTest, DemuxerRead_Aborted) {
342 Initialize();
343
344 // ReturnBuffer() with NULL triggers aborted demuxer read.
345 EXPECT_CALL(*demuxer_, Read(_))
346 .WillOnce(ReturnBuffer(scoped_refptr<DecoderBuffer>()));
347
348 ReadAndExpectFrameReadyWith(AudioDecoder::kAborted, NULL);
349}
350
351// Test config change on the demuxer stream.
352TEST_F(DecryptingAudioDecoderTest, DemuxerRead_ConfigChange) {
353 Initialize();
354
355 EXPECT_CALL(*decryptor_, DeinitializeDecoder(Decryptor::kAudio));
356 EXPECT_CALL(*decryptor_, InitializeAudioDecoderMock(_, _))
357 .WillOnce(RunCallback<1>(true));
358 EXPECT_CALL(*demuxer_, Read(_))
359 .WillOnce(RunCallback<0>(DemuxerStream::kConfigChanged,
360 scoped_refptr<DecoderBuffer>()))
361 .WillRepeatedly(ReturnBuffer(encrypted_buffer_));
362 EXPECT_CALL(*decryptor_, DecryptAndDecodeAudio(_, _))
363 .WillRepeatedly(RunCallback<1>(Decryptor::kSuccess, decoded_frame_list_));
364 EXPECT_CALL(statistics_cb_, OnStatistics(_));
365
366 ReadAndExpectFrameReadyWith(AudioDecoder::kOk, decoded_frame_);
367}
368
369// Test config change failure.
370TEST_F(DecryptingAudioDecoderTest, DemuxerRead_ConfigChangeFailed) {
371 Initialize();
372
373 EXPECT_CALL(*decryptor_, DeinitializeDecoder(Decryptor::kAudio));
374 EXPECT_CALL(*decryptor_, InitializeAudioDecoderMock(_, _))
375 .WillOnce(RunCallback<1>(false));
376 EXPECT_CALL(*demuxer_, Read(_))
377 .WillOnce(RunCallback<0>(DemuxerStream::kConfigChanged,
378 scoped_refptr<DecoderBuffer>()))
379 .WillRepeatedly(ReturnBuffer(encrypted_buffer_));
380
381 ReadAndExpectFrameReadyWith(AudioDecoder::kDecodeError, NULL);
382}
383
xhwang@chromium.org97a9ce42012-10-19 10:06:43384// Test the case where the a key is added when the decryptor is in
385// kWaitingForKey state.
386TEST_F(DecryptingAudioDecoderTest, KeyAdded_DuringWaitingForKey) {
387 Initialize();
388 EnterWaitingForKeyState();
389
390 EXPECT_CALL(*decryptor_, DecryptAndDecodeAudio(_, _))
xhwang@chromium.org8b10f2222012-11-13 05:49:48391 .WillRepeatedly(RunCallback<1>(Decryptor::kSuccess, decoded_frame_list_));
xhwang@chromium.org97a9ce42012-10-19 10:06:43392 EXPECT_CALL(statistics_cb_, OnStatistics(_));
393 EXPECT_CALL(*this, FrameReady(AudioDecoder::kOk, decoded_frame_));
394 key_added_cb_.Run();
xhwang@chromium.org643d5442012-11-14 05:08:32395 message_loop_.RunUntilIdle();
xhwang@chromium.org97a9ce42012-10-19 10:06:43396}
397
398// Test the case where the a key is added when the decryptor is in
399// kPendingDecode state.
400TEST_F(DecryptingAudioDecoderTest, KeyAdded_DruingPendingDecode) {
401 Initialize();
402 EnterPendingDecodeState();
403
404 EXPECT_CALL(*decryptor_, DecryptAndDecodeAudio(_, _))
xhwang@chromium.org8b10f2222012-11-13 05:49:48405 .WillRepeatedly(RunCallback<1>(Decryptor::kSuccess, decoded_frame_list_));
xhwang@chromium.org97a9ce42012-10-19 10:06:43406 EXPECT_CALL(statistics_cb_, OnStatistics(_));
407 EXPECT_CALL(*this, FrameReady(AudioDecoder::kOk, decoded_frame_));
408 // The audio decode callback is returned after the correct decryption key is
409 // added.
410 key_added_cb_.Run();
411 base::ResetAndReturn(&pending_audio_decode_cb_).Run(
412 Decryptor::kNoKey, Decryptor::AudioBuffers());
xhwang@chromium.org643d5442012-11-14 05:08:32413 message_loop_.RunUntilIdle();
xhwang@chromium.org97a9ce42012-10-19 10:06:43414}
415
416// Test resetting when the decoder is in kIdle state but has not decoded any
417// frame.
418TEST_F(DecryptingAudioDecoderTest, Reset_DuringIdleAfterInitialization) {
419 Initialize();
420 Reset();
421}
422
423// Test resetting when the decoder is in kIdle state after it has decoded one
424// frame.
425TEST_F(DecryptingAudioDecoderTest, Reset_DuringIdleAfterDecodedOneFrame) {
426 Initialize();
427 EnterNormalDecodingState();
428 Reset();
429}
430
xhwang@chromium.org7c39486c2013-01-06 15:36:09431// Test resetting when the decoder is in kPendingDemuxerRead state and the read
432// callback is returned with kOk.
433TEST_F(DecryptingAudioDecoderTest, Reset_DuringDemuxerRead_Ok) {
xhwang@chromium.org97a9ce42012-10-19 10:06:43434 Initialize();
435 EnterPendingReadState();
436
xhwang@chromium.org8f5a9a52012-10-23 20:49:20437 EXPECT_CALL(*this, FrameReady(AudioDecoder::kAborted, IsNull()));
xhwang@chromium.org97a9ce42012-10-19 10:06:43438
439 Reset();
440 base::ResetAndReturn(&pending_demuxer_read_cb_).Run(DemuxerStream::kOk,
441 encrypted_buffer_);
xhwang@chromium.org7c39486c2013-01-06 15:36:09442 message_loop_.RunUntilIdle();
443}
444
445// Test resetting when the decoder is in kPendingDemuxerRead state and the read
446// callback is returned with kAborted.
447TEST_F(DecryptingAudioDecoderTest, Reset_DuringDemuxerRead_Aborted) {
448 Initialize();
449 EnterPendingReadState();
450
451 // Make sure we get a NULL audio frame returned.
452 EXPECT_CALL(*this, FrameReady(AudioDecoder::kAborted, IsNull()));
453
454 Reset();
455 base::ResetAndReturn(&pending_demuxer_read_cb_).Run(DemuxerStream::kAborted,
456 NULL);
457 message_loop_.RunUntilIdle();
458}
459
460// Test resetting when the decoder is in kPendingDemuxerRead state and the read
461// callback is returned with kConfigChanged.
462TEST_F(DecryptingAudioDecoderTest, Reset_DuringDemuxerRead_ConfigChange) {
463 Initialize();
464 EnterPendingReadState();
465
466 Reset();
467
468 // Even during pending reset, the decoder still needs to be initialized with
469 // the new config.
470 EXPECT_CALL(*decryptor_, DeinitializeDecoder(Decryptor::kAudio));
471 EXPECT_CALL(*decryptor_, InitializeAudioDecoderMock(_, _))
472 .WillOnce(RunCallback<1>(true));
473 EXPECT_CALL(*this, FrameReady(AudioDecoder::kAborted, IsNull()));
474
475 base::ResetAndReturn(&pending_demuxer_read_cb_)
476 .Run(DemuxerStream::kConfigChanged, NULL);
477 message_loop_.RunUntilIdle();
478}
479
480// Test resetting when the decoder is in kPendingDemuxerRead state, the read
481// callback is returned with kConfigChanged and the config change fails.
482TEST_F(DecryptingAudioDecoderTest, Reset_DuringDemuxerRead_ConfigChangeFailed) {
483 Initialize();
484 EnterPendingReadState();
485
486 Reset();
487
488 // Even during pending reset, the decoder still needs to be initialized with
489 // the new config.
490 EXPECT_CALL(*decryptor_, DeinitializeDecoder(Decryptor::kAudio));
491 EXPECT_CALL(*decryptor_, InitializeAudioDecoderMock(_, _))
492 .WillOnce(RunCallback<1>(false));
493 EXPECT_CALL(*this, FrameReady(AudioDecoder::kDecodeError, IsNull()));
494
495 base::ResetAndReturn(&pending_demuxer_read_cb_)
496 .Run(DemuxerStream::kConfigChanged, NULL);
497 message_loop_.RunUntilIdle();
498}
499
500// Test resetting when the decoder is in kPendingConfigChange state.
501TEST_F(DecryptingAudioDecoderTest, Reset_DuringPendingConfigChange) {
502 Initialize();
503 EnterNormalDecodingState();
504
505 EXPECT_CALL(*demuxer_, Read(_))
506 .WillOnce(RunCallback<0>(DemuxerStream::kConfigChanged,
507 scoped_refptr<DecoderBuffer>()));
508 EXPECT_CALL(*decryptor_, DeinitializeDecoder(Decryptor::kAudio));
509 EXPECT_CALL(*decryptor_, InitializeAudioDecoderMock(_, _))
510 .WillOnce(SaveArg<1>(&pending_init_cb_));
511
512 decoder_->Read(base::Bind(&DecryptingAudioDecoderTest::FrameReady,
513 base::Unretained(this)));
514 message_loop_.RunUntilIdle();
515 EXPECT_FALSE(pending_init_cb_.is_null());
516
517 EXPECT_CALL(*this, FrameReady(AudioDecoder::kAborted, IsNull()));
518
519 Reset();
520 base::ResetAndReturn(&pending_init_cb_).Run(true);
xhwang@chromium.org643d5442012-11-14 05:08:32521 message_loop_.RunUntilIdle();
xhwang@chromium.org97a9ce42012-10-19 10:06:43522}
523
524// Test resetting when the decoder is in kPendingDecode state.
525TEST_F(DecryptingAudioDecoderTest, Reset_DuringPendingDecode) {
526 Initialize();
527 EnterPendingDecodeState();
528
xhwang@chromium.org8f5a9a52012-10-23 20:49:20529 EXPECT_CALL(*this, FrameReady(AudioDecoder::kAborted, IsNull()));
xhwang@chromium.org97a9ce42012-10-19 10:06:43530
531 Reset();
532}
533
534// Test resetting when the decoder is in kWaitingForKey state.
535TEST_F(DecryptingAudioDecoderTest, Reset_DuringWaitingForKey) {
536 Initialize();
537 EnterWaitingForKeyState();
538
xhwang@chromium.org8f5a9a52012-10-23 20:49:20539 EXPECT_CALL(*this, FrameReady(AudioDecoder::kAborted, IsNull()));
xhwang@chromium.org97a9ce42012-10-19 10:06:43540
541 Reset();
542}
543
544// Test resetting when the decoder has hit end of stream and is in
545// kDecodeFinished state.
546TEST_F(DecryptingAudioDecoderTest, Reset_AfterDecodeFinished) {
547 Initialize();
548 EnterNormalDecodingState();
549 EnterEndOfStreamState();
550 Reset();
551}
552
553// Test resetting after the decoder has been reset.
554TEST_F(DecryptingAudioDecoderTest, Reset_AfterReset) {
555 Initialize();
556 EnterNormalDecodingState();
557 Reset();
558 Reset();
xhwang@chromium.org97a9ce42012-10-19 10:06:43559}
560
561} // namespace media