diff options
Diffstat (limited to 'media/base')
-rw-r--r-- | media/base/BUILD.gn | 2 | ||||
-rw-r--r-- | media/base/audio_decoder_config.cc | 25 | ||||
-rw-r--r-- | media/base/audio_decoder_config.h | 14 | ||||
-rw-r--r-- | media/base/encryption_scheme.cc | 37 | ||||
-rw-r--r-- | media/base/encryption_scheme.h | 79 | ||||
-rw-r--r-- | media/base/fake_demuxer_stream.cc | 10 | ||||
-rw-r--r-- | media/base/media_util.cc | 9 | ||||
-rw-r--r-- | media/base/media_util.h | 6 | ||||
-rw-r--r-- | media/base/test_helpers.cc | 9 | ||||
-rw-r--r-- | media/base/video_decoder_config.cc | 33 | ||||
-rw-r--r-- | media/base/video_decoder_config.h | 14 | ||||
-rw-r--r-- | media/base/video_decoder_config_unittest.cc | 14 |
12 files changed, 198 insertions, 54 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()); } |