diff options
author | dougsteed <dougsteed@chromium.org> | 2016-03-11 16:04:30 -0800 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2016-03-12 00:05:22 +0000 |
commit | 8d5275f7bbb6f79c83829a7931f1500128ef3f8f (patch) | |
tree | 06d53aa908b22da47f819afbf815aa941f709ef9 /media | |
parent | c5bf1a9a84aadcf927f94e806f4647d65e3da2c1 (diff) | |
download | chromium_src-8d5275f7bbb6f79c83829a7931f1500128ef3f8f.zip chromium_src-8d5275f7bbb6f79c83829a7931f1500128ef3f8f.tar.gz chromium_src-8d5275f7bbb6f79c83829a7931f1500128ef3f8f.tar.bz2 |
media config: expand is_encrypted to a struct.
Provide more complete encryption metadata, rather than
just a bool. EncryptionScheme also allows specification
of the mode and the pattern, as will be allowed by
CENC (ISO's Common Encryption standard), 3rd Edition.
BUG=568326
Committed: https://crrev.com/c9d2206c62f65e29b141e08df2b2dcb88f54162f
Cr-Commit-Position: refs/heads/master@{#380710}
Review URL: https://codereview.chromium.org/1490613005
Cr-Commit-Position: refs/heads/master@{#380791}
Diffstat (limited to 'media')
43 files changed, 467 insertions, 217 deletions
diff --git a/media/base/BUILD.gn b/media/base/BUILD.gn index ef69b2d..21f5449 100644 --- a/media/base/BUILD.gn +++ b/media/base/BUILD.gn @@ -113,6 +113,8 @@ source_set("base") { "djb2.cc", "djb2.h", "eme_constants.h", + "encryption_scheme.cc", + "encryption_scheme.h", "key_system_info.cc", "key_system_info.h", "key_systems.cc", diff --git a/media/base/audio_decoder_config.cc b/media/base/audio_decoder_config.cc index 3c1b94d..253c82b 100644 --- a/media/base/audio_decoder_config.cc +++ b/media/base/audio_decoder_config.cc @@ -16,18 +16,17 @@ AudioDecoderConfig::AudioDecoderConfig() channel_layout_(CHANNEL_LAYOUT_UNSUPPORTED), samples_per_second_(0), bytes_per_frame_(0), - is_encrypted_(false), - codec_delay_(0) { -} + codec_delay_(0) {} -AudioDecoderConfig::AudioDecoderConfig(AudioCodec codec, - SampleFormat sample_format, - ChannelLayout channel_layout, - int samples_per_second, - const std::vector<uint8_t>& extra_data, - bool is_encrypted) { +AudioDecoderConfig::AudioDecoderConfig( + AudioCodec codec, + SampleFormat sample_format, + ChannelLayout channel_layout, + int samples_per_second, + const std::vector<uint8_t>& extra_data, + const EncryptionScheme& encryption_scheme) { Initialize(codec, sample_format, channel_layout, samples_per_second, - extra_data, is_encrypted, base::TimeDelta(), 0); + extra_data, encryption_scheme, base::TimeDelta(), 0); } AudioDecoderConfig::AudioDecoderConfig(const AudioDecoderConfig& other) = @@ -38,7 +37,7 @@ void AudioDecoderConfig::Initialize(AudioCodec codec, ChannelLayout channel_layout, int samples_per_second, const std::vector<uint8_t>& extra_data, - bool is_encrypted, + const EncryptionScheme& encryption_scheme, base::TimeDelta seek_preroll, int codec_delay) { codec_ = codec; @@ -47,7 +46,7 @@ void AudioDecoderConfig::Initialize(AudioCodec codec, sample_format_ = sample_format; bytes_per_channel_ = SampleFormatToBytesPerChannel(sample_format); extra_data_ = extra_data; - is_encrypted_ = is_encrypted; + encryption_scheme_ = encryption_scheme; seek_preroll_ = seek_preroll; codec_delay_ = codec_delay; @@ -75,7 +74,7 @@ bool AudioDecoderConfig::Matches(const AudioDecoderConfig& config) const { (channel_layout() == config.channel_layout()) && (samples_per_second() == config.samples_per_second()) && (extra_data() == config.extra_data()) && - (is_encrypted() == config.is_encrypted()) && + (encryption_scheme().Matches(config.encryption_scheme())) && (sample_format() == config.sample_format()) && (seek_preroll() == config.seek_preroll()) && (codec_delay() == config.codec_delay())); diff --git a/media/base/audio_decoder_config.h b/media/base/audio_decoder_config.h index 71c8930..266de82 100644 --- a/media/base/audio_decoder_config.h +++ b/media/base/audio_decoder_config.h @@ -14,6 +14,7 @@ #include "base/time/time.h" #include "media/base/audio_codecs.h" #include "media/base/channel_layout.h" +#include "media/base/encryption_scheme.h" #include "media/base/media_export.h" #include "media/base/sample_format.h" @@ -34,7 +35,7 @@ class MEDIA_EXPORT AudioDecoderConfig { ChannelLayout channel_layout, int samples_per_second, const std::vector<uint8_t>& extra_data, - bool is_encrypted); + const EncryptionScheme& encryption_scheme); AudioDecoderConfig(const AudioDecoderConfig& other); @@ -46,7 +47,7 @@ class MEDIA_EXPORT AudioDecoderConfig { ChannelLayout channel_layout, int samples_per_second, const std::vector<uint8_t>& extra_data, - bool is_encrypted, + const EncryptionScheme& encryption_scheme, base::TimeDelta seek_preroll, int codec_delay); @@ -79,7 +80,12 @@ class MEDIA_EXPORT AudioDecoderConfig { // Whether the audio stream is potentially encrypted. // Note that in a potentially encrypted audio stream, individual buffers // can be encrypted or not encrypted. - bool is_encrypted() const { return is_encrypted_; } + bool is_encrypted() const { return encryption_scheme_.is_encrypted(); } + + // Encryption scheme used for encrypted buffers. + const EncryptionScheme& encryption_scheme() const { + return encryption_scheme_; + } private: AudioCodec codec_; @@ -89,7 +95,7 @@ class MEDIA_EXPORT AudioDecoderConfig { int samples_per_second_; int bytes_per_frame_; std::vector<uint8_t> extra_data_; - bool is_encrypted_; + EncryptionScheme encryption_scheme_; // |seek_preroll_| is the duration of the data that the decoder must decode // before the decoded data is valid. diff --git a/media/base/encryption_scheme.cc b/media/base/encryption_scheme.cc new file mode 100644 index 0000000..70d133c --- /dev/null +++ b/media/base/encryption_scheme.cc @@ -0,0 +1,37 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "media/base/encryption_scheme.h" + +namespace media { + +EncryptionScheme::Pattern::Pattern() {} + +EncryptionScheme::Pattern::Pattern(uint32_t encrypt_blocks, + uint32_t skip_blocks) + : encrypt_blocks_(encrypt_blocks), skip_blocks_(skip_blocks) {} + +EncryptionScheme::Pattern::~Pattern() {} + +bool EncryptionScheme::Pattern::Matches(const Pattern& other) const { + return encrypt_blocks_ == other.encrypt_blocks() && + skip_blocks_ == other.skip_blocks(); +} + +bool EncryptionScheme::Pattern::IsInEffect() const { + return encrypt_blocks_ != 0 && skip_blocks_ != 0; +} + +EncryptionScheme::EncryptionScheme() {} + +EncryptionScheme::EncryptionScheme(CipherMode mode, const Pattern& pattern) + : mode_(mode), pattern_(pattern) {} + +EncryptionScheme::~EncryptionScheme() {} + +bool EncryptionScheme::Matches(const EncryptionScheme& other) const { + return mode_ == other.mode_ && pattern_.Matches(other.pattern_); +} + +} // namespace media diff --git a/media/base/encryption_scheme.h b/media/base/encryption_scheme.h new file mode 100644 index 0000000..37bea67 --- /dev/null +++ b/media/base/encryption_scheme.h @@ -0,0 +1,79 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef MEDIA_BASE_ENCRYPTION_SCHEME_H_ +#define MEDIA_BASE_ENCRYPTION_SCHEME_H_ + +#include <stdint.h> + +#include "media/base/media_export.h" + +namespace media { + +// Specification of whether and how the stream is encrypted (in whole or part). +class MEDIA_EXPORT EncryptionScheme { + public: + // Algorithm and mode used for encryption. CIPHER_MODE_UNENCRYPTED indicates + // no encryption. + enum CipherMode { + CIPHER_MODE_UNENCRYPTED, + CIPHER_MODE_AES_CTR, + CIPHER_MODE_AES_CBC, + CIPHER_MODE_MAX = CIPHER_MODE_AES_CBC + }; + + // CENC 3rd Edition adds pattern encryption, through two new protection + // schemes: 'cens' (with AES-CTR) and 'cbcs' (with AES-CBC). + // The pattern applies independently to each 'encrypted' part of the frame (as + // defined by the relevant subsample entries), and reduces further the + // actual encryption applied through a repeating pattern of (encrypt:skip) + // 16 byte blocks. For example, in a (1:9) pattern, the first block is + // encrypted, and the next nine are skipped. This pattern is applied + // repeatedly until the end of the last 16-byte block in the subsample. + // Any remaining bytes are left clear. + // If either of encrypt_blocks or skip_blocks is 0, pattern encryption is + // disabled. + class MEDIA_EXPORT Pattern { + public: + Pattern(); + Pattern(uint32_t encrypt_blocks, uint32_t skip_blocks); + ~Pattern(); + + bool Matches(const Pattern& other) const; + + uint32_t encrypt_blocks() const { return encrypt_blocks_; } + uint32_t skip_blocks() const { return skip_blocks_; } + + bool IsInEffect() const; + + private: + uint32_t encrypt_blocks_ = 0; + uint32_t skip_blocks_ = 0; + + // Allow copy and assignment. + }; + + // The default constructor makes an instance that indicates no encryption. + EncryptionScheme(); + + // This constructor allows specification of the cipher mode and the pattern. + EncryptionScheme(CipherMode mode, const Pattern& pattern); + ~EncryptionScheme(); + + bool Matches(const EncryptionScheme& other) const; + + bool is_encrypted() const { return mode_ != CIPHER_MODE_UNENCRYPTED; } + CipherMode mode() const { return mode_; } + const Pattern& pattern() const { return pattern_; } + + private: + CipherMode mode_ = CIPHER_MODE_UNENCRYPTED; + Pattern pattern_; + + // Allow copy and assignment. +}; + +} // namespace media + +#endif // MEDIA_BASE_ENCRYPTION_SCHEME_H_ diff --git a/media/base/fake_demuxer_stream.cc b/media/base/fake_demuxer_stream.cc index 267b3e5..7ed5841 100644 --- a/media/base/fake_demuxer_stream.cc +++ b/media/base/fake_demuxer_stream.cc @@ -147,11 +147,11 @@ void FakeDemuxerStream::SeekToStart() { void FakeDemuxerStream::UpdateVideoDecoderConfig() { const gfx::Rect kVisibleRect(kStartWidth, kStartHeight); - video_decoder_config_.Initialize(kCodecVP8, VIDEO_CODEC_PROFILE_UNKNOWN, - PIXEL_FORMAT_YV12, COLOR_SPACE_UNSPECIFIED, - next_coded_size_, kVisibleRect, - next_coded_size_, EmptyExtraData(), - is_encrypted_); + video_decoder_config_.Initialize( + kCodecVP8, VIDEO_CODEC_PROFILE_UNKNOWN, PIXEL_FORMAT_YV12, + COLOR_SPACE_UNSPECIFIED, next_coded_size_, kVisibleRect, next_coded_size_, + EmptyExtraData(), + is_encrypted_ ? AesCtrEncryptionScheme() : Unencrypted()); next_coded_size_.Enlarge(kWidthDelta, kHeightDelta); } diff --git a/media/base/media_util.cc b/media/base/media_util.cc index bd7929f..a6516cd2 100644 --- a/media/base/media_util.cc +++ b/media/base/media_util.cc @@ -10,4 +10,13 @@ std::vector<uint8_t> EmptyExtraData() { return std::vector<uint8_t>(); } +EncryptionScheme Unencrypted() { + return EncryptionScheme(); +} + +EncryptionScheme AesCtrEncryptionScheme() { + return EncryptionScheme(EncryptionScheme::CIPHER_MODE_AES_CTR, + EncryptionScheme::Pattern()); +} + } // namespace media diff --git a/media/base/media_util.h b/media/base/media_util.h index 4e53c9a..c7ddc8b 100644 --- a/media/base/media_util.h +++ b/media/base/media_util.h @@ -8,6 +8,7 @@ #include <stdint.h> #include <vector> +#include "media/base/encryption_scheme.h" #include "media/base/media_export.h" namespace media { @@ -16,6 +17,11 @@ namespace media { // constructed with empty extra data. MEDIA_EXPORT std::vector<uint8_t> EmptyExtraData(); +// The following helper functions return new instances of EncryptionScheme that +// indicate widely used settings. +MEDIA_EXPORT EncryptionScheme Unencrypted(); +MEDIA_EXPORT EncryptionScheme AesCtrEncryptionScheme(); + } // namespace media #endif // MEDIA_BASE_UTIL_H_ diff --git a/media/base/test_helpers.cc b/media/base/test_helpers.cc index c38f629..0ab1903 100644 --- a/media/base/test_helpers.cc +++ b/media/base/test_helpers.cc @@ -129,10 +129,11 @@ static VideoDecoderConfig GetTestConfig(VideoCodec codec, gfx::Rect visible_rect(coded_size.width(), coded_size.height()); gfx::Size natural_size = coded_size; - return VideoDecoderConfig(codec, VIDEO_CODEC_PROFILE_UNKNOWN, - PIXEL_FORMAT_YV12, COLOR_SPACE_UNSPECIFIED, - coded_size, visible_rect, natural_size, - EmptyExtraData(), is_encrypted); + return VideoDecoderConfig( + codec, VIDEO_CODEC_PROFILE_UNKNOWN, PIXEL_FORMAT_YV12, + COLOR_SPACE_UNSPECIFIED, coded_size, visible_rect, natural_size, + EmptyExtraData(), + is_encrypted ? AesCtrEncryptionScheme() : Unencrypted()); } static const gfx::Size kNormalSize(320, 240); diff --git a/media/base/video_decoder_config.cc b/media/base/video_decoder_config.cc index 930ffd9..a0edb40 100644 --- a/media/base/video_decoder_config.cc +++ b/media/base/video_decoder_config.cc @@ -39,20 +39,20 @@ VideoCodec VideoCodecProfileToVideoCodec(VideoCodecProfile profile) { VideoDecoderConfig::VideoDecoderConfig() : codec_(kUnknownVideoCodec), profile_(VIDEO_CODEC_PROFILE_UNKNOWN), - format_(PIXEL_FORMAT_UNKNOWN), - is_encrypted_(false) {} + format_(PIXEL_FORMAT_UNKNOWN) {} -VideoDecoderConfig::VideoDecoderConfig(VideoCodec codec, - VideoCodecProfile profile, - VideoPixelFormat format, - ColorSpace color_space, - const gfx::Size& coded_size, - const gfx::Rect& visible_rect, - const gfx::Size& natural_size, - const std::vector<uint8_t>& extra_data, - bool is_encrypted) { +VideoDecoderConfig::VideoDecoderConfig( + VideoCodec codec, + VideoCodecProfile profile, + VideoPixelFormat format, + ColorSpace color_space, + const gfx::Size& coded_size, + const gfx::Rect& visible_rect, + const gfx::Size& natural_size, + const std::vector<uint8_t>& extra_data, + const EncryptionScheme& encryption_scheme) { Initialize(codec, profile, format, color_space, coded_size, visible_rect, - natural_size, extra_data, is_encrypted); + natural_size, extra_data, encryption_scheme); } VideoDecoderConfig::VideoDecoderConfig(const VideoDecoderConfig& other) = @@ -68,7 +68,7 @@ void VideoDecoderConfig::Initialize(VideoCodec codec, const gfx::Rect& visible_rect, const gfx::Size& natural_size, const std::vector<uint8_t>& extra_data, - bool is_encrypted) { + const EncryptionScheme& encryption_scheme) { codec_ = codec; profile_ = profile; format_ = format; @@ -77,7 +77,7 @@ void VideoDecoderConfig::Initialize(VideoCodec codec, visible_rect_ = visible_rect; natural_size_ = natural_size; extra_data_ = extra_data; - is_encrypted_ = is_encrypted; + encryption_scheme_ = encryption_scheme; } bool VideoDecoderConfig::IsValidConfig() const { @@ -89,14 +89,13 @@ bool VideoDecoderConfig::IsValidConfig() const { } bool VideoDecoderConfig::Matches(const VideoDecoderConfig& config) const { - return ((codec() == config.codec()) && - (format() == config.format()) && + return ((codec() == config.codec()) && (format() == config.format()) && (profile() == config.profile()) && (coded_size() == config.coded_size()) && (visible_rect() == config.visible_rect()) && (natural_size() == config.natural_size()) && (extra_data() == config.extra_data()) && - (is_encrypted() == config.is_encrypted())); + (encryption_scheme().Matches(config.encryption_scheme()))); } std::string VideoDecoderConfig::AsHumanReadableString() const { diff --git a/media/base/video_decoder_config.h b/media/base/video_decoder_config.h index 4a192d6..50dee06 100644 --- a/media/base/video_decoder_config.h +++ b/media/base/video_decoder_config.h @@ -11,6 +11,7 @@ #include <vector> #include "base/macros.h" +#include "media/base/encryption_scheme.h" #include "media/base/media_export.h" #include "media/base/video_codecs.h" #include "media/base/video_types.h" @@ -38,7 +39,7 @@ class MEDIA_EXPORT VideoDecoderConfig { const gfx::Rect& visible_rect, const gfx::Size& natural_size, const std::vector<uint8_t>& extra_data, - bool is_encrypted); + const EncryptionScheme& encryption_scheme); VideoDecoderConfig(const VideoDecoderConfig& other); @@ -53,7 +54,7 @@ class MEDIA_EXPORT VideoDecoderConfig { const gfx::Rect& visible_rect, const gfx::Size& natural_size, const std::vector<uint8_t>& extra_data, - bool is_encrypted); + const EncryptionScheme& encryption_scheme); // Returns true if this object has appropriate configuration values, false // otherwise. @@ -100,7 +101,12 @@ class MEDIA_EXPORT VideoDecoderConfig { // Whether the video stream is potentially encrypted. // Note that in a potentially encrypted video stream, individual buffers // can be encrypted or not encrypted. - bool is_encrypted() const { return is_encrypted_; } + bool is_encrypted() const { return encryption_scheme_.is_encrypted(); } + + // Encryption scheme used for encrypted buffers. + const EncryptionScheme& encryption_scheme() const { + return encryption_scheme_; + } private: VideoCodec codec_; @@ -115,7 +121,7 @@ class MEDIA_EXPORT VideoDecoderConfig { std::vector<uint8_t> extra_data_; - bool is_encrypted_; + EncryptionScheme encryption_scheme_; // Not using DISALLOW_COPY_AND_ASSIGN here intentionally to allow the compiler // generated copy constructor and assignment operator. Since the extra data is diff --git a/media/base/video_decoder_config_unittest.cc b/media/base/video_decoder_config_unittest.cc index 7885c8f..1852833 100644 --- a/media/base/video_decoder_config_unittest.cc +++ b/media/base/video_decoder_config_unittest.cc @@ -19,7 +19,7 @@ TEST(VideoDecoderConfigTest, Invalid_UnsupportedPixelFormat) { VideoDecoderConfig config(kCodecVP8, VIDEO_CODEC_PROFILE_UNKNOWN, PIXEL_FORMAT_UNKNOWN, COLOR_SPACE_UNSPECIFIED, kCodedSize, kVisibleRect, kNaturalSize, - EmptyExtraData(), false); + EmptyExtraData(), Unencrypted()); EXPECT_FALSE(config.IsValidConfig()); } @@ -27,7 +27,7 @@ TEST(VideoDecoderConfigTest, Invalid_AspectRatioNumeratorZero) { gfx::Size natural_size = GetNaturalSize(kVisibleRect.size(), 0, 1); VideoDecoderConfig config(kCodecVP8, VP8PROFILE_ANY, kVideoFormat, COLOR_SPACE_UNSPECIFIED, kCodedSize, kVisibleRect, - natural_size, EmptyExtraData(), false); + natural_size, EmptyExtraData(), Unencrypted()); EXPECT_FALSE(config.IsValidConfig()); } @@ -35,7 +35,7 @@ TEST(VideoDecoderConfigTest, Invalid_AspectRatioDenominatorZero) { gfx::Size natural_size = GetNaturalSize(kVisibleRect.size(), 1, 0); VideoDecoderConfig config(kCodecVP8, VP8PROFILE_ANY, kVideoFormat, COLOR_SPACE_UNSPECIFIED, kCodedSize, kVisibleRect, - natural_size, EmptyExtraData(), false); + natural_size, EmptyExtraData(), Unencrypted()); EXPECT_FALSE(config.IsValidConfig()); } @@ -43,7 +43,7 @@ TEST(VideoDecoderConfigTest, Invalid_AspectRatioNumeratorNegative) { gfx::Size natural_size = GetNaturalSize(kVisibleRect.size(), -1, 1); VideoDecoderConfig config(kCodecVP8, VP8PROFILE_ANY, kVideoFormat, COLOR_SPACE_UNSPECIFIED, kCodedSize, kVisibleRect, - natural_size, EmptyExtraData(), false); + natural_size, EmptyExtraData(), Unencrypted()); EXPECT_FALSE(config.IsValidConfig()); } @@ -51,7 +51,7 @@ TEST(VideoDecoderConfigTest, Invalid_AspectRatioDenominatorNegative) { gfx::Size natural_size = GetNaturalSize(kVisibleRect.size(), 1, -1); VideoDecoderConfig config(kCodecVP8, VP8PROFILE_ANY, kVideoFormat, COLOR_SPACE_UNSPECIFIED, kCodedSize, kVisibleRect, - natural_size, EmptyExtraData(), false); + natural_size, EmptyExtraData(), Unencrypted()); EXPECT_FALSE(config.IsValidConfig()); } @@ -61,7 +61,7 @@ TEST(VideoDecoderConfigTest, Invalid_AspectRatioNumeratorTooLarge) { gfx::Size natural_size = GetNaturalSize(kVisibleRect.size(), num, 1); VideoDecoderConfig config(kCodecVP8, VP8PROFILE_ANY, kVideoFormat, COLOR_SPACE_UNSPECIFIED, kCodedSize, kVisibleRect, - natural_size, EmptyExtraData(), false); + natural_size, EmptyExtraData(), Unencrypted()); EXPECT_FALSE(config.IsValidConfig()); } @@ -72,7 +72,7 @@ TEST(VideoDecoderConfigTest, Invalid_AspectRatioDenominatorTooLarge) { EXPECT_EQ(0, natural_size.width()); VideoDecoderConfig config(kCodecVP8, VP8PROFILE_ANY, kVideoFormat, COLOR_SPACE_UNSPECIFIED, kCodedSize, kVisibleRect, - natural_size, EmptyExtraData(), false); + natural_size, EmptyExtraData(), Unencrypted()); EXPECT_FALSE(config.IsValidConfig()); } diff --git a/media/ffmpeg/ffmpeg_common.cc b/media/ffmpeg/ffmpeg_common.cc index 51e8884..f081255 100644 --- a/media/ffmpeg/ffmpeg_common.cc +++ b/media/ffmpeg/ffmpeg_common.cc @@ -13,12 +13,24 @@ #include "build/build_config.h" #include "media/base/audio_decoder_config.h" #include "media/base/decoder_buffer.h" +#include "media/base/encryption_scheme.h" +#include "media/base/media_util.h" #include "media/base/video_decoder_config.h" #include "media/base/video_util.h" #include "media/media_features.h" namespace media { +namespace { + +EncryptionScheme GetEncryptionScheme(const AVStream* stream) { + AVDictionaryEntry* key = + av_dict_get(stream->metadata, "enc_key_id", nullptr, 0); + return key ? AesCtrEncryptionScheme() : Unencrypted(); +} + +} // namespace + // Why FF_INPUT_BUFFER_PADDING_SIZE? FFmpeg assumes all input buffers are // padded. Check here to ensure FFmpeg only receives data padded to its // specifications. @@ -303,9 +315,10 @@ static AVSampleFormat SampleFormatToAVSampleFormat(SampleFormat sample_format) { return AV_SAMPLE_FMT_NONE; } -bool AVCodecContextToAudioDecoderConfig(const AVCodecContext* codec_context, - bool is_encrypted, - AudioDecoderConfig* config) { +bool AVCodecContextToAudioDecoderConfig( + const AVCodecContext* codec_context, + const EncryptionScheme& encryption_scheme, + AudioDecoderConfig* config) { DCHECK_EQ(codec_context->codec_type, AVMEDIA_TYPE_AUDIO); AudioCodec codec = CodecIDToAudioCodec(codec_context->codec_id); @@ -371,13 +384,9 @@ bool AVCodecContextToAudioDecoderConfig(const AVCodecContext* codec_context, extra_data.assign(codec_context->extradata, codec_context->extradata + codec_context->extradata_size); } - config->Initialize(codec, - sample_format, - channel_layout, - sample_rate, - extra_data, - is_encrypted, - seek_preroll, + + config->Initialize(codec, sample_format, channel_layout, sample_rate, + extra_data, encryption_scheme, seek_preroll, codec_context->delay); // Verify that AudioConfig.bits_per_channel was calculated correctly for @@ -400,13 +409,8 @@ bool AVCodecContextToAudioDecoderConfig(const AVCodecContext* codec_context, bool AVStreamToAudioDecoderConfig(const AVStream* stream, AudioDecoderConfig* config) { - bool is_encrypted = false; - AVDictionaryEntry* key = - av_dict_get(stream->metadata, "enc_key_id", nullptr, 0); - if (key) - is_encrypted = true; - return AVCodecContextToAudioDecoderConfig(stream->codec, is_encrypted, - config); + return AVCodecContextToAudioDecoderConfig( + stream->codec, GetEncryptionScheme(stream), config); } void AudioDecoderConfigToAVCodecContext(const AudioDecoderConfig& config, @@ -497,12 +501,6 @@ bool AVStreamToVideoDecoderConfig(const AVStream* stream, coded_size.set_height((coded_size.height() + 1) / 2 * 2); } - bool is_encrypted = false; - AVDictionaryEntry* key = - av_dict_get(stream->metadata, "enc_key_id", nullptr, 0); - if (key) - is_encrypted = true; - AVDictionaryEntry* webm_alpha = av_dict_get(stream->metadata, "alpha_mode", nullptr, 0); if (webm_alpha && !strcmp(webm_alpha->value, "1")) { @@ -535,7 +533,8 @@ bool AVStreamToVideoDecoderConfig(const AVStream* stream, stream->codec->extradata + stream->codec->extradata_size); } config->Initialize(codec, profile, format, color_space, coded_size, - visible_rect, natural_size, extra_data, is_encrypted); + visible_rect, natural_size, extra_data, + GetEncryptionScheme(stream)); return true; } diff --git a/media/ffmpeg/ffmpeg_common.h b/media/ffmpeg/ffmpeg_common.h index b66de897..d5ad132 100644 --- a/media/ffmpeg/ffmpeg_common.h +++ b/media/ffmpeg/ffmpeg_common.h @@ -52,6 +52,7 @@ MSVC_POP_WARNING(); namespace media { class AudioDecoderConfig; +class EncryptionScheme; class VideoDecoderConfig; // The following implement the deleters declared in ffmpeg_deleters.h (which @@ -113,7 +114,7 @@ void VideoDecoderConfigToAVCodecContext( // is not modified. MEDIA_EXPORT bool AVCodecContextToAudioDecoderConfig( const AVCodecContext* codec_context, - bool is_encrypted, + const EncryptionScheme& encryption_scheme, AudioDecoderConfig* config); // Converts FFmpeg's channel layout to chrome's ChannelLayout. |channels| can diff --git a/media/ffmpeg/ffmpeg_common_unittest.cc b/media/ffmpeg/ffmpeg_common_unittest.cc index 1d33405..0650ee6 100644 --- a/media/ffmpeg/ffmpeg_common_unittest.cc +++ b/media/ffmpeg/ffmpeg_common_unittest.cc @@ -14,6 +14,7 @@ #include "base/memory/scoped_ptr.h" #include "media/base/audio_decoder_config.h" #include "media/base/media.h" +#include "media/base/media_util.h" #include "media/base/test_data_util.h" #include "media/base/video_decoder_config.h" #include "media/ffmpeg/ffmpeg_common.h" @@ -134,7 +135,7 @@ TEST_F(FFmpegCommonTest, OpusAudioDecoderConfig) { context.sample_rate = 44100; AudioDecoderConfig decoder_config; - ASSERT_TRUE(AVCodecContextToAudioDecoderConfig(&context, false, + ASSERT_TRUE(AVCodecContextToAudioDecoderConfig(&context, Unencrypted(), &decoder_config)); EXPECT_EQ(48000, decoder_config.samples_per_second()); } diff --git a/media/filters/audio_decoder_selector_unittest.cc b/media/filters/audio_decoder_selector_unittest.cc index 92c4a73..0d87edc 100644 --- a/media/filters/audio_decoder_selector_unittest.cc +++ b/media/filters/audio_decoder_selector_unittest.cc @@ -77,14 +77,14 @@ class AudioDecoderSelectorTest : public ::testing::Test { void UseClearStream() { AudioDecoderConfig clear_audio_config(kCodecVorbis, kSampleFormatPlanarF32, CHANNEL_LAYOUT_STEREO, 44100, - EmptyExtraData(), false); + EmptyExtraData(), Unencrypted()); demuxer_stream_->set_audio_decoder_config(clear_audio_config); } void UseEncryptedStream() { AudioDecoderConfig encrypted_audio_config( kCodecVorbis, kSampleFormatPlanarF32, CHANNEL_LAYOUT_STEREO, 44100, - EmptyExtraData(), true); + EmptyExtraData(), AesCtrEncryptionScheme()); demuxer_stream_->set_audio_decoder_config(encrypted_audio_config); } diff --git a/media/filters/audio_decoder_unittest.cc b/media/filters/audio_decoder_unittest.cc index c4f727b..72881b7 100644 --- a/media/filters/audio_decoder_unittest.cc +++ b/media/filters/audio_decoder_unittest.cc @@ -194,7 +194,7 @@ class AudioDecoderTest : public testing::TestWithParam<DecoderTestData> { AudioDecoderConfig config; ASSERT_TRUE(AVCodecContextToAudioDecoderConfig( - reader_->codec_context_for_testing(), false, &config)); + reader_->codec_context_for_testing(), Unencrypted(), &config)); EXPECT_EQ(GetParam().codec, config.codec()); EXPECT_EQ(GetParam().samples_per_second, config.samples_per_second()); @@ -433,14 +433,9 @@ TEST_P(OpusAudioDecoderBehavioralTest, InitializeWithNoCodecDelay) { kOpusExtraData, kOpusExtraData + arraysize(kOpusExtraData)); AudioDecoderConfig decoder_config; - decoder_config.Initialize(kCodecOpus, - kSampleFormatF32, - CHANNEL_LAYOUT_STEREO, - 48000, - extra_data, - false, - base::TimeDelta::FromMilliseconds(80), - 0); + decoder_config.Initialize(kCodecOpus, kSampleFormatF32, CHANNEL_LAYOUT_STEREO, + 48000, extra_data, Unencrypted(), + base::TimeDelta::FromMilliseconds(80), 0); InitializeDecoder(decoder_config); } @@ -451,13 +446,8 @@ TEST_P(OpusAudioDecoderBehavioralTest, InitializeWithBadCodecDelay) { kOpusExtraData + arraysize(kOpusExtraData)); AudioDecoderConfig decoder_config; decoder_config.Initialize( - kCodecOpus, - kSampleFormatF32, - CHANNEL_LAYOUT_STEREO, - 48000, - extra_data, - false, - base::TimeDelta::FromMilliseconds(80), + kCodecOpus, kSampleFormatF32, CHANNEL_LAYOUT_STEREO, 48000, extra_data, + Unencrypted(), base::TimeDelta::FromMilliseconds(80), // Use a different codec delay than in the extradata. 100); InitializeDecoderWithResult(decoder_config, true); diff --git a/media/filters/decrypting_audio_decoder_unittest.cc b/media/filters/decrypting_audio_decoder_unittest.cc index 2a37b64..6649b68 100644 --- a/media/filters/decrypting_audio_decoder_unittest.cc +++ b/media/filters/decrypting_audio_decoder_unittest.cc @@ -120,7 +120,7 @@ class DecryptingAudioDecoderTest : public testing::Test { config_.Initialize(kCodecVorbis, kSampleFormatPlanarF32, CHANNEL_LAYOUT_STEREO, kSampleRate, EmptyExtraData(), - true, base::TimeDelta(), 0); + AesCtrEncryptionScheme(), base::TimeDelta(), 0); InitializeAndExpectResult(config_, true); } @@ -286,7 +286,7 @@ TEST_F(DecryptingAudioDecoderTest, Initialize_Normal) { TEST_F(DecryptingAudioDecoderTest, Initialize_UnencryptedAudioConfig) { AudioDecoderConfig config(kCodecVorbis, kSampleFormatPlanarF32, CHANNEL_LAYOUT_STEREO, kSampleRate, - EmptyExtraData(), false); + EmptyExtraData(), Unencrypted()); InitializeAndExpectResult(config, false); } @@ -294,7 +294,8 @@ TEST_F(DecryptingAudioDecoderTest, Initialize_UnencryptedAudioConfig) { // Ensure decoder handles invalid audio configs without crashing. TEST_F(DecryptingAudioDecoderTest, Initialize_InvalidAudioConfig) { AudioDecoderConfig config(kUnknownAudioCodec, kUnknownSampleFormat, - CHANNEL_LAYOUT_STEREO, 0, EmptyExtraData(), true); + CHANNEL_LAYOUT_STEREO, 0, EmptyExtraData(), + AesCtrEncryptionScheme()); InitializeAndExpectResult(config, false); } @@ -307,7 +308,7 @@ TEST_F(DecryptingAudioDecoderTest, Initialize_UnsupportedAudioConfig) { AudioDecoderConfig config(kCodecVorbis, kSampleFormatPlanarF32, CHANNEL_LAYOUT_STEREO, kSampleRate, - EmptyExtraData(), true); + EmptyExtraData(), AesCtrEncryptionScheme()); InitializeAndExpectResult(config, false); } @@ -315,7 +316,7 @@ TEST_F(DecryptingAudioDecoderTest, Initialize_CdmWithoutDecryptor) { SetCdmType(CDM_WITHOUT_DECRYPTOR); AudioDecoderConfig config(kCodecVorbis, kSampleFormatPlanarF32, CHANNEL_LAYOUT_STEREO, kSampleRate, - EmptyExtraData(), true); + EmptyExtraData(), AesCtrEncryptionScheme()); InitializeAndExpectResult(config, false); } @@ -384,7 +385,7 @@ TEST_F(DecryptingAudioDecoderTest, Reinitialize_ConfigChange) { // channel layout and samples_per_second. AudioDecoderConfig new_config(kCodecVorbis, kSampleFormatPlanarS16, CHANNEL_LAYOUT_5_1, 88200, EmptyExtraData(), - true); + AesCtrEncryptionScheme()); EXPECT_NE(new_config.bits_per_channel(), config_.bits_per_channel()); EXPECT_NE(new_config.channel_layout(), config_.channel_layout()); EXPECT_NE(new_config.samples_per_second(), config_.samples_per_second()); diff --git a/media/filters/decrypting_demuxer_stream.cc b/media/filters/decrypting_demuxer_stream.cc index 637de2a..a44a036 100644 --- a/media/filters/decrypting_demuxer_stream.cc +++ b/media/filters/decrypting_demuxer_stream.cc @@ -12,6 +12,7 @@ #include "media/base/bind_to_current_loop.h" #include "media/base/decoder_buffer.h" #include "media/base/media_log.h" +#include "media/base/media_util.h" namespace media { @@ -347,14 +348,12 @@ void DecryptingDemuxerStream::InitializeDecoderConfig() { case AUDIO: { AudioDecoderConfig input_audio_config = demuxer_stream_->audio_decoder_config(); - audio_config_.Initialize(input_audio_config.codec(), - input_audio_config.sample_format(), - input_audio_config.channel_layout(), - input_audio_config.samples_per_second(), - input_audio_config.extra_data(), - false, // Output audio is not encrypted. - input_audio_config.seek_preroll(), - input_audio_config.codec_delay()); + audio_config_.Initialize( + input_audio_config.codec(), input_audio_config.sample_format(), + input_audio_config.channel_layout(), + input_audio_config.samples_per_second(), + input_audio_config.extra_data(), Unencrypted(), + input_audio_config.seek_preroll(), input_audio_config.codec_delay()); break; } @@ -366,7 +365,7 @@ void DecryptingDemuxerStream::InitializeDecoderConfig() { input_video_config.format(), input_video_config.color_space(), input_video_config.coded_size(), input_video_config.visible_rect(), input_video_config.natural_size(), input_video_config.extra_data(), - false); // Output video is not encrypted. + Unencrypted()); break; } diff --git a/media/filters/decrypting_demuxer_stream_unittest.cc b/media/filters/decrypting_demuxer_stream_unittest.cc index 45cdfe1..f08733b 100644 --- a/media/filters/decrypting_demuxer_stream_unittest.cc +++ b/media/filters/decrypting_demuxer_stream_unittest.cc @@ -131,7 +131,7 @@ class DecryptingDemuxerStreamTest : public testing::Test { AudioDecoderConfig input_config(kCodecVorbis, kSampleFormatPlanarF32, CHANNEL_LAYOUT_STEREO, 44100, - EmptyExtraData(), true); + EmptyExtraData(), AesCtrEncryptionScheme()); InitializeAudioAndExpectStatus(input_config, PIPELINE_OK); const AudioDecoderConfig& output_config = @@ -305,7 +305,7 @@ TEST_F(DecryptingDemuxerStreamTest, Initialize_CdmWithoutDecryptor) { SetCdmType(CDM_WITHOUT_DECRYPTOR); AudioDecoderConfig input_config(kCodecVorbis, kSampleFormatPlanarF32, CHANNEL_LAYOUT_STEREO, 44100, - EmptyExtraData(), true); + EmptyExtraData(), AesCtrEncryptionScheme()); InitializeAudioAndExpectStatus(input_config, DECODER_ERROR_NOT_SUPPORTED); } @@ -361,7 +361,7 @@ TEST_F(DecryptingDemuxerStreamTest, KeyAdded_DuringWaitingForKey) { // Test the case where the a key is added when the decryptor is in // kPendingDecrypt state. -TEST_F(DecryptingDemuxerStreamTest, KeyAdded_DruingPendingDecrypt) { +TEST_F(DecryptingDemuxerStreamTest, KeyAdded_DuringPendingDecrypt) { Initialize(); EnterPendingDecryptState(); @@ -457,7 +457,7 @@ TEST_F(DecryptingDemuxerStreamTest, DemuxerRead_ConfigChanged) { AudioDecoderConfig new_config(kCodecVorbis, kSampleFormatPlanarF32, CHANNEL_LAYOUT_STEREO, 88200, EmptyExtraData(), - true); + AesCtrEncryptionScheme()); input_audio_stream_->set_audio_decoder_config(new_config); EXPECT_CALL(*input_audio_stream_, Read(_)) diff --git a/media/filters/ffmpeg_video_decoder_unittest.cc b/media/filters/ffmpeg_video_decoder_unittest.cc index 6eef19f..fa91d50 100644 --- a/media/filters/ffmpeg_video_decoder_unittest.cc +++ b/media/filters/ffmpeg_video_decoder_unittest.cc @@ -224,7 +224,7 @@ TEST_F(FFmpegVideoDecoderTest, Initialize_OpenDecoderFails) { VideoDecoderConfig config(kCodecTheora, VIDEO_CODEC_PROFILE_UNKNOWN, kVideoFormat, COLOR_SPACE_UNSPECIFIED, kCodedSize, kVisibleRect, kNaturalSize, EmptyExtraData(), - false); + Unencrypted()); InitializeWithConfigWithResult(config, false); } diff --git a/media/filters/frame_processor_unittest.cc b/media/filters/frame_processor_unittest.cc index 289ca8e..3220ae6 100644 --- a/media/filters/frame_processor_unittest.cc +++ b/media/filters/frame_processor_unittest.cc @@ -294,7 +294,7 @@ class FrameProcessorTest : public testing::TestWithParam<bool> { audio_.reset(new ChunkDemuxerStream(DemuxerStream::AUDIO, true)); AudioDecoderConfig decoder_config(kCodecVorbis, kSampleFormatPlanarF32, CHANNEL_LAYOUT_STEREO, 1000, - EmptyExtraData(), false); + EmptyExtraData(), Unencrypted()); frame_processor_->OnPossibleAudioConfigUpdate(decoder_config); ASSERT_TRUE(audio_->UpdateAudioConfig(decoder_config, new MediaLog())); break; diff --git a/media/filters/opus_audio_decoder.cc b/media/filters/opus_audio_decoder.cc index 83dad21..bec37f3 100644 --- a/media/filters/opus_audio_decoder.cc +++ b/media/filters/opus_audio_decoder.cc @@ -269,7 +269,7 @@ bool OpusAudioDecoder::ConfigureDecoder() { << " vs " << opus_extra_data.skip_samples; config_.Initialize(config_.codec(), config_.sample_format(), config_.channel_layout(), config_.samples_per_second(), - config_.extra_data(), config_.is_encrypted(), + config_.extra_data(), config_.encryption_scheme(), config_.seek_preroll(), opus_extra_data.skip_samples); } diff --git a/media/filters/source_buffer_stream.cc b/media/filters/source_buffer_stream.cc index e03a8c3..05f2337 100644 --- a/media/filters/source_buffer_stream.cc +++ b/media/filters/source_buffer_stream.cc @@ -1476,7 +1476,8 @@ bool SourceBufferStream::UpdateAudioConfig(const AudioDecoderConfig& config) { return false; } - if (audio_configs_[0].is_encrypted() != config.is_encrypted()) { + if (!audio_configs_[0].encryption_scheme().Matches( + config.encryption_scheme())) { MEDIA_LOG(ERROR, media_log_) << "Audio encryption changes not allowed."; return false; } @@ -1507,7 +1508,8 @@ bool SourceBufferStream::UpdateVideoConfig(const VideoDecoderConfig& config) { return false; } - if (video_configs_[0].is_encrypted() != config.is_encrypted()) { + if (!video_configs_[0].encryption_scheme().Matches( + config.encryption_scheme())) { MEDIA_LOG(ERROR, media_log_) << "Video encryption changes not allowed."; return false; } diff --git a/media/filters/source_buffer_stream_unittest.cc b/media/filters/source_buffer_stream_unittest.cc index 53e8066..a9558a2 100644 --- a/media/filters/source_buffer_stream_unittest.cc +++ b/media/filters/source_buffer_stream_unittest.cc @@ -95,14 +95,9 @@ class SourceBufferStreamTest : public testing::Test { void SetAudioStream() { video_config_ = TestVideoConfig::Invalid(); - audio_config_.Initialize(kCodecVorbis, - kSampleFormatPlanarF32, - CHANNEL_LAYOUT_STEREO, - 1000, - EmptyExtraData(), - false, - base::TimeDelta(), - 0); + audio_config_.Initialize(kCodecVorbis, kSampleFormatPlanarF32, + CHANNEL_LAYOUT_STEREO, 1000, EmptyExtraData(), + Unencrypted(), base::TimeDelta(), 0); stream_.reset(new SourceBufferStream(audio_config_, media_log_, true)); // Equivalent to 2ms per frame. @@ -3653,7 +3648,7 @@ TEST_F(SourceBufferStreamTest, SameTimestamp_Video_Overlap_3) { // Test all the valid same timestamp cases for audio. TEST_F(SourceBufferStreamTest, SameTimestamp_Audio) { AudioDecoderConfig config(kCodecMP3, kSampleFormatF32, CHANNEL_LAYOUT_STEREO, - 44100, EmptyExtraData(), false); + 44100, EmptyExtraData(), Unencrypted()); stream_.reset(new SourceBufferStream(config, media_log_, true)); Seek(0); NewCodedFrameGroupAppend("0K 0K 30K 30 60 60"); @@ -3664,7 +3659,7 @@ TEST_F(SourceBufferStreamTest, SameTimestamp_Audio_SingleAppend_Warning) { EXPECT_MEDIA_LOG(ContainsSameTimestampAt30MillisecondsLog()); AudioDecoderConfig config(kCodecMP3, kSampleFormatF32, CHANNEL_LAYOUT_STEREO, - 44100, EmptyExtraData(), false); + 44100, EmptyExtraData(), Unencrypted()); stream_.reset(new SourceBufferStream(config, media_log_, true)); Seek(0); @@ -4229,7 +4224,7 @@ TEST_F(SourceBufferStreamTest, Audio_SpliceFrame_ConfigChange) { AudioDecoderConfig new_config(kCodecVorbis, kSampleFormatPlanarF32, CHANNEL_LAYOUT_MONO, 1000, EmptyExtraData(), - false); + Unencrypted()); ASSERT_NE(new_config.channel_layout(), audio_config_.channel_layout()); Seek(0); @@ -4270,8 +4265,8 @@ TEST_F(SourceBufferStreamTest, Audio_SpliceFrame_NoMillisecondSplices) { video_config_ = TestVideoConfig::Invalid(); audio_config_.Initialize(kCodecVorbis, kSampleFormatPlanarF32, - CHANNEL_LAYOUT_STEREO, 4000, EmptyExtraData(), false, - base::TimeDelta(), 0); + CHANNEL_LAYOUT_STEREO, 4000, EmptyExtraData(), + Unencrypted(), base::TimeDelta(), 0); stream_.reset(new SourceBufferStream(audio_config_, media_log_, true)); // Equivalent to 0.5ms per frame. SetStreamInfo(2000, 2000); diff --git a/media/formats/mp2t/es_adapter_video_unittest.cc b/media/formats/mp2t/es_adapter_video_unittest.cc index a6e1684..5946d21 100644 --- a/media/formats/mp2t/es_adapter_video_unittest.cc +++ b/media/formats/mp2t/es_adapter_video_unittest.cc @@ -32,7 +32,7 @@ VideoDecoderConfig CreateFakeVideoConfig() { gfx::Size natural_size(320, 240); return VideoDecoderConfig(kCodecH264, H264PROFILE_MAIN, PIXEL_FORMAT_I420, COLOR_SPACE_UNSPECIFIED, coded_size, visible_rect, - natural_size, EmptyExtraData(), false); + natural_size, EmptyExtraData(), Unencrypted()); } StreamParserBuffer::BufferQueue diff --git a/media/formats/mp2t/es_parser_adts.cc b/media/formats/mp2t/es_parser_adts.cc index 5a90973..b209d66 100644 --- a/media/formats/mp2t/es_parser_adts.cc +++ b/media/formats/mp2t/es_parser_adts.cc @@ -13,6 +13,7 @@ #include "media/base/audio_timestamp_helper.h" #include "media/base/bit_reader.h" #include "media/base/channel_layout.h" +#include "media/base/media_util.h" #include "media/base/stream_parser_buffer.h" #include "media/base/timestamp_constants.h" #include "media/formats/common/offset_byte_queue.h" @@ -227,12 +228,9 @@ bool EsParserAdts::UpdateAudioConfiguration(const uint8_t* adts_header) { extra_data.push_back(static_cast<uint8_t>(extra_data_int & 0xff)); AudioDecoderConfig audio_decoder_config( - kCodecAAC, - kSampleFormatS16, + kCodecAAC, kSampleFormatS16, kADTSChannelLayoutTable[channel_configuration], - extended_samples_per_second, - extra_data, - false); + extended_samples_per_second, extra_data, Unencrypted()); if (!audio_decoder_config.Matches(last_audio_decoder_config_)) { DVLOG(1) << "Sampling frequency: " << samples_per_second; diff --git a/media/formats/mp2t/es_parser_h264.cc b/media/formats/mp2t/es_parser_h264.cc index dc8315c..3b47fec 100644 --- a/media/formats/mp2t/es_parser_h264.cc +++ b/media/formats/mp2t/es_parser_h264.cc @@ -6,6 +6,8 @@ #include "base/logging.h" #include "base/numerics/safe_conversions.h" +#include "media/base/encryption_scheme.h" +#include "media/base/media_util.h" #include "media/base/stream_parser_buffer.h" #include "media/base/timestamp_constants.h" #include "media/base/video_frame.h" @@ -262,7 +264,7 @@ bool EsParserH264::EmitFrame(int64_t access_unit_pos, const H264SPS* sps = h264_parser_->GetSPS(pps->seq_parameter_set_id); if (!sps) return false; - RCHECK(UpdateVideoDecoderConfig(sps)); + RCHECK(UpdateVideoDecoderConfig(sps, Unencrypted())); } // Emit a frame. @@ -287,7 +289,8 @@ bool EsParserH264::EmitFrame(int64_t access_unit_pos, return es_adapter_.OnNewBuffer(stream_parser_buffer); } -bool EsParserH264::UpdateVideoDecoderConfig(const H264SPS* sps) { +bool EsParserH264::UpdateVideoDecoderConfig(const H264SPS* sps, + const EncryptionScheme& scheme) { // Set the SAR to 1 when not specified in the H264 stream. int sar_width = (sps->sar_width == 0) ? 1 : sps->sar_width; int sar_height = (sps->sar_height == 0) ? 1 : sps->sar_height; @@ -314,7 +317,7 @@ bool EsParserH264::UpdateVideoDecoderConfig(const H264SPS* sps) { VideoDecoderConfig video_decoder_config( kCodecH264, ProfileIDCToVideoCodecProfile(sps->profile_idc), PIXEL_FORMAT_YV12, COLOR_SPACE_HD_REC709, coded_size, visible_rect, - natural_size, std::vector<uint8_t>(), false); + natural_size, EmptyExtraData(), scheme); if (!video_decoder_config.Matches(last_video_decoder_config_)) { DVLOG(1) << "Profile IDC: " << sps->profile_idc; diff --git a/media/formats/mp2t/es_parser_h264.h b/media/formats/mp2t/es_parser_h264.h index 9ce8ea0..184ac07 100644 --- a/media/formats/mp2t/es_parser_h264.h +++ b/media/formats/mp2t/es_parser_h264.h @@ -7,7 +7,6 @@ #include <stdint.h> -#include <list> #include <utility> #include "base/callback.h" @@ -21,6 +20,7 @@ #include "media/formats/mp2t/es_parser.h" namespace media { +class EncryptionScheme; class H264Parser; struct H264SPS; class OffsetByteQueue; @@ -70,7 +70,8 @@ class MEDIA_EXPORT EsParserH264 : public EsParser { // Update the video decoder config based on an H264 SPS. // Return true if successful. - bool UpdateVideoDecoderConfig(const H264SPS* sps); + bool UpdateVideoDecoderConfig(const H264SPS* sps, + const EncryptionScheme& scheme); EsAdapterVideo es_adapter_; diff --git a/media/formats/mp2t/es_parser_mpeg1audio.cc b/media/formats/mp2t/es_parser_mpeg1audio.cc index 5032887..96ed8d6 100644 --- a/media/formats/mp2t/es_parser_mpeg1audio.cc +++ b/media/formats/mp2t/es_parser_mpeg1audio.cc @@ -12,6 +12,7 @@ #include "media/base/audio_timestamp_helper.h" #include "media/base/bit_reader.h" #include "media/base/channel_layout.h" +#include "media/base/media_util.h" #include "media/base/stream_parser_buffer.h" #include "media/base/timestamp_constants.h" #include "media/formats/common/offset_byte_queue.h" @@ -170,12 +171,8 @@ bool EsParserMpeg1Audio::UpdateAudioConfiguration( // TODO(damienv): Verify whether Android playback requires the extra data // field for Mpeg1 audio. If yes, we should generate this field. AudioDecoderConfig audio_decoder_config( - kCodecMP3, - kSampleFormatS16, - header.channel_layout, - header.sample_rate, - std::vector<uint8_t>(), - false); + kCodecMP3, kSampleFormatS16, header.channel_layout, header.sample_rate, + EmptyExtraData(), Unencrypted()); if (!audio_decoder_config.Matches(last_audio_decoder_config_)) { DVLOG(1) << "Sampling frequency: " << header.sample_rate; diff --git a/media/formats/mp4/mp4_stream_parser.cc b/media/formats/mp4/mp4_stream_parser.cc index 37b5396..4f72c5e 100644 --- a/media/formats/mp4/mp4_stream_parser.cc +++ b/media/formats/mp4/mp4_stream_parser.cc @@ -16,6 +16,7 @@ #include "build/build_config.h" #include "media/base/audio_decoder_config.h" #include "media/base/media_tracks.h" +#include "media/base/media_util.h" #include "media/base/stream_parser_buffer.h" #include "media/base/text_track_config.h" #include "media/base/timestamp_constants.h" @@ -304,9 +305,10 @@ bool MP4StreamParser::ParseMoov(BoxReader* reader) { is_audio_track_encrypted_ = entry.sinf.info.track_encryption.is_encrypted; DVLOG(1) << "is_audio_track_encrypted_: " << is_audio_track_encrypted_; - audio_config.Initialize(codec, sample_format, channel_layout, - sample_per_second, extra_data, - is_audio_track_encrypted_, base::TimeDelta(), 0); + audio_config.Initialize( + codec, sample_format, channel_layout, sample_per_second, extra_data, + is_audio_track_encrypted_ ? AesCtrEncryptionScheme() : Unencrypted(), + base::TimeDelta(), 0); has_audio_ = true; audio_track_id_ = track->header.track_id; media_tracks->AddAudioTrack( @@ -350,7 +352,8 @@ bool MP4StreamParser::ParseMoov(BoxReader* reader) { COLOR_SPACE_HD_REC709, coded_size, visible_rect, natural_size, // No decoder-specific buffer needed for AVC; // SPS/PPS are embedded in the video stream - std::vector<uint8_t>(), is_video_track_encrypted_); + EmptyExtraData(), + is_video_track_encrypted_ ? AesCtrEncryptionScheme() : Unencrypted()); has_video_ = true; video_track_id_ = track->header.track_id; media_tracks->AddVideoTrack( diff --git a/media/formats/mpeg/mpeg_audio_stream_parser_base.cc b/media/formats/mpeg/mpeg_audio_stream_parser_base.cc index 2028495..47dd2f6 100644 --- a/media/formats/mpeg/mpeg_audio_stream_parser_base.cc +++ b/media/formats/mpeg/mpeg_audio_stream_parser_base.cc @@ -8,6 +8,7 @@ #include "base/callback_helpers.h" #include "base/message_loop/message_loop.h" #include "media/base/media_tracks.h" +#include "media/base/media_util.h" #include "media/base/stream_parser_buffer.h" #include "media/base/text_track_config.h" #include "media/base/timestamp_constants.h" @@ -205,14 +206,9 @@ int MPEGAudioStreamParserBase::ParseFrame(const uint8_t* data, } if (!config_.IsValidConfig()) { - config_.Initialize(audio_codec_, - kSampleFormatF32, - channel_layout, - sample_rate, - std::vector<uint8_t>(), - false, - base::TimeDelta(), - codec_delay_); + config_.Initialize(audio_codec_, kSampleFormatF32, channel_layout, + sample_rate, std::vector<uint8_t>(), Unencrypted(), + base::TimeDelta(), codec_delay_); base::TimeDelta base_timestamp; if (timestamp_helper_) diff --git a/media/formats/webm/webm_audio_client.cc b/media/formats/webm/webm_audio_client.cc index fb6a723a..173d81f 100644 --- a/media/formats/webm/webm_audio_client.cc +++ b/media/formats/webm/webm_audio_client.cc @@ -29,7 +29,7 @@ bool WebMAudioClient::InitializeConfig( const std::vector<uint8_t>& codec_private, int64_t seek_preroll, int64_t codec_delay, - bool is_encrypted, + const EncryptionScheme& encryption_scheme, AudioDecoderConfig* config) { DCHECK(config); SampleFormat sample_format = kSampleFormatPlanarF32; @@ -78,16 +78,11 @@ bool WebMAudioClient::InitializeConfig( base::Time::kNanosecondsPerSecond); } - config->Initialize( - audio_codec, - sample_format, - channel_layout, - samples_per_second, - codec_private, - is_encrypted, - base::TimeDelta::FromMicroseconds( - (seek_preroll != -1 ? seek_preroll : 0) / 1000), - codec_delay_in_frames); + config->Initialize(audio_codec, sample_format, channel_layout, + samples_per_second, codec_private, encryption_scheme, + base::TimeDelta::FromMicroseconds( + (seek_preroll != -1 ? seek_preroll : 0) / 1000), + codec_delay_in_frames); return config->IsValidConfig(); } diff --git a/media/formats/webm/webm_audio_client.h b/media/formats/webm/webm_audio_client.h index fefa55f..06d7e0c 100644 --- a/media/formats/webm/webm_audio_client.h +++ b/media/formats/webm/webm_audio_client.h @@ -16,6 +16,7 @@ namespace media { class AudioDecoderConfig; +class EncryptionScheme; // Helper class used to parse an Audio element inside a TrackEntry element. class WebMAudioClient : public WebMParserClient { @@ -27,8 +28,8 @@ class WebMAudioClient : public WebMParserClient { void Reset(); // Initialize |config| with the data in |codec_id|, |codec_private|, - // |is_encrypted| and the fields parsed from the last audio track element this - // object was used to parse. + // |encryption_scheme| and the fields parsed from the last audio track element + // this object was used to parse. // Returns true if |config| was successfully initialized. // Returns false if there was unexpected values in the provided parameters or // audio track element fields. @@ -36,7 +37,7 @@ class WebMAudioClient : public WebMParserClient { const std::vector<uint8_t>& codec_private, const int64_t seek_preroll, const int64_t codec_delay, - bool is_encrypted, + const EncryptionScheme& encryption_scheme, AudioDecoderConfig* config); private: diff --git a/media/formats/webm/webm_tracks_parser.cc b/media/formats/webm/webm_tracks_parser.cc index 5ffa0aa..112427f 100644 --- a/media/formats/webm/webm_tracks_parser.cc +++ b/media/formats/webm/webm_tracks_parser.cc @@ -7,6 +7,7 @@ #include "base/logging.h" #include "base/strings/string_number_conversions.h" #include "base/strings/string_util.h" +#include "media/base/media_util.h" #include "media/base/timestamp_constants.h" #include "media/formats/webm/webm_constants.h" #include "media/formats/webm/webm_content_encodings.h" @@ -193,6 +194,9 @@ bool WebMTracksParser::OnListEnd(int id) { content_encodings()[0]->encryption_key_id(); } + EncryptionScheme encryption_scheme = + encryption_key_id.empty() ? Unencrypted() : AesCtrEncryptionScheme(); + if (track_type_ == kWebMTrackTypeAudio) { if (audio_track_num_ == -1) { audio_track_num_ = track_num_; @@ -208,7 +212,7 @@ bool WebMTracksParser::OnListEnd(int id) { DCHECK(!audio_decoder_config_.IsValidConfig()); if (!audio_client_.InitializeConfig( codec_id_, codec_private_, seek_preroll_, codec_delay_, - !audio_encryption_key_id_.empty(), &audio_decoder_config_)) { + encryption_scheme, &audio_decoder_config_)) { return false; } media_tracks_->AddAudioTrack(audio_decoder_config_, @@ -231,9 +235,9 @@ bool WebMTracksParser::OnListEnd(int id) { video_default_duration_ = default_duration_; DCHECK(!video_decoder_config_.IsValidConfig()); - if (!video_client_.InitializeConfig( - codec_id_, codec_private_, !video_encryption_key_id_.empty(), - &video_decoder_config_)) { + if (!video_client_.InitializeConfig(codec_id_, codec_private_, + encryption_scheme, + &video_decoder_config_)) { return false; } media_tracks_->AddVideoTrack(video_decoder_config_, diff --git a/media/formats/webm/webm_video_client.cc b/media/formats/webm/webm_video_client.cc index 6e57dfb..9d0435f 100644 --- a/media/formats/webm/webm_video_client.cc +++ b/media/formats/webm/webm_video_client.cc @@ -33,7 +33,7 @@ void WebMVideoClient::Reset() { bool WebMVideoClient::InitializeConfig( const std::string& codec_id, const std::vector<uint8_t>& codec_private, - bool is_encrypted, + const EncryptionScheme& encryption_scheme, VideoDecoderConfig* config) { DCHECK(config); @@ -93,7 +93,7 @@ bool WebMVideoClient::InitializeConfig( config->Initialize(video_codec, profile, format, COLOR_SPACE_HD_REC709, coded_size, visible_rect, natural_size, codec_private, - is_encrypted); + encryption_scheme); return config->IsValidConfig(); } diff --git a/media/formats/webm/webm_video_client.h b/media/formats/webm/webm_video_client.h index dfdc5f6..d746df9 100644 --- a/media/formats/webm/webm_video_client.h +++ b/media/formats/webm/webm_video_client.h @@ -15,6 +15,7 @@ #include "media/formats/webm/webm_parser.h" namespace media { +class EncryptionScheme; class VideoDecoderConfig; // Helper class used to parse a Video element inside a TrackEntry element. @@ -27,15 +28,15 @@ class WebMVideoClient : public WebMParserClient { void Reset(); // Initialize |config| with the data in |codec_id|, |codec_private|, - // |is_encrypted| and the fields parsed from the last video track element this - // object was used to parse. + // |encryption_scheme| and the fields parsed from the last video track element + // this object was used to parse. // Returns true if |config| was successfully initialized. // Returns false if there was unexpected values in the provided parameters or // video track element fields. The contents of |config| are undefined in this // case and should not be relied upon. bool InitializeConfig(const std::string& codec_id, const std::vector<uint8_t>& codec_private, - bool is_encrypted, + const EncryptionScheme& encryption_scheme, VideoDecoderConfig* config); private: diff --git a/media/media.gyp b/media/media.gyp index f254b8f..0863c02 100644 --- a/media/media.gyp +++ b/media/media.gyp @@ -329,6 +329,8 @@ 'base/djb2.cc', 'base/djb2.h', 'base/eme_constants.h', + 'base/encryption_scheme.cc', + 'base/encryption_scheme.h', 'base/key_system_info.cc', 'base/key_system_info.h', 'base/key_systems.cc', diff --git a/media/mojo/common/media_type_converters.cc b/media/mojo/common/media_type_converters.cc index f1bf033..7725a2e 100644 --- a/media/mojo/common/media_type_converters.cc +++ b/media/mojo/common/media_type_converters.cc @@ -17,6 +17,7 @@ #include "media/base/decrypt_config.h" #include "media/base/decryptor.h" #include "media/base/demuxer_stream.h" +#include "media/base/encryption_scheme.h" #include "media/base/media_keys.h" #include "media/base/video_decoder_config.h" #include "media/base/video_frame.h" @@ -221,6 +222,20 @@ ASSERT_ENUM_EQ(VideoCodecProfile, , , VP9PROFILE_ANY); ASSERT_ENUM_EQ(VideoCodecProfile, , , VP9PROFILE_MAX); ASSERT_ENUM_EQ(VideoCodecProfile, , , VIDEO_CODEC_PROFILE_MAX); +// CipherMode +ASSERT_ENUM_EQ_RAW(EncryptionScheme::CipherMode, + EncryptionScheme::CipherMode::CIPHER_MODE_UNENCRYPTED, + CipherMode::UNENCRYPTED); +ASSERT_ENUM_EQ_RAW(EncryptionScheme::CipherMode, + EncryptionScheme::CipherMode::CIPHER_MODE_AES_CTR, + CipherMode::AES_CTR); +ASSERT_ENUM_EQ_RAW(EncryptionScheme::CipherMode, + EncryptionScheme::CipherMode::CIPHER_MODE_AES_CBC, + CipherMode::AES_CBC); +ASSERT_ENUM_EQ_RAW(EncryptionScheme::CipherMode, + EncryptionScheme::CipherMode::CIPHER_MODE_MAX, + CipherMode::MAX); + // Decryptor Status ASSERT_ENUM_EQ_RAW(Decryptor::Status, Decryptor::kSuccess, @@ -295,6 +310,59 @@ ASSERT_CDM_MESSAGE_TYPE(LICENSE_REQUEST); ASSERT_CDM_MESSAGE_TYPE(LICENSE_RENEWAL); ASSERT_CDM_MESSAGE_TYPE(LICENSE_RELEASE); +template <> +struct TypeConverter<media::interfaces::PatternPtr, + media::EncryptionScheme::Pattern> { + static media::interfaces::PatternPtr Convert( + const media::EncryptionScheme::Pattern& input); +}; +template <> +struct TypeConverter<media::EncryptionScheme::Pattern, + media::interfaces::PatternPtr> { + static media::EncryptionScheme::Pattern Convert( + const media::interfaces::PatternPtr& input); +}; + +// static +media::interfaces::PatternPtr +TypeConverter<media::interfaces::PatternPtr, media::EncryptionScheme::Pattern>:: + Convert(const media::EncryptionScheme::Pattern& input) { + media::interfaces::PatternPtr mojo_pattern(media::interfaces::Pattern::New()); + mojo_pattern->encrypt_blocks = input.encrypt_blocks(); + mojo_pattern->skip_blocks = input.skip_blocks(); + return mojo_pattern; +} + +// static +media::EncryptionScheme::Pattern +TypeConverter<media::EncryptionScheme::Pattern, media::interfaces::PatternPtr>:: + Convert(const media::interfaces::PatternPtr& input) { + return media::EncryptionScheme::Pattern(input->encrypt_blocks, + input->skip_blocks); +} + +// static +media::interfaces::EncryptionSchemePtr TypeConverter< + media::interfaces::EncryptionSchemePtr, + media::EncryptionScheme>::Convert(const media::EncryptionScheme& input) { + media::interfaces::EncryptionSchemePtr mojo_encryption_scheme( + media::interfaces::EncryptionScheme::New()); + mojo_encryption_scheme->mode = + static_cast<media::interfaces::CipherMode>(input.mode()); + mojo_encryption_scheme->pattern = + media::interfaces::Pattern::From(input.pattern()); + return mojo_encryption_scheme; +} + +// static +media::EncryptionScheme +TypeConverter<media::EncryptionScheme, media::interfaces::EncryptionSchemePtr>:: + Convert(const media::interfaces::EncryptionSchemePtr& input) { + return media::EncryptionScheme( + static_cast<media::EncryptionScheme::CipherMode>(input->mode), + input->pattern.To<media::EncryptionScheme::Pattern>()); +} + // static media::interfaces::SubsampleEntryPtr TypeConverter< media::interfaces::SubsampleEntryPtr, @@ -435,7 +503,8 @@ media::interfaces::AudioDecoderConfigPtr TypeConverter< } config->seek_preroll_usec = input.seek_preroll().InMicroseconds(); config->codec_delay = input.codec_delay(); - config->is_encrypted = input.is_encrypted(); + config->encryption_scheme = + media::interfaces::EncryptionScheme::From(input.encryption_scheme()); return config; } @@ -449,7 +518,7 @@ TypeConverter<media::AudioDecoderConfig, static_cast<media::SampleFormat>(input->sample_format), static_cast<media::ChannelLayout>(input->channel_layout), input->samples_per_second, input->extra_data.storage(), - input->is_encrypted, + input->encryption_scheme.To<media::EncryptionScheme>(), base::TimeDelta::FromMicroseconds(input->seek_preroll_usec), input->codec_delay); return config; @@ -474,7 +543,8 @@ media::interfaces::VideoDecoderConfigPtr TypeConverter< if (!input.extra_data().empty()) { config->extra_data = mojo::Array<uint8_t>::From(input.extra_data()); } - config->is_encrypted = input.is_encrypted(); + config->encryption_scheme = + media::interfaces::EncryptionScheme::From(input.encryption_scheme()); return config; } @@ -484,14 +554,14 @@ TypeConverter<media::VideoDecoderConfig, media::interfaces::VideoDecoderConfigPtr>:: Convert(const media::interfaces::VideoDecoderConfigPtr& input) { media::VideoDecoderConfig config; - config.Initialize(static_cast<media::VideoCodec>(input->codec), - static_cast<media::VideoCodecProfile>(input->profile), - static_cast<media::VideoPixelFormat>(input->format), - static_cast<media::ColorSpace>(input->color_space), - input->coded_size.To<gfx::Size>(), - input->visible_rect.To<gfx::Rect>(), - input->natural_size.To<gfx::Size>(), - input->extra_data.storage(), input->is_encrypted); + config.Initialize( + static_cast<media::VideoCodec>(input->codec), + static_cast<media::VideoCodecProfile>(input->profile), + static_cast<media::VideoPixelFormat>(input->format), + static_cast<media::ColorSpace>(input->color_space), + input->coded_size.To<gfx::Size>(), input->visible_rect.To<gfx::Rect>(), + input->natural_size.To<gfx::Size>(), input->extra_data.storage(), + input->encryption_scheme.To<media::EncryptionScheme>()); return config; } diff --git a/media/mojo/common/media_type_converters.h b/media/mojo/common/media_type_converters.h index 50cc30b..6b5664b 100644 --- a/media/mojo/common/media_type_converters.h +++ b/media/mojo/common/media_type_converters.h @@ -16,6 +16,7 @@ class AudioBuffer; class AudioDecoderConfig; class DecoderBuffer; class DecryptConfig; +class EncryptionScheme; class VideoDecoderConfig; class VideoFrame; struct CdmConfig; @@ -28,6 +29,19 @@ struct SubsampleEntry; namespace mojo { template <> +struct TypeConverter<media::interfaces::EncryptionSchemePtr, + media::EncryptionScheme> { + static media::interfaces::EncryptionSchemePtr Convert( + const media::EncryptionScheme& input); +}; +template <> +struct TypeConverter<media::EncryptionScheme, + media::interfaces::EncryptionSchemePtr> { + static media::EncryptionScheme Convert( + const media::interfaces::EncryptionSchemePtr& input); +}; + +template <> struct TypeConverter<media::interfaces::SubsampleEntryPtr, media::SubsampleEntry> { static media::interfaces::SubsampleEntryPtr Convert( diff --git a/media/mojo/common/media_type_converters_unittest.cc b/media/mojo/common/media_type_converters_unittest.cc index 9858cd0..5a2237f 100644 --- a/media/mojo/common/media_type_converters_unittest.cc +++ b/media/mojo/common/media_type_converters_unittest.cc @@ -13,6 +13,7 @@ #include "media/base/audio_decoder_config.h" #include "media/base/cdm_config.h" #include "media/base/decoder_buffer.h" +#include "media/base/encryption_scheme.h" #include "media/base/media_util.h" #include "media/base/sample_format.h" #include "media/base/test_helpers.h" @@ -287,7 +288,7 @@ TEST(MediaTypeConvertersTest, ConvertAudioDecoderConfig_Normal) { AudioDecoderConfig config; config.Initialize(kCodecAAC, kSampleFormatU8, CHANNEL_LAYOUT_SURROUND, 48000, - kExtraDataVector, false, base::TimeDelta(), 0); + kExtraDataVector, Unencrypted(), base::TimeDelta(), 0); interfaces::AudioDecoderConfigPtr ptr( interfaces::AudioDecoderConfig::From(config)); EXPECT_FALSE(ptr->extra_data.is_null()); @@ -298,7 +299,7 @@ TEST(MediaTypeConvertersTest, ConvertAudioDecoderConfig_Normal) { TEST(MediaTypeConvertersTest, ConvertAudioDecoderConfig_EmptyExtraData) { AudioDecoderConfig config; config.Initialize(kCodecAAC, kSampleFormatU8, CHANNEL_LAYOUT_SURROUND, 48000, - EmptyExtraData(), false, base::TimeDelta(), 0); + EmptyExtraData(), Unencrypted(), base::TimeDelta(), 0); interfaces::AudioDecoderConfigPtr ptr( interfaces::AudioDecoderConfig::From(config)); EXPECT_TRUE(ptr->extra_data.is_null()); @@ -309,14 +310,11 @@ TEST(MediaTypeConvertersTest, ConvertAudioDecoderConfig_EmptyExtraData) { TEST(MediaTypeConvertersTest, ConvertAudioDecoderConfig_Encrypted) { AudioDecoderConfig config; config.Initialize(kCodecAAC, kSampleFormatU8, CHANNEL_LAYOUT_SURROUND, 48000, - EmptyExtraData(), - true, // Is encrypted. + EmptyExtraData(), AesCtrEncryptionScheme(), base::TimeDelta(), 0); interfaces::AudioDecoderConfigPtr ptr( interfaces::AudioDecoderConfig::From(config)); - EXPECT_TRUE(ptr->is_encrypted); AudioDecoderConfig result(ptr.To<AudioDecoderConfig>()); - EXPECT_TRUE(result.is_encrypted()); EXPECT_TRUE(result.Matches(config)); } @@ -327,7 +325,7 @@ TEST(MediaTypeConvertersTest, ConvertVideoDecoderConfig_Normal) { VideoDecoderConfig config(kCodecVP8, VP8PROFILE_ANY, PIXEL_FORMAT_YV12, COLOR_SPACE_UNSPECIFIED, kCodedSize, kVisibleRect, - kNaturalSize, kExtraDataVector, false); + kNaturalSize, kExtraDataVector, Unencrypted()); interfaces::VideoDecoderConfigPtr ptr( interfaces::VideoDecoderConfig::From(config)); EXPECT_FALSE(ptr->extra_data.is_null()); @@ -338,7 +336,7 @@ TEST(MediaTypeConvertersTest, ConvertVideoDecoderConfig_Normal) { TEST(MediaTypeConvertersTest, ConvertVideoDecoderConfig_EmptyExtraData) { VideoDecoderConfig config(kCodecVP8, VP8PROFILE_ANY, PIXEL_FORMAT_YV12, COLOR_SPACE_UNSPECIFIED, kCodedSize, kVisibleRect, - kNaturalSize, EmptyExtraData(), false); + kNaturalSize, EmptyExtraData(), Unencrypted()); interfaces::VideoDecoderConfigPtr ptr( interfaces::VideoDecoderConfig::From(config)); EXPECT_TRUE(ptr->extra_data.is_null()); @@ -350,12 +348,10 @@ TEST(MediaTypeConvertersTest, ConvertVideoDecoderConfig_Encrypted) { VideoDecoderConfig config(kCodecVP8, VP8PROFILE_ANY, PIXEL_FORMAT_YV12, COLOR_SPACE_UNSPECIFIED, kCodedSize, kVisibleRect, kNaturalSize, EmptyExtraData(), - true /* is_encrypted */); + AesCtrEncryptionScheme()); interfaces::VideoDecoderConfigPtr ptr( interfaces::VideoDecoderConfig::From(config)); - EXPECT_TRUE(ptr->is_encrypted); VideoDecoderConfig result(ptr.To<VideoDecoderConfig>()); - EXPECT_TRUE(result.is_encrypted()); EXPECT_TRUE(result.Matches(config)); } @@ -458,4 +454,21 @@ TEST(MediaTypeConvertersTest, ConvertVideoFrame_ColorFrame) { CompareVideoFrames(frame, result); } +TEST(MediaTypeConvertersTest, ConvertEncryptionSchemeAesCbcWithPattern) { + // Original. + EncryptionScheme scheme(EncryptionScheme::CIPHER_MODE_AES_CBC, + EncryptionScheme::Pattern(1, 9)); + + // Convert to and back. + interfaces::EncryptionSchemePtr ptr( + interfaces::EncryptionScheme::From(scheme)); + EncryptionScheme result(ptr.To<EncryptionScheme>()); + + EXPECT_TRUE(result.Matches(scheme)); + + // Verify a couple of negative cases. + EXPECT_FALSE(result.Matches(Unencrypted())); + EXPECT_FALSE(result.Matches(AesCtrEncryptionScheme())); +} + } // namespace media diff --git a/media/mojo/interfaces/media_types.mojom b/media/mojo/interfaces/media_types.mojom index 44e6cdf..5f4d942 100644 --- a/media/mojo/interfaces/media_types.mojom +++ b/media/mojo/interfaces/media_types.mojom @@ -168,6 +168,29 @@ enum VideoCodecProfile { VIDEO_CODEC_PROFILE_MAX = VP9PROFILE_MAX, }; +// See media/base/encryption_scheme.h. +// Kept in sync with media::CipherMode via static_asserts. +enum CipherMode { + UNENCRYPTED = 0, + AES_CTR, + AES_CBC, + MAX = AES_CBC +}; + +// This defines a mojo transport format for media::EncryptionScheme::Pattern +// See media/base/encryption_scheme.h for description. +struct Pattern { + uint32 encrypt_blocks; + uint32 skip_blocks; +}; + +// This defines a mojo transport format for media::EncryptionScheme. +// See media/base/encryption_scheme.h for description. +struct EncryptionScheme { + CipherMode mode; + Pattern pattern; +}; + // This defines a mojo transport format for media::AudioDecoderConfig. // See media/base/audio_decoder_config.h for descriptions. struct AudioDecoderConfig { @@ -178,7 +201,7 @@ struct AudioDecoderConfig { array<uint8>? extra_data; int64 seek_preroll_usec; int32 codec_delay; - bool is_encrypted; + EncryptionScheme encryption_scheme; }; // This defines a mojo transport format for media::VideoDecoderConfig. @@ -192,7 +215,7 @@ struct VideoDecoderConfig { mojo.Rect visible_rect; mojo.Size natural_size; array<uint8>? extra_data; - bool is_encrypted; + EncryptionScheme encryption_scheme; }; // This defines a mojo transport format for media::SubsampleEntry. diff --git a/media/renderers/audio_renderer_impl_unittest.cc b/media/renderers/audio_renderer_impl_unittest.cc index 20c5fdb..0b6a3df 100644 --- a/media/renderers/audio_renderer_impl_unittest.cc +++ b/media/renderers/audio_renderer_impl_unittest.cc @@ -73,12 +73,9 @@ class AudioRendererImplTest : public ::testing::Test { demuxer_stream_(DemuxerStream::AUDIO), decoder_(new MockAudioDecoder()), ended_(false) { - AudioDecoderConfig audio_config(kCodec, - kSampleFormat, - kChannelLayout, - kInputSamplesPerSecond, - EmptyExtraData(), - false); + AudioDecoderConfig audio_config(kCodec, kSampleFormat, kChannelLayout, + kInputSamplesPerSecond, EmptyExtraData(), + Unencrypted()); demuxer_stream_.set_audio_decoder_config(audio_config); // Used to save callbacks and run them at a later time. |