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