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