[go: nahoru, domu]

blob: 1ca19b88c9014b84a4386b09ab7cd3af866c10b9 [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;
xhwang@chromium.org97a9ce42012-10-19 10:06:4324using ::testing::SaveArg;
25using ::testing::StrictMock;
26
27namespace media {
28
xhwang@chromium.orgecf16912013-01-12 16:55:2229// Make sure the kFakeAudioFrameSize is a valid frame size for all audio decoder
30// configs used in this test.
31static const int kFakeAudioFrameSize = 48;
xhwang@chromium.org97a9ce42012-10-19 10:06:4332static const uint8 kFakeKeyId[] = { 0x4b, 0x65, 0x79, 0x20, 0x49, 0x44 };
33static const uint8 kFakeIv[DecryptConfig::kDecryptionKeySize] = { 0 };
34
35// Create a fake non-empty encrypted buffer.
36static 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.
50namespace {
51
52ACTION_P(ReturnBuffer, buffer) {
rsleevi@chromium.org5b7ca4282013-06-03 00:19:1653 arg0.Run(buffer.get() ? DemuxerStream::kOk : DemuxerStream::kAborted, buffer);
xhwang@chromium.org97a9ce42012-10-19 10:06:4354}
55
xhwang@chromium.org8b10f2222012-11-13 05:49:4856ACTION_P(RunCallbackIfNotNull, param) {
xhwang@chromium.org97a9ce42012-10-19 10:06:4357 if (!arg0.is_null())
58 arg0.Run(param);
xhwang@chromium.org97a9ce42012-10-19 10:06:4359}
60
61ACTION_P2(ResetAndRunCallback, callback, param) {
62 base::ResetAndReturn(callback).Run(param);
63}
64
xhwang@chromium.org8b10f2222012-11-13 05:49:4865MATCHER(IsEndOfStream, "end of stream") {
xhwang@chromium.org8f5a9a52012-10-23 20:49:2066 return (arg->IsEndOfStream());
67}
68
xhwang@chromium.org97a9ce42012-10-19 10:06:4369} // namespace
70
71class DecryptingAudioDecoderTest : public testing::Test {
72 public:
73 DecryptingAudioDecoderTest()
xhwang@chromium.org2b454ff82012-11-15 03:57:5874 : decoder_(new DecryptingAudioDecoder(
scherkus@chromium.org8c076cb2012-11-28 21:06:1675 message_loop_.message_loop_proxy(),
xhwang@chromium.org97a9ce42012-10-19 10:06:4376 base::Bind(
77 &DecryptingAudioDecoderTest::RequestDecryptorNotification,
78 base::Unretained(this)))),
79 decryptor_(new StrictMock<MockDecryptor>()),
xhwang@chromium.orgac853e02013-04-25 01:15:5280 demuxer_(new StrictMock<MockDemuxerStream>(DemuxerStream::AUDIO)),
xhwang@chromium.org97a9ce42012-10-19 10:06:4381 encrypted_buffer_(CreateFakeEncryptedBuffer()),
xhwang@chromium.orgecbb9762012-10-24 22:33:5482 decoded_frame_(NULL),
scherkus@chromium.org5095fbf2013-01-17 23:20:1483 end_of_stream_frame_(DataBuffer::CreateEOSBuffer()),
xhwang@chromium.orgecbb9762012-10-24 22:33:5484 decoded_frame_list_() {
xhwang@chromium.org2b454ff82012-11-15 03:57:5885 scoped_refptr<DataBuffer> data_buffer = new DataBuffer(kFakeAudioFrameSize);
86 data_buffer->SetDataSize(kFakeAudioFrameSize);
87 // |decoded_frame_| contains random data.
88 decoded_frame_ = data_buffer;
xhwang@chromium.orgecbb9762012-10-24 22:33:5489 decoded_frame_list_.push_back(decoded_frame_);
xhwang@chromium.org97a9ce42012-10-19 10:06:4390 }
91
92 void InitializeAndExpectStatus(const AudioDecoderConfig& config,
93 PipelineStatus status) {
xhwang@chromium.orgac853e02013-04-25 01:15:5294 demuxer_->set_audio_decoder_config(config);
scherkus@chromium.org34811ef2013-04-25 08:51:4795 decoder_->Initialize(demuxer_.get(), NewExpectedStatusCB(status),
xhwang@chromium.org97a9ce42012-10-19 10:06:4396 base::Bind(&MockStatisticsCB::OnStatistics,
97 base::Unretained(&statistics_cb_)));
xhwang@chromium.org643d5442012-11-14 05:08:3298 message_loop_.RunUntilIdle();
xhwang@chromium.org97a9ce42012-10-19 10:06:4399 }
100
101 void Initialize() {
xhwang@chromium.orga3e28672013-03-14 14:54:59102 EXPECT_CALL(*decryptor_, InitializeAudioDecoder(_, _))
xhwang@chromium.org97a9ce42012-10-19 10:06:43103 .Times(AtMost(1))
xhwang@chromium.org8b10f2222012-11-13 05:49:48104 .WillOnce(RunCallback<1>(true));
xhwang@chromium.org97a9ce42012-10-19 10:06:43105 EXPECT_CALL(*this, RequestDecryptorNotification(_))
xhwang@chromium.org8b10f2222012-11-13 05:49:48106 .WillOnce(RunCallbackIfNotNull(decryptor_.get()));
xhwang@chromium.orgabd36b3af2012-12-22 03:42:02107 EXPECT_CALL(*decryptor_, RegisterNewKeyCB(Decryptor::kAudio, _))
xhwang@chromium.org82d7abd2012-11-02 23:04:03108 .WillOnce(SaveArg<1>(&key_added_cb_));
xhwang@chromium.org97a9ce42012-10-19 10:06:43109
xhwang@chromium.org7c39486c2013-01-06 15:36:09110 config_.Initialize(kCodecVorbis, kSampleFormatPlanarF32,
111 CHANNEL_LAYOUT_STEREO, 44100, NULL, 0, true, true);
112 InitializeAndExpectStatus(config_, PIPELINE_OK);
xhwang@chromium.org97a9ce42012-10-19 10:06:43113
xhwang@chromium.orgca1d8f72013-01-15 06:25:03114 EXPECT_EQ(DecryptingAudioDecoder::kSupportedBitsPerChannel,
115 decoder_->bits_per_channel());
xhwang@chromium.org7c39486c2013-01-06 15:36:09116 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,
scherkus@chromium.orgb33417332013-01-15 19:50:09122 const scoped_refptr<DataBuffer>& audio_frame) {
xhwang@chromium.org97a9ce42012-10-19 10:06:43123 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,
scherkus@chromium.orgb33417332013-01-15 19:50:09217 const scoped_refptr<DataBuffer>&));
xhwang@chromium.org97a9ce42012-10-19 10:06:43218
xhwang@chromium.orgfb5af232013-04-22 22:40:03219 base::MessageLoop message_loop_;
scherkus@chromium.org7dd4c742013-03-21 22:33:47220 scoped_ptr<DecryptingAudioDecoder> decoder_;
xhwang@chromium.org97a9ce42012-10-19 10:06:43221 scoped_ptr<StrictMock<MockDecryptor> > decryptor_;
scherkus@chromium.org34811ef2013-04-25 08:51:47222 scoped_ptr<StrictMock<MockDemuxerStream> > demuxer_;
xhwang@chromium.org97a9ce42012-10-19 10:06:43223 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_;
scherkus@chromium.orgb33417332013-01-15 19:50:09233 scoped_refptr<DataBuffer> decoded_frame_;
234 scoped_refptr<DataBuffer> end_of_stream_frame_;
xhwang@chromium.org97a9ce42012-10-19 10:06:43235 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.orga3e28672013-03-14 14:54:59263 EXPECT_CALL(*decryptor_, InitializeAudioDecoder(_, _))
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
xhwang@chromium.org699b64a2013-06-19 07:36:05273TEST_F(DecryptingAudioDecoderTest, Initialize_NullDecryptor) {
274 EXPECT_CALL(*this, RequestDecryptorNotification(_))
275 .WillRepeatedly(RunCallbackIfNotNull(static_cast<Decryptor*>(NULL)));
276
277 AudioDecoderConfig config(kCodecVorbis, kSampleFormatPlanarF32,
278 CHANNEL_LAYOUT_STEREO, 44100, NULL, 0, true);
279 InitializeAndExpectStatus(config, DECODER_ERROR_NOT_SUPPORTED);
280}
281
xhwang@chromium.org97a9ce42012-10-19 10:06:43282// Test normal decrypt and decode case.
283TEST_F(DecryptingAudioDecoderTest, DecryptAndDecode_Normal) {
284 Initialize();
285 EnterNormalDecodingState();
286}
287
288// Test the case where the decryptor returns error when doing decrypt and
289// decode.
290TEST_F(DecryptingAudioDecoderTest, DecryptAndDecode_DecodeError) {
291 Initialize();
292
293 EXPECT_CALL(*demuxer_, Read(_))
294 .WillRepeatedly(ReturnBuffer(encrypted_buffer_));
295 EXPECT_CALL(*decryptor_, DecryptAndDecodeAudio(_, _))
xhwang@chromium.org8b10f2222012-11-13 05:49:48296 .WillRepeatedly(RunCallback<1>(Decryptor::kError,
297 Decryptor::AudioBuffers()));
xhwang@chromium.org97a9ce42012-10-19 10:06:43298
299 ReadAndExpectFrameReadyWith(AudioDecoder::kDecodeError, NULL);
300}
301
302// Test the case where the decryptor returns kNeedMoreData to ask for more
303// buffers before it can produce a frame.
304TEST_F(DecryptingAudioDecoderTest, DecryptAndDecode_NeedMoreData) {
305 Initialize();
306
307 EXPECT_CALL(*demuxer_, Read(_))
308 .Times(2)
309 .WillRepeatedly(ReturnBuffer(encrypted_buffer_));
310 EXPECT_CALL(*decryptor_, DecryptAndDecodeAudio(_, _))
xhwang@chromium.org8b10f2222012-11-13 05:49:48311 .WillOnce(RunCallback<1>(Decryptor::kNeedMoreData,
312 Decryptor::AudioBuffers()))
313 .WillRepeatedly(RunCallback<1>(Decryptor::kSuccess, decoded_frame_list_));
xhwang@chromium.org97a9ce42012-10-19 10:06:43314 EXPECT_CALL(statistics_cb_, OnStatistics(_))
315 .Times(2);
316
317 ReadAndExpectFrameReadyWith(AudioDecoder::kOk, decoded_frame_);
318}
319
320// Test the case where the decryptor returns multiple decoded frames.
321TEST_F(DecryptingAudioDecoderTest, DecryptAndDecode_MultipleFrames) {
322 Initialize();
323
xhwang@chromium.orgecbb9762012-10-24 22:33:54324 scoped_refptr<DataBuffer> frame_a = new DataBuffer(kFakeAudioFrameSize);
325 frame_a->SetDataSize(kFakeAudioFrameSize);
326 scoped_refptr<DataBuffer> frame_b = new DataBuffer(kFakeAudioFrameSize);
327 frame_b->SetDataSize(kFakeAudioFrameSize);
328 decoded_frame_list_.push_back(frame_a);
329 decoded_frame_list_.push_back(frame_b);
xhwang@chromium.org97a9ce42012-10-19 10:06:43330
331 EXPECT_CALL(*demuxer_, Read(_))
332 .WillOnce(ReturnBuffer(encrypted_buffer_));
333 EXPECT_CALL(*decryptor_, DecryptAndDecodeAudio(_, _))
xhwang@chromium.org8b10f2222012-11-13 05:49:48334 .WillOnce(RunCallback<1>(Decryptor::kSuccess, decoded_frame_list_));
xhwang@chromium.org97a9ce42012-10-19 10:06:43335 EXPECT_CALL(statistics_cb_, OnStatistics(_));
336
337 ReadAndExpectFrameReadyWith(AudioDecoder::kOk, decoded_frame_);
xhwang@chromium.orgecbb9762012-10-24 22:33:54338 ReadAndExpectFrameReadyWith(AudioDecoder::kOk, frame_a);
339 ReadAndExpectFrameReadyWith(AudioDecoder::kOk, frame_b);
xhwang@chromium.org97a9ce42012-10-19 10:06:43340}
341
342// Test the case where the decryptor receives end-of-stream buffer.
343TEST_F(DecryptingAudioDecoderTest, DecryptAndDecode_EndOfStream) {
344 Initialize();
345 EnterNormalDecodingState();
346 EnterEndOfStreamState();
xhwang@chromium.org97a9ce42012-10-19 10:06:43347}
348
xhwang@chromium.org7c39486c2013-01-06 15:36:09349// Test aborted read on the demuxer stream.
350TEST_F(DecryptingAudioDecoderTest, DemuxerRead_Aborted) {
351 Initialize();
352
353 // ReturnBuffer() with NULL triggers aborted demuxer read.
354 EXPECT_CALL(*demuxer_, Read(_))
355 .WillOnce(ReturnBuffer(scoped_refptr<DecoderBuffer>()));
356
357 ReadAndExpectFrameReadyWith(AudioDecoder::kAborted, NULL);
358}
359
360// Test config change on the demuxer stream.
361TEST_F(DecryptingAudioDecoderTest, DemuxerRead_ConfigChange) {
362 Initialize();
363
xhwang@chromium.orgecf16912013-01-12 16:55:22364 // The new config is different from the initial config in bits-per-channel,
365 // channel layout and samples_per_second.
366 AudioDecoderConfig new_config(kCodecVorbis, kSampleFormatPlanarS16,
367 CHANNEL_LAYOUT_5_1, 88200, NULL, 0, false);
368 EXPECT_NE(new_config.bits_per_channel(), config_.bits_per_channel());
369 EXPECT_NE(new_config.channel_layout(), config_.channel_layout());
370 EXPECT_NE(new_config.samples_per_second(), config_.samples_per_second());
371
xhwang@chromium.orgac853e02013-04-25 01:15:52372 demuxer_->set_audio_decoder_config(new_config);
xhwang@chromium.org7c39486c2013-01-06 15:36:09373 EXPECT_CALL(*decryptor_, DeinitializeDecoder(Decryptor::kAudio));
xhwang@chromium.orga3e28672013-03-14 14:54:59374 EXPECT_CALL(*decryptor_, InitializeAudioDecoder(_, _))
xhwang@chromium.org7c39486c2013-01-06 15:36:09375 .WillOnce(RunCallback<1>(true));
376 EXPECT_CALL(*demuxer_, Read(_))
377 .WillOnce(RunCallback<0>(DemuxerStream::kConfigChanged,
378 scoped_refptr<DecoderBuffer>()))
379 .WillRepeatedly(ReturnBuffer(encrypted_buffer_));
380 EXPECT_CALL(*decryptor_, DecryptAndDecodeAudio(_, _))
381 .WillRepeatedly(RunCallback<1>(Decryptor::kSuccess, decoded_frame_list_));
382 EXPECT_CALL(statistics_cb_, OnStatistics(_));
383
384 ReadAndExpectFrameReadyWith(AudioDecoder::kOk, decoded_frame_);
xhwang@chromium.orgecf16912013-01-12 16:55:22385
386 EXPECT_EQ(new_config.bits_per_channel(), decoder_->bits_per_channel());
387 EXPECT_EQ(new_config.channel_layout(), decoder_->channel_layout());
388 EXPECT_EQ(new_config.samples_per_second(), decoder_->samples_per_second());
xhwang@chromium.org7c39486c2013-01-06 15:36:09389}
390
391// Test config change failure.
392TEST_F(DecryptingAudioDecoderTest, DemuxerRead_ConfigChangeFailed) {
393 Initialize();
394
395 EXPECT_CALL(*decryptor_, DeinitializeDecoder(Decryptor::kAudio));
xhwang@chromium.orga3e28672013-03-14 14:54:59396 EXPECT_CALL(*decryptor_, InitializeAudioDecoder(_, _))
xhwang@chromium.org7c39486c2013-01-06 15:36:09397 .WillOnce(RunCallback<1>(false));
398 EXPECT_CALL(*demuxer_, Read(_))
399 .WillOnce(RunCallback<0>(DemuxerStream::kConfigChanged,
400 scoped_refptr<DecoderBuffer>()))
401 .WillRepeatedly(ReturnBuffer(encrypted_buffer_));
402
403 ReadAndExpectFrameReadyWith(AudioDecoder::kDecodeError, NULL);
404}
405
xhwang@chromium.org97a9ce42012-10-19 10:06:43406// Test the case where the a key is added when the decryptor is in
407// kWaitingForKey state.
408TEST_F(DecryptingAudioDecoderTest, KeyAdded_DuringWaitingForKey) {
409 Initialize();
410 EnterWaitingForKeyState();
411
412 EXPECT_CALL(*decryptor_, DecryptAndDecodeAudio(_, _))
xhwang@chromium.org8b10f2222012-11-13 05:49:48413 .WillRepeatedly(RunCallback<1>(Decryptor::kSuccess, decoded_frame_list_));
xhwang@chromium.org97a9ce42012-10-19 10:06:43414 EXPECT_CALL(statistics_cb_, OnStatistics(_));
415 EXPECT_CALL(*this, FrameReady(AudioDecoder::kOk, decoded_frame_));
416 key_added_cb_.Run();
xhwang@chromium.org643d5442012-11-14 05:08:32417 message_loop_.RunUntilIdle();
xhwang@chromium.org97a9ce42012-10-19 10:06:43418}
419
420// Test the case where the a key is added when the decryptor is in
421// kPendingDecode state.
422TEST_F(DecryptingAudioDecoderTest, KeyAdded_DruingPendingDecode) {
423 Initialize();
424 EnterPendingDecodeState();
425
426 EXPECT_CALL(*decryptor_, DecryptAndDecodeAudio(_, _))
xhwang@chromium.org8b10f2222012-11-13 05:49:48427 .WillRepeatedly(RunCallback<1>(Decryptor::kSuccess, decoded_frame_list_));
xhwang@chromium.org97a9ce42012-10-19 10:06:43428 EXPECT_CALL(statistics_cb_, OnStatistics(_));
429 EXPECT_CALL(*this, FrameReady(AudioDecoder::kOk, decoded_frame_));
430 // The audio decode callback is returned after the correct decryption key is
431 // added.
432 key_added_cb_.Run();
433 base::ResetAndReturn(&pending_audio_decode_cb_).Run(
434 Decryptor::kNoKey, Decryptor::AudioBuffers());
xhwang@chromium.org643d5442012-11-14 05:08:32435 message_loop_.RunUntilIdle();
xhwang@chromium.org97a9ce42012-10-19 10:06:43436}
437
438// Test resetting when the decoder is in kIdle state but has not decoded any
439// frame.
440TEST_F(DecryptingAudioDecoderTest, Reset_DuringIdleAfterInitialization) {
441 Initialize();
442 Reset();
443}
444
445// Test resetting when the decoder is in kIdle state after it has decoded one
446// frame.
447TEST_F(DecryptingAudioDecoderTest, Reset_DuringIdleAfterDecodedOneFrame) {
448 Initialize();
449 EnterNormalDecodingState();
450 Reset();
451}
452
xhwang@chromium.org7c39486c2013-01-06 15:36:09453// Test resetting when the decoder is in kPendingDemuxerRead state and the read
454// callback is returned with kOk.
455TEST_F(DecryptingAudioDecoderTest, Reset_DuringDemuxerRead_Ok) {
xhwang@chromium.org97a9ce42012-10-19 10:06:43456 Initialize();
457 EnterPendingReadState();
458
xhwang@chromium.org8f5a9a52012-10-23 20:49:20459 EXPECT_CALL(*this, FrameReady(AudioDecoder::kAborted, IsNull()));
xhwang@chromium.org97a9ce42012-10-19 10:06:43460
461 Reset();
462 base::ResetAndReturn(&pending_demuxer_read_cb_).Run(DemuxerStream::kOk,
463 encrypted_buffer_);
xhwang@chromium.org7c39486c2013-01-06 15:36:09464 message_loop_.RunUntilIdle();
465}
466
467// Test resetting when the decoder is in kPendingDemuxerRead state and the read
468// callback is returned with kAborted.
469TEST_F(DecryptingAudioDecoderTest, Reset_DuringDemuxerRead_Aborted) {
470 Initialize();
471 EnterPendingReadState();
472
473 // Make sure we get a NULL audio frame returned.
474 EXPECT_CALL(*this, FrameReady(AudioDecoder::kAborted, IsNull()));
475
476 Reset();
477 base::ResetAndReturn(&pending_demuxer_read_cb_).Run(DemuxerStream::kAborted,
478 NULL);
479 message_loop_.RunUntilIdle();
480}
481
482// Test resetting when the decoder is in kPendingDemuxerRead state and the read
483// callback is returned with kConfigChanged.
484TEST_F(DecryptingAudioDecoderTest, Reset_DuringDemuxerRead_ConfigChange) {
485 Initialize();
486 EnterPendingReadState();
487
488 Reset();
489
xhwang@chromium.orgecf16912013-01-12 16:55:22490 // The new config is different from the initial config in bits-per-channel,
491 // channel layout and samples_per_second.
492 AudioDecoderConfig new_config(kCodecVorbis, kSampleFormatPlanarS16,
493 CHANNEL_LAYOUT_5_1, 88200, NULL, 0, false);
494 EXPECT_NE(new_config.bits_per_channel(), config_.bits_per_channel());
495 EXPECT_NE(new_config.channel_layout(), config_.channel_layout());
496 EXPECT_NE(new_config.samples_per_second(), config_.samples_per_second());
497
xhwang@chromium.org7c39486c2013-01-06 15:36:09498 // Even during pending reset, the decoder still needs to be initialized with
499 // the new config.
xhwang@chromium.orgac853e02013-04-25 01:15:52500 demuxer_->set_audio_decoder_config(new_config);
xhwang@chromium.org7c39486c2013-01-06 15:36:09501 EXPECT_CALL(*decryptor_, DeinitializeDecoder(Decryptor::kAudio));
xhwang@chromium.orga3e28672013-03-14 14:54:59502 EXPECT_CALL(*decryptor_, InitializeAudioDecoder(_, _))
xhwang@chromium.org7c39486c2013-01-06 15:36:09503 .WillOnce(RunCallback<1>(true));
504 EXPECT_CALL(*this, FrameReady(AudioDecoder::kAborted, IsNull()));
505
506 base::ResetAndReturn(&pending_demuxer_read_cb_)
507 .Run(DemuxerStream::kConfigChanged, NULL);
508 message_loop_.RunUntilIdle();
xhwang@chromium.orgecf16912013-01-12 16:55:22509
510 EXPECT_EQ(new_config.bits_per_channel(), decoder_->bits_per_channel());
511 EXPECT_EQ(new_config.channel_layout(), decoder_->channel_layout());
512 EXPECT_EQ(new_config.samples_per_second(), decoder_->samples_per_second());
xhwang@chromium.org7c39486c2013-01-06 15:36:09513}
514
515// Test resetting when the decoder is in kPendingDemuxerRead state, the read
516// callback is returned with kConfigChanged and the config change fails.
517TEST_F(DecryptingAudioDecoderTest, Reset_DuringDemuxerRead_ConfigChangeFailed) {
518 Initialize();
519 EnterPendingReadState();
520
521 Reset();
522
523 // Even during pending reset, the decoder still needs to be initialized with
524 // the new config.
525 EXPECT_CALL(*decryptor_, DeinitializeDecoder(Decryptor::kAudio));
xhwang@chromium.orga3e28672013-03-14 14:54:59526 EXPECT_CALL(*decryptor_, InitializeAudioDecoder(_, _))
xhwang@chromium.org7c39486c2013-01-06 15:36:09527 .WillOnce(RunCallback<1>(false));
528 EXPECT_CALL(*this, FrameReady(AudioDecoder::kDecodeError, IsNull()));
529
530 base::ResetAndReturn(&pending_demuxer_read_cb_)
531 .Run(DemuxerStream::kConfigChanged, NULL);
532 message_loop_.RunUntilIdle();
533}
534
535// Test resetting when the decoder is in kPendingConfigChange state.
536TEST_F(DecryptingAudioDecoderTest, Reset_DuringPendingConfigChange) {
537 Initialize();
538 EnterNormalDecodingState();
539
540 EXPECT_CALL(*demuxer_, Read(_))
541 .WillOnce(RunCallback<0>(DemuxerStream::kConfigChanged,
542 scoped_refptr<DecoderBuffer>()));
543 EXPECT_CALL(*decryptor_, DeinitializeDecoder(Decryptor::kAudio));
xhwang@chromium.orga3e28672013-03-14 14:54:59544 EXPECT_CALL(*decryptor_, InitializeAudioDecoder(_, _))
xhwang@chromium.org7c39486c2013-01-06 15:36:09545 .WillOnce(SaveArg<1>(&pending_init_cb_));
546
547 decoder_->Read(base::Bind(&DecryptingAudioDecoderTest::FrameReady,
548 base::Unretained(this)));
549 message_loop_.RunUntilIdle();
550 EXPECT_FALSE(pending_init_cb_.is_null());
551
552 EXPECT_CALL(*this, FrameReady(AudioDecoder::kAborted, IsNull()));
553
554 Reset();
555 base::ResetAndReturn(&pending_init_cb_).Run(true);
xhwang@chromium.org643d5442012-11-14 05:08:32556 message_loop_.RunUntilIdle();
xhwang@chromium.org97a9ce42012-10-19 10:06:43557}
558
559// Test resetting when the decoder is in kPendingDecode state.
560TEST_F(DecryptingAudioDecoderTest, Reset_DuringPendingDecode) {
561 Initialize();
562 EnterPendingDecodeState();
563
xhwang@chromium.org8f5a9a52012-10-23 20:49:20564 EXPECT_CALL(*this, FrameReady(AudioDecoder::kAborted, IsNull()));
xhwang@chromium.org97a9ce42012-10-19 10:06:43565
566 Reset();
567}
568
569// Test resetting when the decoder is in kWaitingForKey state.
570TEST_F(DecryptingAudioDecoderTest, Reset_DuringWaitingForKey) {
571 Initialize();
572 EnterWaitingForKeyState();
573
xhwang@chromium.org8f5a9a52012-10-23 20:49:20574 EXPECT_CALL(*this, FrameReady(AudioDecoder::kAborted, IsNull()));
xhwang@chromium.org97a9ce42012-10-19 10:06:43575
576 Reset();
577}
578
579// Test resetting when the decoder has hit end of stream and is in
580// kDecodeFinished state.
581TEST_F(DecryptingAudioDecoderTest, Reset_AfterDecodeFinished) {
582 Initialize();
583 EnterNormalDecodingState();
584 EnterEndOfStreamState();
585 Reset();
586}
587
588// Test resetting after the decoder has been reset.
589TEST_F(DecryptingAudioDecoderTest, Reset_AfterReset) {
590 Initialize();
591 EnterNormalDecodingState();
592 Reset();
593 Reset();
xhwang@chromium.org97a9ce42012-10-19 10:06:43594}
595
596} // namespace media