diff options
author | xhwang@chromium.org <xhwang@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-01-08 22:23:17 +0000 |
---|---|---|
committer | xhwang@chromium.org <xhwang@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-01-08 22:23:17 +0000 |
commit | dcd57350ed464493780247174db6a7c3628c01a2 (patch) | |
tree | c0ee4511c106a7825b8894c6620f6fabb3aead9a /media | |
parent | 3b10e258f6ebf230e6c0a2c8096346eb002461c6 (diff) | |
download | chromium_src-dcd57350ed464493780247174db6a7c3628c01a2.zip chromium_src-dcd57350ed464493780247174db6a7c3628c01a2.tar.gz chromium_src-dcd57350ed464493780247174db6a7c3628c01a2.tar.bz2 |
Drop DecryptConfig::data_offset_.
This CL drops DecryptConfig::data_offset_ and moves the offset parsing code into WebM demuxers. This allows us to remove offset passing/calculation code in several layers of the media pipeline.
Background:
We used to have HMAC check in encrypted WebM RFC, which requires us to keep the IV together with the encrypted frame, hence the offset. Now the HMAC check is dropped from the RFC so offset is not necessary anymore.
BUG=298569
Review URL: https://codereview.chromium.org/119203003
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@243672 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'media')
-rw-r--r-- | media/base/decrypt_config.cc | 3 | ||||
-rw-r--r-- | media/base/decrypt_config.h | 12 | ||||
-rw-r--r-- | media/cdm/aes_decryptor.cc | 12 | ||||
-rw-r--r-- | media/cdm/aes_decryptor_unittest.cc | 55 | ||||
-rw-r--r-- | media/cdm/ppapi/external_clear_key/clear_key_cdm.cc | 4 | ||||
-rw-r--r-- | media/filters/decrypting_audio_decoder_unittest.cc | 1 | ||||
-rw-r--r-- | media/filters/decrypting_demuxer_stream.cc | 3 | ||||
-rw-r--r-- | media/filters/decrypting_demuxer_stream_unittest.cc | 2 | ||||
-rw-r--r-- | media/filters/decrypting_video_decoder_unittest.cc | 1 | ||||
-rw-r--r-- | media/filters/fake_demuxer_stream.cc | 1 | ||||
-rw-r--r-- | media/filters/ffmpeg_demuxer.cc | 33 | ||||
-rw-r--r-- | media/mp4/mp4_stream_parser.cc | 3 | ||||
-rw-r--r-- | media/mp4/track_run_iterator.cc | 1 | ||||
-rw-r--r-- | media/webm/webm_cluster_parser.cc | 40 | ||||
-rw-r--r-- | media/webm/webm_cluster_parser_unittest.cc | 6 | ||||
-rw-r--r-- | media/webm/webm_crypto_helpers.cc | 18 | ||||
-rw-r--r-- | media/webm/webm_crypto_helpers.h | 19 |
17 files changed, 96 insertions, 118 deletions
diff --git a/media/base/decrypt_config.cc b/media/base/decrypt_config.cc index 53e2014..a478065 100644 --- a/media/base/decrypt_config.cc +++ b/media/base/decrypt_config.cc @@ -10,16 +10,13 @@ namespace media { DecryptConfig::DecryptConfig(const std::string& key_id, const std::string& iv, - const int data_offset, const std::vector<SubsampleEntry>& subsamples) : key_id_(key_id), iv_(iv), - data_offset_(data_offset), subsamples_(subsamples) { CHECK_GT(key_id.size(), 0u); CHECK(iv.size() == static_cast<size_t>(DecryptConfig::kDecryptionKeySize) || iv.empty()); - CHECK_GE(data_offset, 0); } DecryptConfig::~DecryptConfig() {} diff --git a/media/base/decrypt_config.h b/media/base/decrypt_config.h index be0bb4d..86480aa 100644 --- a/media/base/decrypt_config.h +++ b/media/base/decrypt_config.h @@ -38,23 +38,16 @@ class MEDIA_EXPORT DecryptConfig { // |iv| is the initialization vector defined by the encrypted format. // Currently |iv| must be 16 bytes as defined by WebM and ISO. Or must be // empty which signals an unencrypted frame. - // |data_offset| is the amount of data that should be discarded from the - // head of the sample buffer before applying subsample information. A - // decrypted buffer will be shorter than an encrypted buffer by this amount. // |subsamples| defines the clear and encrypted portions of the sample as // described above. A decrypted buffer will be equal in size to the sum // of the subsample sizes. - // - // |data_offset| is applied before |subsamples|. DecryptConfig(const std::string& key_id, const std::string& iv, - const int data_offset, const std::vector<SubsampleEntry>& subsamples); ~DecryptConfig(); const std::string& key_id() const { return key_id_; } const std::string& iv() const { return iv_; } - int data_offset() const { return data_offset_; } const std::vector<SubsampleEntry>& subsamples() const { return subsamples_; } private: @@ -63,11 +56,6 @@ class MEDIA_EXPORT DecryptConfig { // Initialization vector. const std::string iv_; - // TODO(fgalligan): Remove |data_offset_| if there is no plan to use it in - // the future. - // Amount of data to be discarded before applying subsample information. - const int data_offset_; - // Subsample information. May be empty for some formats, meaning entire frame // (less data ignored by data_offset_) is encrypted. const std::vector<SubsampleEntry> subsamples_; diff --git a/media/cdm/aes_decryptor.cc b/media/cdm/aes_decryptor.cc index de6f834..9f9f080 100644 --- a/media/cdm/aes_decryptor.cc +++ b/media/cdm/aes_decryptor.cc @@ -141,11 +141,8 @@ static scoped_refptr<DecoderBuffer> DecryptData(const DecoderBuffer& input, return NULL; } - const int data_offset = input.decrypt_config()->data_offset(); - const char* sample = - reinterpret_cast<const char*>(input.data() + data_offset); - DCHECK_GT(input.data_size(), data_offset); - size_t sample_size = static_cast<size_t>(input.data_size() - data_offset); + const char* sample = reinterpret_cast<const char*>(input.data()); + size_t sample_size = static_cast<size_t>(input.data_size()); DCHECK_GT(sample_size, 0U) << "No sample data to be decrypted."; if (sample_size == 0) @@ -333,9 +330,8 @@ void AesDecryptor::Decrypt(StreamType stream_type, scoped_refptr<DecoderBuffer> decrypted; // An empty iv string signals that the frame is unencrypted. if (encrypted->decrypt_config()->iv().empty()) { - int data_offset = encrypted->decrypt_config()->data_offset(); - decrypted = DecoderBuffer::CopyFrom(encrypted->data() + data_offset, - encrypted->data_size() - data_offset); + decrypted = DecoderBuffer::CopyFrom(encrypted->data(), + encrypted->data_size()); } else { const std::string& key_id = encrypted->decrypt_config()->key_id(); DecryptionKey* key = GetKey(key_id); diff --git a/media/cdm/aes_decryptor_unittest.cc b/media/cdm/aes_decryptor_unittest.cc index 3076d5a..8fb6a56 100644 --- a/media/cdm/aes_decryptor_unittest.cc +++ b/media/cdm/aes_decryptor_unittest.cc @@ -177,12 +177,10 @@ static scoped_refptr<DecoderBuffer> CreateEncryptedBuffer( const std::vector<uint8>& data, const std::vector<uint8>& key_id, const std::vector<uint8>& iv, - int offset, const std::vector<SubsampleEntry>& subsample_entries) { DCHECK(!data.empty()); - int padded_size = offset + data.size(); - scoped_refptr<DecoderBuffer> encrypted_buffer(new DecoderBuffer(padded_size)); - memcpy(encrypted_buffer->writable_data() + offset, &data[0], data.size()); + scoped_refptr<DecoderBuffer> encrypted_buffer(new DecoderBuffer(data.size())); + memcpy(encrypted_buffer->writable_data(), &data[0], data.size()); CHECK(encrypted_buffer.get()); std::string key_id_string( reinterpret_cast<const char*>(key_id.empty() ? NULL : &key_id[0]), @@ -190,7 +188,7 @@ static scoped_refptr<DecoderBuffer> CreateEncryptedBuffer( std::string iv_string( reinterpret_cast<const char*>(iv.empty() ? NULL : &iv[0]), iv.size()); encrypted_buffer->set_decrypt_config(scoped_ptr<DecryptConfig>( - new DecryptConfig(key_id_string, iv_string, offset, subsample_entries))); + new DecryptConfig(key_id_string, iv_string, subsample_entries))); return encrypted_buffer; } @@ -381,22 +379,14 @@ TEST_F(AesDecryptorTest, NormalDecryption) { uint32 session_id = CreateSession(key_id_); UpdateSessionAndExpect(session_id, kKeyAsJWK, SESSION_READY); scoped_refptr<DecoderBuffer> encrypted_buffer = CreateEncryptedBuffer( - encrypted_data_, key_id_, iv_, 0, no_subsample_entries_); - DecryptAndExpect(encrypted_buffer, original_data_, SUCCESS); -} - -TEST_F(AesDecryptorTest, DecryptionWithOffset) { - uint32 session_id = CreateSession(key_id_); - UpdateSessionAndExpect(session_id, kKeyAsJWK, SESSION_READY); - scoped_refptr<DecoderBuffer> encrypted_buffer = CreateEncryptedBuffer( - encrypted_data_, key_id_, iv_, 23, no_subsample_entries_); + encrypted_data_, key_id_, iv_, no_subsample_entries_); DecryptAndExpect(encrypted_buffer, original_data_, SUCCESS); } TEST_F(AesDecryptorTest, UnencryptedFrame) { // An empty iv string signals that the frame is unencrypted. scoped_refptr<DecoderBuffer> encrypted_buffer = CreateEncryptedBuffer( - original_data_, key_id_, std::vector<uint8>(), 0, no_subsample_entries_); + original_data_, key_id_, std::vector<uint8>(), no_subsample_entries_); DecryptAndExpect(encrypted_buffer, original_data_, SUCCESS); } @@ -404,13 +394,13 @@ TEST_F(AesDecryptorTest, WrongKey) { uint32 session_id = CreateSession(key_id_); UpdateSessionAndExpect(session_id, kWrongKeyAsJWK, SESSION_READY); scoped_refptr<DecoderBuffer> encrypted_buffer = CreateEncryptedBuffer( - encrypted_data_, key_id_, iv_, 0, no_subsample_entries_); + encrypted_data_, key_id_, iv_, no_subsample_entries_); DecryptAndExpect(encrypted_buffer, original_data_, DATA_MISMATCH); } TEST_F(AesDecryptorTest, NoKey) { scoped_refptr<DecoderBuffer> encrypted_buffer = CreateEncryptedBuffer( - encrypted_data_, key_id_, iv_, 0, no_subsample_entries_); + encrypted_data_, key_id_, iv_, no_subsample_entries_); EXPECT_CALL(*this, BufferDecrypted(AesDecryptor::kNoKey, IsNull())); decryptor_.Decrypt(Decryptor::kVideo, encrypted_buffer, decrypt_cb_); } @@ -418,7 +408,7 @@ TEST_F(AesDecryptorTest, NoKey) { TEST_F(AesDecryptorTest, KeyReplacement) { uint32 session_id = CreateSession(key_id_); scoped_refptr<DecoderBuffer> encrypted_buffer = CreateEncryptedBuffer( - encrypted_data_, key_id_, iv_, 0, no_subsample_entries_); + encrypted_data_, key_id_, iv_, no_subsample_entries_); UpdateSessionAndExpect(session_id, kWrongKeyAsJWK, SESSION_READY); ASSERT_NO_FATAL_FAILURE(DecryptAndExpect( @@ -438,7 +428,7 @@ TEST_F(AesDecryptorTest, MultipleKeysAndFrames) { uint32 session_id = CreateSession(key_id_); UpdateSessionAndExpect(session_id, kKeyAsJWK, SESSION_READY); scoped_refptr<DecoderBuffer> encrypted_buffer = CreateEncryptedBuffer( - encrypted_data_, key_id_, iv_, 10, no_subsample_entries_); + encrypted_data_, key_id_, iv_, no_subsample_entries_); ASSERT_NO_FATAL_FAILURE( DecryptAndExpect(encrypted_buffer, original_data_, SUCCESS)); @@ -454,7 +444,6 @@ TEST_F(AesDecryptorTest, MultipleKeysAndFrames) { kEncryptedData2 + arraysize(kEncryptedData2)), std::vector<uint8>(kKeyId2, kKeyId2 + arraysize(kKeyId2)), std::vector<uint8>(kIv2, kIv2 + arraysize(kIv2)), - 30, no_subsample_entries_); ASSERT_NO_FATAL_FAILURE(DecryptAndExpect( encrypted_buffer, @@ -471,7 +460,7 @@ TEST_F(AesDecryptorTest, CorruptedIv) { bad_iv[1]++; scoped_refptr<DecoderBuffer> encrypted_buffer = CreateEncryptedBuffer( - encrypted_data_, key_id_, bad_iv, 0, no_subsample_entries_); + encrypted_data_, key_id_, bad_iv, no_subsample_entries_); DecryptAndExpect(encrypted_buffer, original_data_, DATA_MISMATCH); } @@ -484,7 +473,7 @@ TEST_F(AesDecryptorTest, CorruptedData) { bad_data[1]++; scoped_refptr<DecoderBuffer> encrypted_buffer = CreateEncryptedBuffer( - bad_data, key_id_, iv_, 0, no_subsample_entries_); + bad_data, key_id_, iv_, no_subsample_entries_); DecryptAndExpect(encrypted_buffer, original_data_, DATA_MISMATCH); } @@ -492,7 +481,7 @@ TEST_F(AesDecryptorTest, EncryptedAsUnencryptedFailure) { uint32 session_id = CreateSession(key_id_); UpdateSessionAndExpect(session_id, kKeyAsJWK, SESSION_READY); scoped_refptr<DecoderBuffer> encrypted_buffer = CreateEncryptedBuffer( - encrypted_data_, key_id_, std::vector<uint8>(), 0, no_subsample_entries_); + encrypted_data_, key_id_, std::vector<uint8>(), no_subsample_entries_); DecryptAndExpect(encrypted_buffer, original_data_, DATA_MISMATCH); } @@ -500,7 +489,7 @@ TEST_F(AesDecryptorTest, SubsampleDecryption) { uint32 session_id = CreateSession(key_id_); UpdateSessionAndExpect(session_id, kKeyAsJWK, SESSION_READY); scoped_refptr<DecoderBuffer> encrypted_buffer = CreateEncryptedBuffer( - subsample_encrypted_data_, key_id_, iv_, 0, normal_subsample_entries_); + subsample_encrypted_data_, key_id_, iv_, normal_subsample_entries_); DecryptAndExpect(encrypted_buffer, original_data_, SUCCESS); } @@ -511,7 +500,7 @@ TEST_F(AesDecryptorTest, SubsampleDecryptionWithOffset) { uint32 session_id = CreateSession(key_id_); UpdateSessionAndExpect(session_id, kKeyAsJWK, SESSION_READY); scoped_refptr<DecoderBuffer> encrypted_buffer = CreateEncryptedBuffer( - subsample_encrypted_data_, key_id_, iv_, 23, normal_subsample_entries_); + subsample_encrypted_data_, key_id_, iv_, normal_subsample_entries_); DecryptAndExpect(encrypted_buffer, original_data_, SUCCESS); } @@ -524,7 +513,7 @@ TEST_F(AesDecryptorTest, SubsampleWrongSize) { kSubsampleEntriesWrongSize + arraysize(kSubsampleEntriesWrongSize)); scoped_refptr<DecoderBuffer> encrypted_buffer = CreateEncryptedBuffer( - subsample_encrypted_data_, key_id_, iv_, 0, subsample_entries_wrong_size); + subsample_encrypted_data_, key_id_, iv_, subsample_entries_wrong_size); DecryptAndExpect(encrypted_buffer, original_data_, DATA_MISMATCH); } @@ -538,7 +527,7 @@ TEST_F(AesDecryptorTest, SubsampleInvalidTotalSize) { arraysize(kSubsampleEntriesInvalidTotalSize)); scoped_refptr<DecoderBuffer> encrypted_buffer = CreateEncryptedBuffer( - subsample_encrypted_data_, key_id_, iv_, 0, + subsample_encrypted_data_, key_id_, iv_, subsample_entries_invalid_total_size); DecryptAndExpect(encrypted_buffer, original_data_, DECRYPT_ERROR); } @@ -553,7 +542,7 @@ TEST_F(AesDecryptorTest, SubsampleClearBytesOnly) { kSubsampleEntriesClearOnly + arraysize(kSubsampleEntriesClearOnly)); scoped_refptr<DecoderBuffer> encrypted_buffer = CreateEncryptedBuffer( - original_data_, key_id_, iv_, 0, clear_only_subsample_entries); + original_data_, key_id_, iv_, clear_only_subsample_entries); DecryptAndExpect(encrypted_buffer, original_data_, SUCCESS); } @@ -567,14 +556,14 @@ TEST_F(AesDecryptorTest, SubsampleCypherBytesOnly) { kSubsampleEntriesCypherOnly + arraysize(kSubsampleEntriesCypherOnly)); scoped_refptr<DecoderBuffer> encrypted_buffer = CreateEncryptedBuffer( - encrypted_data_, key_id_, iv_, 0, cypher_only_subsample_entries); + encrypted_data_, key_id_, iv_, cypher_only_subsample_entries); DecryptAndExpect(encrypted_buffer, original_data_, SUCCESS); } TEST_F(AesDecryptorTest, ReleaseSession) { uint32 session_id = CreateSession(key_id_); scoped_refptr<DecoderBuffer> encrypted_buffer = CreateEncryptedBuffer( - encrypted_data_, key_id_, iv_, 0, no_subsample_entries_); + encrypted_data_, key_id_, iv_, no_subsample_entries_); UpdateSessionAndExpect(session_id, kKeyAsJWK, SESSION_READY); ASSERT_NO_FATAL_FAILURE( @@ -586,7 +575,7 @@ TEST_F(AesDecryptorTest, ReleaseSession) { TEST_F(AesDecryptorTest, NoKeyAfterReleaseSession) { uint32 session_id = CreateSession(key_id_); scoped_refptr<DecoderBuffer> encrypted_buffer = CreateEncryptedBuffer( - encrypted_data_, key_id_, iv_, 0, no_subsample_entries_); + encrypted_data_, key_id_, iv_, no_subsample_entries_); UpdateSessionAndExpect(session_id, kKeyAsJWK, SESSION_READY); ASSERT_NO_FATAL_FAILURE( @@ -600,7 +589,7 @@ TEST_F(AesDecryptorTest, NoKeyAfterReleaseSession) { TEST_F(AesDecryptorTest, LatestKeyUsed) { uint32 session_id1 = CreateSession(key_id_); scoped_refptr<DecoderBuffer> encrypted_buffer = CreateEncryptedBuffer( - encrypted_data_, key_id_, iv_, 0, no_subsample_entries_); + encrypted_data_, key_id_, iv_, no_subsample_entries_); // Add alternate key, buffer should not be decoded properly. UpdateSessionAndExpect(session_id1, kKeyAlternateAsJWK, SESSION_READY); @@ -619,7 +608,7 @@ TEST_F(AesDecryptorTest, LatestKeyUsed) { TEST_F(AesDecryptorTest, LatestKeyUsedAfterReleaseSession) { uint32 session_id1 = CreateSession(key_id_); scoped_refptr<DecoderBuffer> encrypted_buffer = CreateEncryptedBuffer( - encrypted_data_, key_id_, iv_, 0, no_subsample_entries_); + encrypted_data_, key_id_, iv_, no_subsample_entries_); UpdateSessionAndExpect(session_id1, kKeyAsJWK, SESSION_READY); ASSERT_NO_FATAL_FAILURE( DecryptAndExpect(encrypted_buffer, original_data_, SUCCESS)); diff --git a/media/cdm/ppapi/external_clear_key/clear_key_cdm.cc b/media/cdm/ppapi/external_clear_key/clear_key_cdm.cc index a67eb2e..9dfea99 100644 --- a/media/cdm/ppapi/external_clear_key/clear_key_cdm.cc +++ b/media/cdm/ppapi/external_clear_key/clear_key_cdm.cc @@ -85,7 +85,7 @@ static scoped_refptr<media::DecoderBuffer> CopyDecoderBufferFrom( return media::DecoderBuffer::CreateEOSBuffer(); } - // TODO(tomfinegan): Get rid of this copy. + // TODO(xhwang): Get rid of this copy. scoped_refptr<media::DecoderBuffer> output_buffer = media::DecoderBuffer::CopyFrom(input_buffer.data, input_buffer.data_size); @@ -97,12 +97,12 @@ static scoped_refptr<media::DecoderBuffer> CopyDecoderBufferFrom( subsamples.push_back(subsample); } + DCHECK_EQ(input_buffer.data_offset, 0u); scoped_ptr<media::DecryptConfig> decrypt_config(new media::DecryptConfig( std::string(reinterpret_cast<const char*>(input_buffer.key_id), input_buffer.key_id_size), std::string(reinterpret_cast<const char*>(input_buffer.iv), input_buffer.iv_size), - input_buffer.data_offset, subsamples)); output_buffer->set_decrypt_config(decrypt_config.Pass()); diff --git a/media/filters/decrypting_audio_decoder_unittest.cc b/media/filters/decrypting_audio_decoder_unittest.cc index 2f07e23..20d1597 100644 --- a/media/filters/decrypting_audio_decoder_unittest.cc +++ b/media/filters/decrypting_audio_decoder_unittest.cc @@ -40,7 +40,6 @@ static scoped_refptr<DecoderBuffer> CreateFakeEncryptedBuffer() { std::string(reinterpret_cast<const char*>(kFakeKeyId), arraysize(kFakeKeyId)), std::string(reinterpret_cast<const char*>(kFakeIv), arraysize(kFakeIv)), - 0, std::vector<SubsampleEntry>()))); return buffer; } diff --git a/media/filters/decrypting_demuxer_stream.cc b/media/filters/decrypting_demuxer_stream.cc index 9610442..7ce5a9d 100644 --- a/media/filters/decrypting_demuxer_stream.cc +++ b/media/filters/decrypting_demuxer_stream.cc @@ -211,9 +211,8 @@ void DecryptingDemuxerStream::DecryptBuffer( // An empty iv string signals that the frame is unencrypted. if (buffer->decrypt_config()->iv().empty()) { DVLOG(2) << "DoDecryptBuffer() - clear buffer."; - int data_offset = buffer->decrypt_config()->data_offset(); scoped_refptr<DecoderBuffer> decrypted = DecoderBuffer::CopyFrom( - buffer->data() + data_offset, buffer->data_size() - data_offset); + buffer->data(), buffer->data_size()); decrypted->set_timestamp(buffer->timestamp()); decrypted->set_duration(buffer->duration()); state_ = kIdle; diff --git a/media/filters/decrypting_demuxer_stream_unittest.cc b/media/filters/decrypting_demuxer_stream_unittest.cc index 031ebe1..17a33425 100644 --- a/media/filters/decrypting_demuxer_stream_unittest.cc +++ b/media/filters/decrypting_demuxer_stream_unittest.cc @@ -38,7 +38,7 @@ static scoped_refptr<DecoderBuffer> CreateFakeEncryptedStreamBuffer( buffer->set_decrypt_config(scoped_ptr<DecryptConfig>(new DecryptConfig( std::string(reinterpret_cast<const char*>(kFakeKeyId), arraysize(kFakeKeyId)), - iv, 0, std::vector<SubsampleEntry>()))); + iv, std::vector<SubsampleEntry>()))); return buffer; } diff --git a/media/filters/decrypting_video_decoder_unittest.cc b/media/filters/decrypting_video_decoder_unittest.cc index 1d6296b..04b073f 100644 --- a/media/filters/decrypting_video_decoder_unittest.cc +++ b/media/filters/decrypting_video_decoder_unittest.cc @@ -37,7 +37,6 @@ static scoped_refptr<DecoderBuffer> CreateFakeEncryptedBuffer() { std::string(reinterpret_cast<const char*>(kFakeKeyId), arraysize(kFakeKeyId)), std::string(reinterpret_cast<const char*>(kFakeIv), arraysize(kFakeIv)), - 0, std::vector<SubsampleEntry>()))); return buffer; } diff --git a/media/filters/fake_demuxer_stream.cc b/media/filters/fake_demuxer_stream.cc index ab0e025..69626e9 100644 --- a/media/filters/fake_demuxer_stream.cc +++ b/media/filters/fake_demuxer_stream.cc @@ -151,7 +151,6 @@ void FakeDemuxerStream::DoRead() { buffer->set_decrypt_config(scoped_ptr<DecryptConfig>( new DecryptConfig(std::string(kKeyId, kKeyId + arraysize(kKeyId)), std::string(kIv, kIv + arraysize(kIv)), - 0, std::vector<SubsampleEntry>()))); } buffer->set_timestamp(current_timestamp_); diff --git a/media/filters/ffmpeg_demuxer.cc b/media/filters/ffmpeg_demuxer.cc index ae0d604..f181993 100644 --- a/media/filters/ffmpeg_demuxer.cc +++ b/media/filters/ffmpeg_demuxer.cc @@ -116,6 +116,7 @@ void FFmpegDemuxerStream::EnqueuePacket(ScopedAVPacket packet) { // keep this generic so that other side_data types in the future can be // handled the same way as well. av_packet_split_side_data(packet.get()); + scoped_refptr<DecoderBuffer> buffer; if (type() == DemuxerStream::TEXT) { @@ -145,14 +146,30 @@ void FFmpegDemuxerStream::EnqueuePacket(ScopedAVPacket packet) { AV_PKT_DATA_MATROSKA_BLOCKADDITIONAL, &side_data_size); + scoped_ptr<DecryptConfig> decrypt_config; + int data_offset = 0; + if ((type() == DemuxerStream::AUDIO && audio_config_.is_encrypted()) || + (type() == DemuxerStream::VIDEO && video_config_.is_encrypted())) { + if (!WebMCreateDecryptConfig( + packet->data, packet->size, + reinterpret_cast<const uint8*>(encryption_key_id_.data()), + encryption_key_id_.size(), + &decrypt_config, + &data_offset)) { + LOG(ERROR) << "Creation of DecryptConfig failed."; + } + } + // If a packet is returned by FFmpeg's av_parser_parse2() the packet will // reference inner memory of FFmpeg. As such we should transfer the packet // into memory we control. if (side_data_size > 0) { - buffer = DecoderBuffer::CopyFrom(packet.get()->data, packet.get()->size, + buffer = DecoderBuffer::CopyFrom(packet.get()->data + data_offset, + packet.get()->size - data_offset, side_data, side_data_size); } else { - buffer = DecoderBuffer::CopyFrom(packet.get()->data, packet.get()->size); + buffer = DecoderBuffer::CopyFrom(packet.get()->data + data_offset, + packet.get()->size - data_offset); } int skip_samples_size = 0; @@ -171,17 +188,9 @@ void FFmpegDemuxerStream::EnqueuePacket(ScopedAVPacket packet) { discard_padding_samples * 1000000.0 / audio_decoder_config().samples_per_second())); } - } - if ((type() == DemuxerStream::AUDIO && audio_config_.is_encrypted()) || - (type() == DemuxerStream::VIDEO && video_config_.is_encrypted())) { - scoped_ptr<DecryptConfig> config(WebMCreateDecryptConfig( - packet->data, packet->size, - reinterpret_cast<const uint8*>(encryption_key_id_.data()), - encryption_key_id_.size())); - if (!config) - LOG(ERROR) << "Creation of DecryptConfig failed."; - buffer->set_decrypt_config(config.Pass()); + if (decrypt_config) + buffer->set_decrypt_config(decrypt_config.Pass()); } buffer->set_timestamp(ConvertStreamTimestamp( diff --git a/media/mp4/mp4_stream_parser.cc b/media/mp4/mp4_stream_parser.cc index db1b59b..62cc751 100644 --- a/media/mp4/mp4_stream_parser.cc +++ b/media/mp4/mp4_stream_parser.cc @@ -493,7 +493,6 @@ bool MP4StreamParser::EnqueueSample(BufferQueue* audio_buffers, decrypt_config.reset(new DecryptConfig( decrypt_config->key_id(), decrypt_config->iv(), - decrypt_config->data_offset(), subsamples)); } // else, use the existing config. @@ -502,7 +501,7 @@ bool MP4StreamParser::EnqueueSample(BufferQueue* audio_buffers, // The media pipeline requires a DecryptConfig with an empty |iv|. // TODO(ddorwin): Refactor so we do not need a fake key ID ("1"); decrypt_config.reset( - new DecryptConfig("1", "", 0, std::vector<SubsampleEntry>())); + new DecryptConfig("1", "", std::vector<SubsampleEntry>())); } scoped_refptr<StreamParserBuffer> stream_buf = diff --git a/media/mp4/track_run_iterator.cc b/media/mp4/track_run_iterator.cc index 4dbd14f..2fbf271 100644 --- a/media/mp4/track_run_iterator.cc +++ b/media/mp4/track_run_iterator.cc @@ -451,7 +451,6 @@ scoped_ptr<DecryptConfig> TrackRunIterator::GetDecryptConfig() { std::string(reinterpret_cast<const char*>(&kid[0]), kid.size()), std::string(reinterpret_cast<const char*>(cenc_info.iv), arraysize(cenc_info.iv)), - 0, // No offset to start of media data in MP4 using CENC. cenc_info.subsamples)); } diff --git a/media/webm/webm_cluster_parser.cc b/media/webm/webm_cluster_parser.cc index df9e4ce2..4ac888d 100644 --- a/media/webm/webm_cluster_parser.cc +++ b/media/webm/webm_cluster_parser.cc @@ -345,13 +345,30 @@ bool WebMClusterParser::OnBlock(bool is_simple_block, int track_num, scoped_refptr<StreamParserBuffer> buffer; if (!is_text) { - buffer = StreamParserBuffer::CopyFrom(data, size, - additional, additional_size, - is_keyframe); + // Every encrypted Block has a signal byte and IV prepended to it. Current + // encrypted WebM request for comments specification is here + // http://wiki.webmproject.org/encryption/webm-encryption-rfc + scoped_ptr<DecryptConfig> decrypt_config; + int data_offset = 0; + if (!encryption_key_id.empty() && + !WebMCreateDecryptConfig( + data, size, + reinterpret_cast<const uint8*>(encryption_key_id.data()), + encryption_key_id.size(), + &decrypt_config, &data_offset)) { + return false; + } + + buffer = StreamParserBuffer::CopyFrom( + data + data_offset, size - data_offset, + additional, additional_size, + is_keyframe); + + if (decrypt_config) + buffer->set_decrypt_config(decrypt_config.Pass()); } else { std::string id, settings, content; - WebMWebVTTParser::Parse(data, size, - &id, &settings, &content); + WebMWebVTTParser::Parse(data, size, &id, &settings, &content); std::vector<uint8> side_data; MakeSideData(id.begin(), id.end(), @@ -366,19 +383,6 @@ bool WebMClusterParser::OnBlock(bool is_simple_block, int track_num, is_keyframe); } - // Every encrypted Block has a signal byte and IV prepended to it. Current - // encrypted WebM request for comments specification is here - // http://wiki.webmproject.org/encryption/webm-encryption-rfc - if (!encryption_key_id.empty()) { - scoped_ptr<DecryptConfig> config(WebMCreateDecryptConfig( - data, size, - reinterpret_cast<const uint8*>(encryption_key_id.data()), - encryption_key_id.size())); - if (!config) - return false; - buffer->set_decrypt_config(config.Pass()); - } - buffer->set_timestamp(timestamp); if (cluster_start_time_ == kNoTimestamp()) cluster_start_time_ = timestamp; diff --git a/media/webm/webm_cluster_parser_unittest.cc b/media/webm/webm_cluster_parser_unittest.cc index 691325d..865a274 100644 --- a/media/webm/webm_cluster_parser_unittest.cc +++ b/media/webm/webm_cluster_parser_unittest.cc @@ -183,13 +183,11 @@ static bool VerifyTextBuffers( return true; } -static bool VerifyEncryptedBuffer( +static void VerifyEncryptedBuffer( scoped_refptr<StreamParserBuffer> buffer) { EXPECT_TRUE(buffer->decrypt_config()); EXPECT_EQ(static_cast<unsigned long>(DecryptConfig::kDecryptionKeySize), buffer->decrypt_config()->iv().length()); - const uint8* data = buffer->data(); - return data[0] & kWebMFlagEncryptedFrame; } static void AppendToEnd(const WebMClusterParser::BufferQueue& src, @@ -508,7 +506,7 @@ TEST_F(WebMClusterParserTest, ParseEncryptedBlock) { EXPECT_EQ(cluster->size(), result); ASSERT_EQ(1UL, parser_->video_buffers().size()); scoped_refptr<StreamParserBuffer> buffer = parser_->video_buffers()[0]; - EXPECT_TRUE(VerifyEncryptedBuffer(buffer)); + VerifyEncryptedBuffer(buffer); } TEST_F(WebMClusterParserTest, ParseBadEncryptedBlock) { diff --git a/media/webm/webm_crypto_helpers.cc b/media/webm/webm_crypto_helpers.cc index a663f3c..d6af43f 100644 --- a/media/webm/webm_crypto_helpers.cc +++ b/media/webm/webm_crypto_helpers.cc @@ -24,12 +24,13 @@ std::string GenerateWebMCounterBlock(const uint8* iv, int iv_size) { } // namespace anonymous -scoped_ptr<DecryptConfig> WebMCreateDecryptConfig( - const uint8* data, int data_size, - const uint8* key_id, int key_id_size) { +bool WebMCreateDecryptConfig(const uint8* data, int data_size, + const uint8* key_id, int key_id_size, + scoped_ptr<DecryptConfig>* decrypt_config, + int* data_offset) { if (data_size < kWebMSignalByteSize) { DVLOG(1) << "Got a block from an encrypted stream with no data."; - return scoped_ptr<DecryptConfig>(); + return false; } uint8 signal_byte = data[0]; @@ -43,18 +44,19 @@ scoped_ptr<DecryptConfig> WebMCreateDecryptConfig( if (signal_byte & kWebMFlagEncryptedFrame) { if (data_size < kWebMSignalByteSize + kWebMIvSize) { DVLOG(1) << "Got an encrypted block with not enough data " << data_size; - return scoped_ptr<DecryptConfig>(); + return false; } counter_block = GenerateWebMCounterBlock(data + frame_offset, kWebMIvSize); frame_offset += kWebMIvSize; } - scoped_ptr<DecryptConfig> config(new DecryptConfig( + decrypt_config->reset(new DecryptConfig( std::string(reinterpret_cast<const char*>(key_id), key_id_size), counter_block, - frame_offset, std::vector<SubsampleEntry>())); - return config.Pass(); + *data_offset = frame_offset; + + return true; } } // namespace media diff --git a/media/webm/webm_crypto_helpers.h b/media/webm/webm_crypto_helpers.h index c5f1f15..086d745 100644 --- a/media/webm/webm_crypto_helpers.h +++ b/media/webm/webm_crypto_helpers.h @@ -16,16 +16,17 @@ namespace media { // information. const char kWebMEncryptInitDataType[] = "video/webm"; -// Returns an initialized DecryptConfig, which can be sent to the Decryptor if -// the stream has potentially encrypted frames. Every encrypted Block has a -// signal byte, and if the frame is encrypted, an initialization vector -// prepended to the frame. Leaving the IV empty will tell the decryptor that the -// frame is unencrypted. Returns NULL if |data| is invalid. Current encrypted -// WebM request for comments specification is here +// Fills an initialized DecryptConfig, which can be sent to the Decryptor if +// the stream has potentially encrypted frames. Also sets |data_offset| which +// indicates where the encrypted data starts. Leaving the IV empty will tell +// the decryptor that the frame is unencrypted. Returns true if |data| is valid, +// false otherwise, in which case |decrypt_config| and |data_offset| will not be +// changed. Current encrypted WebM request for comments specification is here // http://wiki.webmproject.org/encryption/webm-encryption-rfc -scoped_ptr<DecryptConfig> WebMCreateDecryptConfig( - const uint8* data, int data_size, - const uint8* key_id, int key_id_size); +bool WebMCreateDecryptConfig(const uint8* data, int data_size, + const uint8* key_id, int key_id_size, + scoped_ptr<DecryptConfig>* decrypt_config, + int* data_offset); } // namespace media |