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