Index: media/formats/mp4/mp4_stream_parser.cc |
diff --git a/media/formats/mp4/mp4_stream_parser.cc b/media/formats/mp4/mp4_stream_parser.cc |
index 8e8ec08b3898ab20bd27f4fc79110cbc44d1cd5f..97d474579af8d8b6e1728d88e1ba890d49988b18 100644 |
--- a/media/formats/mp4/mp4_stream_parser.cc |
+++ b/media/formats/mp4/mp4_stream_parser.cc |
@@ -17,6 +17,7 @@ |
#include "base/time/time.h" |
#include "build/build_config.h" |
#include "media/base/audio_decoder_config.h" |
+#include "media/base/encryption_scheme.h" |
#include "media/base/media_tracks.h" |
#include "media/base/media_util.h" |
#include "media/base/stream_parser_buffer.h" |
@@ -35,6 +36,41 @@ namespace mp4 { |
namespace { |
const int kMaxEmptySampleLogs = 20; |
+ |
+// Caller should be prepared to handle return of Unencrypted() in case of |
+// unsupported scheme. |
+EncryptionScheme GetEncryptionScheme(const ProtectionSchemeInfo& sinf) { |
+ if (!sinf.HasSupportedScheme()) |
+ return Unencrypted(); |
+ FourCC fourcc = sinf.type.type; |
+ EncryptionScheme::CipherMode mode = EncryptionScheme::CIPHER_MODE_UNENCRYPTED; |
+ EncryptionScheme::Pattern pattern; |
+#if BUILDFLAG(ENABLE_CBCS_ENCRYPTION_SCHEME) |
+ bool uses_pattern_encryption = false; |
+#endif |
+ switch (fourcc) { |
+ case FOURCC_CENC: |
+ mode = EncryptionScheme::CIPHER_MODE_AES_CTR; |
+ break; |
+#if BUILDFLAG(ENABLE_CBCS_ENCRYPTION_SCHEME) |
+ case FOURCC_CBCS: |
+ mode = EncryptionScheme::CIPHER_MODE_AES_CBC; |
+ uses_pattern_encryption = true; |
+ break; |
+#endif |
+ default: |
+ NOTREACHED(); |
+ break; |
+ } |
+#if BUILDFLAG(ENABLE_CBCS_ENCRYPTION_SCHEME) |
+ if (uses_pattern_encryption) { |
+ uint8_t crypt = sinf.info.track_encryption.default_crypt_byte_block; |
+ uint8_t skip = sinf.info.track_encryption.default_skip_byte_block; |
+ pattern = EncryptionScheme::Pattern(crypt, skip); |
+ } |
+#endif |
+ return EncryptionScheme(mode, pattern); |
+} |
} // namespace |
MP4StreamParser::MP4StreamParser(const std::set<int>& audio_object_types, |
@@ -317,10 +353,15 @@ bool MP4StreamParser::ParseMoov(BoxReader* reader) { |
} |
bool is_track_encrypted = entry.sinf.info.track_encryption.is_encrypted; |
is_track_encrypted_[audio_track_id] = is_track_encrypted; |
- audio_config.Initialize( |
- codec, sample_format, channel_layout, sample_per_second, extra_data, |
- is_track_encrypted ? AesCtrEncryptionScheme() : Unencrypted(), |
- base::TimeDelta(), 0); |
+ EncryptionScheme scheme = Unencrypted(); |
+ if (is_track_encrypted) { |
+ scheme = GetEncryptionScheme(entry.sinf); |
+ if (!scheme.is_encrypted()) |
+ return false; |
+ } |
+ audio_config.Initialize(codec, sample_format, channel_layout, |
+ sample_per_second, extra_data, scheme, |
+ base::TimeDelta(), 0); |
DVLOG(1) << "audio_track_id=" << audio_track_id |
<< " config=" << audio_config.AsHumanReadableString(); |
if (!audio_config.IsValidConfig()) { |
@@ -378,13 +419,18 @@ bool MP4StreamParser::ParseMoov(BoxReader* reader) { |
} |
bool is_track_encrypted = entry.sinf.info.track_encryption.is_encrypted; |
is_track_encrypted_[video_track_id] = is_track_encrypted; |
- video_config.Initialize( |
- entry.video_codec, entry.video_codec_profile, PIXEL_FORMAT_YV12, |
- 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 |
- EmptyExtraData(), |
- is_track_encrypted ? AesCtrEncryptionScheme() : Unencrypted()); |
+ EncryptionScheme scheme = Unencrypted(); |
+ if (is_track_encrypted) { |
+ scheme = GetEncryptionScheme(entry.sinf); |
+ if (!scheme.is_encrypted()) |
+ return false; |
+ } |
+ video_config.Initialize(entry.video_codec, entry.video_codec_profile, |
+ PIXEL_FORMAT_YV12, 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 |
+ EmptyExtraData(), scheme); |
DVLOG(1) << "video_track_id=" << video_track_id |
<< " config=" << video_config.AsHumanReadableString(); |
if (!video_config.IsValidConfig()) { |
@@ -622,11 +668,9 @@ bool MP4StreamParser::EnqueueSample(BufferQueueMap* buffers, bool* err) { |
if (decrypt_config) { |
if (!subsamples.empty()) { |
- // Create a new config with the updated subsamples. |
- decrypt_config.reset(new DecryptConfig( |
- decrypt_config->key_id(), |
- decrypt_config->iv(), |
- subsamples)); |
+ // Create a new config with the updated subsamples. |
+ decrypt_config.reset(new DecryptConfig(decrypt_config->key_id(), |
+ decrypt_config->iv(), subsamples)); |
} |
// else, use the existing config. |
} else if (is_track_encrypted_[runs_->track_id()]) { |