decrypting_demuxer_stream_unittest.cc revision f2477e01787aa58f445919b809d89e252beef54f
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/decoder_buffer.h"
12#include "media/base/decrypt_config.h"
13#include "media/base/gmock_callback_support.h"
14#include "media/base/mock_filters.h"
15#include "media/base/test_helpers.h"
16#include "media/filters/decrypting_demuxer_stream.h"
17#include "testing/gmock/include/gmock/gmock.h"
18
19using ::testing::_;
20using ::testing::IsNull;
21using ::testing::Return;
22using ::testing::SaveArg;
23using ::testing::StrictMock;
24
25namespace media {
26
27static const int kFakeBufferSize = 16;
28static const uint8 kFakeKeyId[] = { 0x4b, 0x65, 0x79, 0x20, 0x49, 0x44 };
29static const uint8 kFakeIv[DecryptConfig::kDecryptionKeySize] = { 0 };
30
31// Create a fake non-empty buffer in an encrypted stream. When |is_clear| is
32// ture, the buffer is not encrypted (signaled by an empty IV).
33static scoped_refptr<DecoderBuffer> CreateFakeEncryptedStreamBuffer(
34    bool is_clear) {
35  scoped_refptr<DecoderBuffer> buffer(new DecoderBuffer(kFakeBufferSize));
36  std::string iv = is_clear ? std::string() :
37      std::string(reinterpret_cast<const char*>(kFakeIv), arraysize(kFakeIv));
38  buffer->set_decrypt_config(scoped_ptr<DecryptConfig>(new DecryptConfig(
39      std::string(reinterpret_cast<const char*>(kFakeKeyId),
40                  arraysize(kFakeKeyId)),
41      iv, 0, std::vector<SubsampleEntry>())));
42  return buffer;
43}
44
45// Use anonymous namespace here to prevent the actions to be defined multiple
46// times across multiple test files. Sadly we can't use static for them.
47namespace {
48
49ACTION_P(ReturnBuffer, buffer) {
50  arg0.Run(buffer.get() ? DemuxerStream::kOk : DemuxerStream::kAborted, buffer);
51}
52
53ACTION_P(RunCallbackIfNotNull, param) {
54  if (!arg0.is_null())
55    arg0.Run(param);
56}
57
58ACTION_P2(ResetAndRunCallback, callback, param) {
59  base::ResetAndReturn(callback).Run(param);
60}
61
62MATCHER(IsEndOfStream, "end of stream") {
63  return arg->end_of_stream();
64}
65
66}  // namespace
67
68class DecryptingDemuxerStreamTest : public testing::Test {
69 public:
70  DecryptingDemuxerStreamTest()
71      : demuxer_stream_(new DecryptingDemuxerStream(
72            message_loop_.message_loop_proxy(),
73            base::Bind(
74                &DecryptingDemuxerStreamTest::RequestDecryptorNotification,
75                base::Unretained(this)))),
76        decryptor_(new StrictMock<MockDecryptor>()),
77        input_audio_stream_(
78            new StrictMock<MockDemuxerStream>(DemuxerStream::AUDIO)),
79        input_video_stream_(
80            new StrictMock<MockDemuxerStream>(DemuxerStream::VIDEO)),
81        clear_buffer_(CreateFakeEncryptedStreamBuffer(true)),
82        encrypted_buffer_(CreateFakeEncryptedStreamBuffer(false)),
83        decrypted_buffer_(new DecoderBuffer(kFakeBufferSize)) {
84  }
85
86  void InitializeAudioAndExpectStatus(const AudioDecoderConfig& config,
87                                      PipelineStatus status) {
88    input_audio_stream_->set_audio_decoder_config(config);
89    demuxer_stream_->Initialize(input_audio_stream_.get(),
90                                NewExpectedStatusCB(status));
91    message_loop_.RunUntilIdle();
92  }
93
94  void InitializeVideoAndExpectStatus(const VideoDecoderConfig& config,
95                                      PipelineStatus status) {
96    input_video_stream_->set_video_decoder_config(config);
97    demuxer_stream_->Initialize(input_video_stream_.get(),
98                                NewExpectedStatusCB(status));
99    message_loop_.RunUntilIdle();
100  }
101
102  // The following functions are used to test stream-type-neutral logic in
103  // DecryptingDemuxerStream. Therefore, we don't specify audio or video in the
104  // function names. But for testing purpose, they all use an audio input
105  // demuxer stream.
106
107  void Initialize() {
108    EXPECT_CALL(*this, RequestDecryptorNotification(_))
109        .WillOnce(RunCallbackIfNotNull(decryptor_.get()));
110    EXPECT_CALL(*decryptor_, RegisterNewKeyCB(Decryptor::kAudio, _))
111        .WillOnce(SaveArg<1>(&key_added_cb_));
112
113    AudioDecoderConfig input_config(
114        kCodecVorbis, kSampleFormatPlanarF32, CHANNEL_LAYOUT_STEREO, 44100,
115        NULL, 0, true);
116    InitializeAudioAndExpectStatus(input_config, PIPELINE_OK);
117
118    const AudioDecoderConfig& output_config =
119        demuxer_stream_->audio_decoder_config();
120    EXPECT_EQ(DemuxerStream::AUDIO, demuxer_stream_->type());
121    EXPECT_FALSE(output_config.is_encrypted());
122    EXPECT_EQ(input_config.bits_per_channel(),
123              output_config.bits_per_channel());
124    EXPECT_EQ(input_config.channel_layout(), output_config.channel_layout());
125    EXPECT_EQ(input_config.sample_format(), output_config.sample_format());
126    EXPECT_EQ(input_config.samples_per_second(),
127              output_config.samples_per_second());
128  }
129
130  void ReadAndExpectBufferReadyWith(
131      DemuxerStream::Status status,
132      const scoped_refptr<DecoderBuffer>& decrypted_buffer) {
133    if (status != DemuxerStream::kOk)
134      EXPECT_CALL(*this, BufferReady(status, IsNull()));
135    else if (decrypted_buffer->end_of_stream())
136      EXPECT_CALL(*this, BufferReady(status, IsEndOfStream()));
137    else
138      EXPECT_CALL(*this, BufferReady(status, decrypted_buffer));
139
140    demuxer_stream_->Read(base::Bind(&DecryptingDemuxerStreamTest::BufferReady,
141                                     base::Unretained(this)));
142    message_loop_.RunUntilIdle();
143  }
144
145  void EnterClearReadingState() {
146    EXPECT_TRUE(clear_buffer_->decrypt_config());
147    EXPECT_CALL(*input_audio_stream_, Read(_))
148        .WillOnce(ReturnBuffer(clear_buffer_));
149
150    // For clearbuffer, decryptor->Decrypt() will not be called.
151
152    scoped_refptr<DecoderBuffer> decrypted_buffer;
153    EXPECT_CALL(*this, BufferReady(DemuxerStream::kOk, _))
154        .WillOnce(SaveArg<1>(&decrypted_buffer));
155    demuxer_stream_->Read(base::Bind(&DecryptingDemuxerStreamTest::BufferReady,
156                                     base::Unretained(this)));
157    message_loop_.RunUntilIdle();
158
159    EXPECT_FALSE(decrypted_buffer->decrypt_config());
160  }
161
162  // Sets up expectations and actions to put DecryptingDemuxerStream in an
163  // active normal reading state.
164  void EnterNormalReadingState() {
165    EXPECT_CALL(*input_audio_stream_, Read(_))
166        .WillOnce(ReturnBuffer(encrypted_buffer_));
167    EXPECT_CALL(*decryptor_, Decrypt(_, _, _))
168        .WillOnce(RunCallback<2>(Decryptor::kSuccess, decrypted_buffer_));
169
170    ReadAndExpectBufferReadyWith(DemuxerStream::kOk, decrypted_buffer_);
171  }
172
173  // Make the read callback pending by saving and not firing it.
174  void EnterPendingReadState() {
175    EXPECT_TRUE(pending_demuxer_read_cb_.is_null());
176    EXPECT_CALL(*input_audio_stream_, Read(_))
177        .WillOnce(SaveArg<0>(&pending_demuxer_read_cb_));
178    demuxer_stream_->Read(base::Bind(&DecryptingDemuxerStreamTest::BufferReady,
179                                     base::Unretained(this)));
180    message_loop_.RunUntilIdle();
181    // Make sure the Read() triggers a Read() on the input demuxer stream.
182    EXPECT_FALSE(pending_demuxer_read_cb_.is_null());
183  }
184
185  // Make the decrypt callback pending by saving and not firing it.
186  void EnterPendingDecryptState() {
187    EXPECT_TRUE(pending_decrypt_cb_.is_null());
188    EXPECT_CALL(*input_audio_stream_, Read(_))
189        .WillRepeatedly(ReturnBuffer(encrypted_buffer_));
190    EXPECT_CALL(*decryptor_, Decrypt(_, encrypted_buffer_, _))
191        .WillOnce(SaveArg<2>(&pending_decrypt_cb_));
192
193    demuxer_stream_->Read(base::Bind(&DecryptingDemuxerStreamTest::BufferReady,
194                                     base::Unretained(this)));
195    message_loop_.RunUntilIdle();
196    // Make sure Read() triggers a Decrypt() on the decryptor.
197    EXPECT_FALSE(pending_decrypt_cb_.is_null());
198  }
199
200  void EnterWaitingForKeyState() {
201    EXPECT_CALL(*input_audio_stream_, Read(_))
202        .WillRepeatedly(ReturnBuffer(encrypted_buffer_));
203    EXPECT_CALL(*decryptor_, Decrypt(_, encrypted_buffer_, _))
204        .WillRepeatedly(RunCallback<2>(Decryptor::kNoKey,
205                                       scoped_refptr<DecoderBuffer>()));
206    demuxer_stream_->Read(base::Bind(&DecryptingDemuxerStreamTest::BufferReady,
207                                     base::Unretained(this)));
208    message_loop_.RunUntilIdle();
209  }
210
211  void AbortPendingDecryptCB() {
212    if (!pending_decrypt_cb_.is_null()) {
213      base::ResetAndReturn(&pending_decrypt_cb_).Run(Decryptor::kSuccess, NULL);
214    }
215  }
216
217  void SatisfyPendingDemuxerReadCB(DemuxerStream::Status status) {
218    scoped_refptr<DecoderBuffer> buffer =
219        (status == DemuxerStream::kOk) ? encrypted_buffer_ : NULL;
220    base::ResetAndReturn(&pending_demuxer_read_cb_).Run(status, buffer);
221  }
222
223  void Reset() {
224    EXPECT_CALL(*decryptor_, CancelDecrypt(Decryptor::kAudio))
225        .WillRepeatedly(InvokeWithoutArgs(
226            this, &DecryptingDemuxerStreamTest::AbortPendingDecryptCB));
227
228    demuxer_stream_->Reset(NewExpectedClosure());
229    message_loop_.RunUntilIdle();
230  }
231
232  MOCK_METHOD1(RequestDecryptorNotification, void(const DecryptorReadyCB&));
233
234  MOCK_METHOD2(BufferReady, void(DemuxerStream::Status,
235                                 const scoped_refptr<DecoderBuffer>&));
236
237  base::MessageLoop message_loop_;
238  scoped_ptr<DecryptingDemuxerStream> demuxer_stream_;
239  scoped_ptr<StrictMock<MockDecryptor> > decryptor_;
240  scoped_ptr<StrictMock<MockDemuxerStream> > input_audio_stream_;
241  scoped_ptr<StrictMock<MockDemuxerStream> > input_video_stream_;
242
243  DemuxerStream::ReadCB pending_demuxer_read_cb_;
244  Decryptor::NewKeyCB key_added_cb_;
245  Decryptor::DecryptCB pending_decrypt_cb_;
246
247  // Constant buffers to be returned by the input demuxer streams and the
248  // |decryptor_|.
249  scoped_refptr<DecoderBuffer> clear_buffer_;
250  scoped_refptr<DecoderBuffer> encrypted_buffer_;
251  scoped_refptr<DecoderBuffer> decrypted_buffer_;
252
253 private:
254  DISALLOW_COPY_AND_ASSIGN(DecryptingDemuxerStreamTest);
255};
256
257TEST_F(DecryptingDemuxerStreamTest, Initialize_NormalAudio) {
258  Initialize();
259}
260
261TEST_F(DecryptingDemuxerStreamTest, Initialize_NormalVideo) {
262  EXPECT_CALL(*this, RequestDecryptorNotification(_))
263      .WillOnce(RunCallbackIfNotNull(decryptor_.get()));
264  EXPECT_CALL(*decryptor_, RegisterNewKeyCB(Decryptor::kVideo, _))
265        .WillOnce(SaveArg<1>(&key_added_cb_));
266
267  VideoDecoderConfig input_config = TestVideoConfig::NormalEncrypted();
268  InitializeVideoAndExpectStatus(input_config, PIPELINE_OK);
269
270  const VideoDecoderConfig& output_config =
271      demuxer_stream_->video_decoder_config();
272  EXPECT_EQ(DemuxerStream::VIDEO, demuxer_stream_->type());
273  EXPECT_FALSE(output_config.is_encrypted());
274  EXPECT_EQ(input_config.codec(), output_config.codec());
275  EXPECT_EQ(input_config.format(), output_config.format());
276  EXPECT_EQ(input_config.profile(), output_config.profile());
277  EXPECT_EQ(input_config.coded_size(), output_config.coded_size());
278  EXPECT_EQ(input_config.visible_rect(), output_config.visible_rect());
279  EXPECT_EQ(input_config.natural_size(), output_config.natural_size());
280  ASSERT_EQ(input_config.extra_data_size(), output_config.extra_data_size());
281  if (input_config.extra_data_size() > 0) {
282    EXPECT_FALSE(output_config.extra_data());
283    EXPECT_EQ(0, memcmp(output_config.extra_data(), input_config.extra_data(),
284                        input_config.extra_data_size()));
285  }
286}
287
288TEST_F(DecryptingDemuxerStreamTest, Initialize_NullDecryptor) {
289  EXPECT_CALL(*this, RequestDecryptorNotification(_))
290      .WillRepeatedly(RunCallbackIfNotNull(static_cast<Decryptor*>(NULL)));
291
292  AudioDecoderConfig input_config(kCodecVorbis, kSampleFormatPlanarF32,
293                                  CHANNEL_LAYOUT_STEREO, 44100, NULL, 0, true);
294  InitializeAudioAndExpectStatus(input_config, DECODER_ERROR_NOT_SUPPORTED);
295}
296
297// Test normal read case where the buffer is encrypted.
298TEST_F(DecryptingDemuxerStreamTest, Read_Normal) {
299  Initialize();
300  EnterNormalReadingState();
301}
302
303// Test normal read case where the buffer is clear.
304TEST_F(DecryptingDemuxerStreamTest, Read_Clear) {
305  Initialize();
306  EnterClearReadingState();
307}
308
309// Test the case where the decryptor returns error during read.
310TEST_F(DecryptingDemuxerStreamTest, Read_DecryptError) {
311  Initialize();
312
313  EXPECT_CALL(*input_audio_stream_, Read(_))
314      .WillRepeatedly(ReturnBuffer(encrypted_buffer_));
315  EXPECT_CALL(*decryptor_, Decrypt(_, encrypted_buffer_, _))
316      .WillRepeatedly(RunCallback<2>(Decryptor::kError,
317                                     scoped_refptr<DecoderBuffer>()));
318  ReadAndExpectBufferReadyWith(DemuxerStream::kAborted, NULL);
319}
320
321// Test the case where the input is an end-of-stream buffer.
322TEST_F(DecryptingDemuxerStreamTest, Read_EndOfStream) {
323  Initialize();
324  EnterNormalReadingState();
325
326  // No Decryptor::Decrypt() call is expected for EOS buffer.
327  EXPECT_CALL(*input_audio_stream_, Read(_))
328      .WillOnce(ReturnBuffer(DecoderBuffer::CreateEOSBuffer()));
329
330  ReadAndExpectBufferReadyWith(DemuxerStream::kOk,
331                               DecoderBuffer::CreateEOSBuffer());
332}
333
334// Test the case where the a key is added when the decryptor is in
335// kWaitingForKey state.
336TEST_F(DecryptingDemuxerStreamTest, KeyAdded_DuringWaitingForKey) {
337  Initialize();
338  EnterWaitingForKeyState();
339
340  EXPECT_CALL(*decryptor_, Decrypt(_, encrypted_buffer_, _))
341      .WillRepeatedly(RunCallback<2>(Decryptor::kSuccess, decrypted_buffer_));
342  EXPECT_CALL(*this, BufferReady(DemuxerStream::kOk, decrypted_buffer_));
343  key_added_cb_.Run();
344  message_loop_.RunUntilIdle();
345}
346
347// Test the case where the a key is added when the decryptor is in
348// kPendingDecrypt state.
349TEST_F(DecryptingDemuxerStreamTest, KeyAdded_DruingPendingDecrypt) {
350  Initialize();
351  EnterPendingDecryptState();
352
353  EXPECT_CALL(*decryptor_, Decrypt(_, encrypted_buffer_, _))
354      .WillRepeatedly(RunCallback<2>(Decryptor::kSuccess, decrypted_buffer_));
355  EXPECT_CALL(*this, BufferReady(DemuxerStream::kOk, decrypted_buffer_));
356  // The decrypt callback is returned after the correct decryption key is added.
357  key_added_cb_.Run();
358  base::ResetAndReturn(&pending_decrypt_cb_).Run(Decryptor::kNoKey, NULL);
359  message_loop_.RunUntilIdle();
360}
361
362// Test resetting when the DecryptingDemuxerStream is in kDecryptorRequested
363// state.
364TEST_F(DecryptingDemuxerStreamTest, Reset_DuringDecryptorRequested) {
365  // One for decryptor request, one for canceling request during Reset().
366  EXPECT_CALL(*this, RequestDecryptorNotification(_))
367      .Times(2);
368  AudioDecoderConfig input_config(
369      kCodecVorbis, kSampleFormatPlanarF32, CHANNEL_LAYOUT_STEREO, 44100,
370      NULL, 0, true);
371  InitializeAudioAndExpectStatus(input_config, PIPELINE_ERROR_ABORT);
372  Reset();
373}
374
375// Test resetting when the DecryptingDemuxerStream is in kIdle state but has
376// not returned any buffer.
377TEST_F(DecryptingDemuxerStreamTest, Reset_DuringIdleAfterInitialization) {
378  Initialize();
379  Reset();
380}
381
382// Test resetting when the DecryptingDemuxerStream is in kIdle state after it
383// has returned one buffer.
384TEST_F(DecryptingDemuxerStreamTest, Reset_DuringIdleAfterReadOneBuffer) {
385  Initialize();
386  EnterNormalReadingState();
387  Reset();
388}
389
390// Test resetting when DecryptingDemuxerStream is in kPendingDemuxerRead state.
391TEST_F(DecryptingDemuxerStreamTest, Reset_DuringPendingDemuxerRead) {
392  Initialize();
393  EnterPendingReadState();
394
395  EXPECT_CALL(*this, BufferReady(DemuxerStream::kAborted, IsNull()));
396
397  Reset();
398  SatisfyPendingDemuxerReadCB(DemuxerStream::kOk);
399  message_loop_.RunUntilIdle();
400}
401
402// Test resetting when the DecryptingDemuxerStream is in kPendingDecrypt state.
403TEST_F(DecryptingDemuxerStreamTest, Reset_DuringPendingDecrypt) {
404  Initialize();
405  EnterPendingDecryptState();
406
407  EXPECT_CALL(*this, BufferReady(DemuxerStream::kAborted, IsNull()));
408
409  Reset();
410}
411
412// Test resetting when the DecryptingDemuxerStream is in kWaitingForKey state.
413TEST_F(DecryptingDemuxerStreamTest, Reset_DuringWaitingForKey) {
414  Initialize();
415  EnterWaitingForKeyState();
416
417  EXPECT_CALL(*this, BufferReady(DemuxerStream::kAborted, IsNull()));
418
419  Reset();
420}
421
422// Test resetting after the DecryptingDemuxerStream has been reset.
423TEST_F(DecryptingDemuxerStreamTest, Reset_AfterReset) {
424  Initialize();
425  EnterNormalReadingState();
426  Reset();
427  Reset();
428}
429
430// Test aborted read on the demuxer stream.
431TEST_F(DecryptingDemuxerStreamTest, DemuxerRead_Aborted) {
432  Initialize();
433
434  // ReturnBuffer() with NULL triggers aborted demuxer read.
435  EXPECT_CALL(*input_audio_stream_, Read(_))
436      .WillOnce(ReturnBuffer(scoped_refptr<DecoderBuffer>()));
437
438  ReadAndExpectBufferReadyWith(DemuxerStream::kAborted, NULL);
439}
440
441// Test resetting when DecryptingDemuxerStream is waiting for an aborted read.
442TEST_F(DecryptingDemuxerStreamTest, Reset_DuringAbortedDemuxerRead) {
443  Initialize();
444  EnterPendingReadState();
445
446  // Make sure we get a NULL audio frame returned.
447  EXPECT_CALL(*this, BufferReady(DemuxerStream::kAborted, IsNull()));
448
449  Reset();
450  SatisfyPendingDemuxerReadCB(DemuxerStream::kAborted);
451  message_loop_.RunUntilIdle();
452}
453
454// Test config change on the input demuxer stream.
455TEST_F(DecryptingDemuxerStreamTest, DemuxerRead_ConfigChanged) {
456  Initialize();
457
458  AudioDecoderConfig new_config(
459      kCodecVorbis, kSampleFormatPlanarF32, CHANNEL_LAYOUT_STEREO, 88200, NULL,
460      0, true);
461  input_audio_stream_->set_audio_decoder_config(new_config);
462
463  EXPECT_CALL(*input_audio_stream_, Read(_))
464      .WillOnce(RunCallback<0>(DemuxerStream::kConfigChanged,
465                               scoped_refptr<DecoderBuffer>()));
466
467  ReadAndExpectBufferReadyWith(DemuxerStream::kConfigChanged, NULL);
468}
469
470// Test resetting when DecryptingDemuxerStream is waiting for an config changed
471// read.
472TEST_F(DecryptingDemuxerStreamTest, Reset_DuringConfigChangedDemuxerRead) {
473  Initialize();
474  EnterPendingReadState();
475
476  // Make sure we get a |kConfigChanged| instead of a |kAborted|.
477  EXPECT_CALL(*this, BufferReady(DemuxerStream::kConfigChanged, IsNull()));
478
479  Reset();
480  SatisfyPendingDemuxerReadCB(DemuxerStream::kConfigChanged);
481  message_loop_.RunUntilIdle();
482}
483
484}  // namespace media
485