summaryrefslogtreecommitdiff
path: root/chromium/media/formats
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/media/formats')
-rw-r--r--chromium/media/formats/BUILD.gn22
-rw-r--r--chromium/media/formats/ac3/ac3_util.cc10
-rw-r--r--chromium/media/formats/mp2t/es_parser_adts.cc10
-rw-r--r--chromium/media/formats/mp2t/es_parser_h264.cc28
-rw-r--r--chromium/media/formats/mp2t/mp2t_stream_parser.cc36
-rw-r--r--chromium/media/formats/mp2t/mp2t_stream_parser.h7
-rw-r--r--chromium/media/formats/mp2t/mp2t_stream_parser_unittest.cc3
-rw-r--r--chromium/media/formats/mp2t/ts_section_cets_ecm.cc9
-rw-r--r--chromium/media/formats/mp2t/ts_section_cets_ecm.h20
-rw-r--r--chromium/media/formats/mp4/box_definitions.cc25
-rw-r--r--chromium/media/formats/mp4/box_definitions.h8
-rw-r--r--chromium/media/formats/mp4/box_reader.cc9
-rw-r--r--chromium/media/formats/mp4/box_reader.h12
-rw-r--r--chromium/media/formats/mp4/fourccs.h5
-rw-r--r--chromium/media/formats/mp4/mp4_stream_parser.cc103
-rw-r--r--chromium/media/formats/mp4/mp4_stream_parser.h7
-rw-r--r--chromium/media/formats/mp4/mp4_stream_parser_unittest.cc60
-rw-r--r--chromium/media/formats/mp4/track_run_iterator.cc87
-rw-r--r--chromium/media/formats/mp4/track_run_iterator.h1
-rw-r--r--chromium/media/formats/mpeg/mpeg_audio_stream_parser_base.cc1
-rw-r--r--chromium/media/formats/webm/webm_crypto_helpers.cc15
-rw-r--r--chromium/media/formats/webm/webm_crypto_helpers.h10
-rw-r--r--chromium/media/formats/webm/webm_crypto_helpers_unittest.cc10
-rw-r--r--chromium/media/formats/webm/webm_parser_unittest.cc2
-rw-r--r--chromium/media/formats/webm/webm_stream_parser_unittest.cc32
-rw-r--r--chromium/media/formats/webm/webm_video_client.cc2
26 files changed, 406 insertions, 128 deletions
diff --git a/chromium/media/formats/BUILD.gn b/chromium/media/formats/BUILD.gn
index 0b58533cbf1..1ed89cb5a83 100644
--- a/chromium/media/formats/BUILD.gn
+++ b/chromium/media/formats/BUILD.gn
@@ -72,7 +72,7 @@ source_set("formats") {
deps = [
"//media/base",
"//skia",
- "//third_party/libaom:av1_features",
+ "//third_party/libaom:av1_buildflags",
]
configs += [
@@ -162,6 +162,8 @@ static_library("test_support") {
visibility = [ "//media:test_support" ]
sources = [
+ "common/stream_parser_test_base.cc",
+ "common/stream_parser_test_base.h",
"webm/cluster_builder.cc",
"webm/cluster_builder.h",
"webm/opus_packet_builder.cc",
@@ -178,22 +180,14 @@ static_library("test_support") {
deps = [
"//base/test:test_support",
"//media/base:test_support",
+ "//testing/gtest",
]
- if (proprietary_codecs) {
+ if (proprietary_codecs && enable_mse_mpeg2ts_stream_parser) {
sources += [
- "common/stream_parser_test_base.cc",
- "common/stream_parser_test_base.h",
+ "mp2t/es_parser_test_base.cc",
+ "mp2t/es_parser_test_base.h",
]
-
- deps += [ "//testing/gtest" ]
-
- if (enable_mse_mpeg2ts_stream_parser) {
- sources += [
- "mp2t/es_parser_test_base.cc",
- "mp2t/es_parser_test_base.h",
- ]
- }
}
}
@@ -202,6 +196,7 @@ source_set("unit_tests") {
sources = [
"ac3/ac3_util_unittest.cc",
"common/offset_byte_queue_unittest.cc",
+ "mpeg/mpeg1_audio_stream_parser_unittest.cc",
"webm/webm_cluster_parser_unittest.cc",
"webm/webm_content_encodings_client_unittest.cc",
"webm/webm_crypto_helpers_unittest.cc",
@@ -234,7 +229,6 @@ source_set("unit_tests") {
"mp4/sample_to_group_iterator_unittest.cc",
"mp4/track_run_iterator_unittest.cc",
"mpeg/adts_stream_parser_unittest.cc",
- "mpeg/mpeg1_audio_stream_parser_unittest.cc",
]
deps += [ "//crypto" ]
diff --git a/chromium/media/formats/ac3/ac3_util.cc b/chromium/media/formats/ac3/ac3_util.cc
index 8d0b7869ec0..2c28262da9e 100644
--- a/chromium/media/formats/ac3/ac3_util.cc
+++ b/chromium/media/formats/ac3/ac3_util.cc
@@ -86,7 +86,7 @@ const uint8_t* FindNextSyncWord(const uint8_t* const begin,
while (current < end - 1) {
if (current[0] == 0x0B && current[1] == 0x77) {
if (current != begin)
- DVLOG(2) << __FUNCTION__ << " skip " << current - begin << " bytes.";
+ DVLOG(2) << __func__ << " skip " << current - begin << " bytes.";
return current;
} else if (current[1] != 0x0B) {
@@ -124,7 +124,7 @@ int ParseAc3SyncFrameSize(Ac3Header& header) {
if (header.sample_rate_code() >= arraysize(kSampleRate) ||
header.ac3_frame_size_code() >=
arraysize(kSyncFrameSizeInWordsFor44kHz)) {
- DVLOG(2) << __FUNCTION__ << " Invalid frame header."
+ DVLOG(2) << __func__ << " Invalid frame header."
<< " fscod:" << header.sample_rate_code()
<< " frmsizecod:" << header.ac3_frame_size_code();
return -1;
@@ -171,15 +171,15 @@ int ParseTotalSampleCount(const uint8_t* data, size_t size, bool is_eac3) {
if (frame_size > 0 && sample_count > 0) {
current += frame_size;
if (current > end) {
- DVLOG(2) << __FUNCTION__ << " Incomplete frame, missing "
- << current - end << " bytes.";
+ DVLOG(2) << __func__ << " Incomplete frame, missing " << current - end
+ << " bytes.";
break;
}
total_sample_count += sample_count;
} else {
DVLOG(2)
- << __FUNCTION__
+ << __func__
<< " Invalid frame, skip 2 bytes to find next synchronization word.";
current += 2;
}
diff --git a/chromium/media/formats/mp2t/es_parser_adts.cc b/chromium/media/formats/mp2t/es_parser_adts.cc
index f27c91bfcde..7a2dbb5c469 100644
--- a/chromium/media/formats/mp2t/es_parser_adts.cc
+++ b/chromium/media/formats/mp2t/es_parser_adts.cc
@@ -9,6 +9,7 @@
#include <vector>
#include "base/logging.h"
+#include "base/optional.h"
#include "base/strings/string_number_conversions.h"
#include "media/base/audio_timestamp_helper.h"
#include "media/base/bit_reader.h"
@@ -215,10 +216,11 @@ bool EsParserAdts::ParseFromEsQueue() {
if (base_decrypt_config) {
std::vector<SubsampleEntry> subsamples;
CalculateSubsamplesForAdtsFrame(adts_frame, &subsamples);
- std::unique_ptr<DecryptConfig> decrypt_config(
- new DecryptConfig(base_decrypt_config->key_id(),
- base_decrypt_config->iv(), subsamples));
- stream_parser_buffer->set_decrypt_config(std::move(decrypt_config));
+ stream_parser_buffer->set_decrypt_config(
+ std::make_unique<DecryptConfig>(
+ base_decrypt_config->encryption_mode(),
+ base_decrypt_config->key_id(), base_decrypt_config->iv(),
+ subsamples, base_decrypt_config->encryption_pattern()));
}
}
#endif
diff --git a/chromium/media/formats/mp2t/es_parser_h264.cc b/chromium/media/formats/mp2t/es_parser_h264.cc
index 3b2099f20a0..887b89879ef 100644
--- a/chromium/media/formats/mp2t/es_parser_h264.cc
+++ b/chromium/media/formats/mp2t/es_parser_h264.cc
@@ -466,9 +466,31 @@ bool EsParserH264::EmitFrame(int64_t access_unit_pos,
stream_parser_buffer->set_timestamp(current_timing_desc.pts);
#if BUILDFLAG(ENABLE_HLS_SAMPLE_AES)
if (use_hls_sample_aes_ && base_decrypt_config) {
- std::unique_ptr<DecryptConfig> decrypt_config(new DecryptConfig(
- base_decrypt_config->key_id(), base_decrypt_config->iv(), subsamples));
- stream_parser_buffer->set_decrypt_config(std::move(decrypt_config));
+ switch (base_decrypt_config->encryption_mode()) {
+ case EncryptionMode::kUnencrypted:
+ // As |base_decrypt_config| is specified, the stream is encrypted,
+ // so this shouldn't happen.
+ NOTREACHED();
+ break;
+ case EncryptionMode::kCenc:
+ stream_parser_buffer->set_decrypt_config(
+ DecryptConfig::CreateCencConfig(base_decrypt_config->key_id(),
+ base_decrypt_config->iv(),
+ subsamples));
+ break;
+ case EncryptionMode::kCbcs:
+ // Note that for SampleAES the (encrypt,skip) pattern is constant.
+ // If not specified in |base_decrypt_config|, use default values.
+ stream_parser_buffer->set_decrypt_config(
+ DecryptConfig::CreateCbcsConfig(
+ base_decrypt_config->key_id(), base_decrypt_config->iv(),
+ subsamples,
+ base_decrypt_config->HasPattern()
+ ? base_decrypt_config->encryption_pattern()
+ : EncryptionPattern(kSampleAESEncryptBlocks,
+ kSampleAESSkipBlocks)));
+ break;
+ }
}
#endif
return es_adapter_.OnNewBuffer(stream_parser_buffer);
diff --git a/chromium/media/formats/mp2t/mp2t_stream_parser.cc b/chromium/media/formats/mp2t/mp2t_stream_parser.cc
index cd4a8bccab6..60ccf910e2d 100644
--- a/chromium/media/formats/mp2t/mp2t_stream_parser.cc
+++ b/chromium/media/formats/mp2t/mp2t_stream_parser.cc
@@ -9,6 +9,7 @@
#include "base/bind.h"
#include "base/callback_helpers.h"
+#include "base/optional.h"
#include "media/base/media_tracks.h"
#include "media/base/stream_parser_buffer.h"
#include "media/base/text_track_config.h"
@@ -843,8 +844,9 @@ void Mp2tStreamParser::UnregisterCat() {
}
void Mp2tStreamParser::RegisterCencPids(int ca_pid, int pssh_pid) {
- std::unique_ptr<TsSectionCetsEcm> ecm_parser(new TsSectionCetsEcm(base::Bind(
- &Mp2tStreamParser::RegisterDecryptConfig, base::Unretained(this))));
+ std::unique_ptr<TsSectionCetsEcm> ecm_parser(
+ new TsSectionCetsEcm(base::BindRepeating(
+ &Mp2tStreamParser::RegisterNewKeyIdAndIv, base::Unretained(this))));
std::unique_ptr<PidState> ecm_pid_state(
new PidState(ca_pid, PidState::kPidCetsEcm, std::move(ecm_parser)));
ecm_pid_state->Enable();
@@ -883,12 +885,34 @@ void Mp2tStreamParser::RegisterEncryptionScheme(
// Reset the DecryptConfig, so that unless and until a CENC-ECM (containing
// key id and IV) is seen, media data will be considered unencrypted. This is
// similar to the way clear leaders can occur in MP4 containers.
- decrypt_config_.reset(nullptr);
+ decrypt_config_.reset();
}
-void Mp2tStreamParser::RegisterDecryptConfig(const DecryptConfig& config) {
- decrypt_config_.reset(
- new DecryptConfig(config.key_id(), config.iv(), config.subsamples()));
+void Mp2tStreamParser::RegisterNewKeyIdAndIv(const std::string& key_id,
+ const std::string& iv) {
+ if (!iv.empty()) {
+ switch (initial_scheme_.mode()) {
+ case EncryptionScheme::CIPHER_MODE_UNENCRYPTED:
+ decrypt_config_.reset();
+ break;
+ case EncryptionScheme::CIPHER_MODE_AES_CTR:
+ decrypt_config_ = DecryptConfig::CreateCencConfig(key_id, iv, {});
+ break;
+ case EncryptionScheme::CIPHER_MODE_AES_CBC:
+ // MP2 Transport Streams don't always specify the encryption pattern up
+ // front. Instead it is determined later by the stream type. So if the
+ // pattern is unknown, leave it out.
+ EncryptionPattern pattern = initial_scheme_.pattern();
+ if (pattern.IsInEffect()) {
+ decrypt_config_ =
+ DecryptConfig::CreateCbcsConfig(key_id, iv, {}, pattern);
+ } else {
+ decrypt_config_ =
+ DecryptConfig::CreateCbcsConfig(key_id, iv, {}, base::nullopt);
+ }
+ break;
+ }
+ }
}
void Mp2tStreamParser::RegisterPsshBoxes(
diff --git a/chromium/media/formats/mp2t/mp2t_stream_parser.h b/chromium/media/formats/mp2t/mp2t_stream_parser.h
index 835fafe7400..e46327b723c 100644
--- a/chromium/media/formats/mp2t/mp2t_stream_parser.h
+++ b/chromium/media/formats/mp2t/mp2t_stream_parser.h
@@ -125,8 +125,8 @@ class MEDIA_EXPORT Mp2tStreamParser : public StreamParser {
// be the case during an unencrypted portion of a live stream.
void RegisterEncryptionScheme(const EncryptionScheme& scheme);
- // Register the DecryptConfig (parsed from CENC-ECM).
- void RegisterDecryptConfig(const DecryptConfig& config);
+ // Register the new KeyID and IV (parsed from CENC-ECM).
+ void RegisterNewKeyIdAndIv(const std::string& key_id, const std::string& iv);
// Register the PSSH (parsed from CENC-PSSH).
void RegisterPsshBoxes(const std::vector<uint8_t>& init_data);
@@ -173,6 +173,9 @@ class MEDIA_EXPORT Mp2tStreamParser : public StreamParser {
#if BUILDFLAG(ENABLE_HLS_SAMPLE_AES)
EncryptionScheme initial_scheme_;
+
+ // TODO(jrummell): Rather than store the key_id and iv in a DecryptConfig,
+ // provide a better way to access the last values seen in a ECM packet.
std::unique_ptr<DecryptConfig> decrypt_config_;
#endif
diff --git a/chromium/media/formats/mp2t/mp2t_stream_parser_unittest.cc b/chromium/media/formats/mp2t/mp2t_stream_parser_unittest.cc
index 137a74246a2..a0ae6df897e 100644
--- a/chromium/media/formats/mp2t/mp2t_stream_parser_unittest.cc
+++ b/chromium/media/formats/mp2t/mp2t_stream_parser_unittest.cc
@@ -127,8 +127,7 @@ std::string DecryptBuffer(const StreamParserBuffer& buffer,
EXPECT_TRUE(scheme.is_encrypted());
EXPECT_TRUE(scheme.mode() == EncryptionScheme::CIPHER_MODE_AES_CBC);
bool has_pattern = scheme.pattern().IsInEffect();
- EXPECT_TRUE(!has_pattern ||
- scheme.pattern().Matches(EncryptionPattern(1, 9)));
+ EXPECT_TRUE(!has_pattern || scheme.pattern() == EncryptionPattern(1, 9));
std::string key;
EXPECT_TRUE(
diff --git a/chromium/media/formats/mp2t/ts_section_cets_ecm.cc b/chromium/media/formats/mp2t/ts_section_cets_ecm.cc
index 1679c030718..a50dec10152 100644
--- a/chromium/media/formats/mp2t/ts_section_cets_ecm.cc
+++ b/chromium/media/formats/mp2t/ts_section_cets_ecm.cc
@@ -6,15 +6,14 @@
#include "base/logging.h"
#include "media/base/bit_reader.h"
-#include "media/base/decrypt_config.h"
#include "media/formats/mp2t/mp2t_common.h"
namespace media {
namespace mp2t {
TsSectionCetsEcm::TsSectionCetsEcm(
- const RegisterDecryptConfigCb& register_decrypt_config_cb)
- : register_decrypt_config_cb_(register_decrypt_config_cb) {}
+ const RegisterNewKeyIdAndIvCB& register_new_key_id_and_iv_cb)
+ : register_new_key_id_and_iv_cb_(register_new_key_id_and_iv_cb) {}
TsSectionCetsEcm::~TsSectionCetsEcm() {}
@@ -33,7 +32,6 @@ bool TsSectionCetsEcm::Parse(bool payload_unit_start_indicator,
bool key_id_flag;
int au_byte_offset_size;
std::string iv;
- std::vector<SubsampleEntry> subsamples_empty;
// TODO(dougsteed). Currently we allow only a subset of the possible values.
// When we flesh out this implementation to cover all of ISO/IEC 23001-9 we
// will need to generalize this.
@@ -67,8 +65,7 @@ bool TsSectionCetsEcm::Parse(bool payload_unit_start_indicator,
// The CETS-ECM is supposed to use adaptation field stuffing to fill the TS
// packet, so there should be no data left to read.
RCHECK(bit_reader.bits_available() == 0);
- DecryptConfig decrypt_config(key_id, iv, subsamples_empty);
- register_decrypt_config_cb_.Run(decrypt_config);
+ register_new_key_id_and_iv_cb_.Run(key_id, iv);
return true;
}
diff --git a/chromium/media/formats/mp2t/ts_section_cets_ecm.h b/chromium/media/formats/mp2t/ts_section_cets_ecm.h
index c07be4a0d58..6d17b8bff37 100644
--- a/chromium/media/formats/mp2t/ts_section_cets_ecm.h
+++ b/chromium/media/formats/mp2t/ts_section_cets_ecm.h
@@ -7,24 +7,28 @@
#include <stdint.h>
+#include <string>
+
#include "base/callback.h"
#include "base/macros.h"
-#include "media/base/byte_queue.h"
#include "media/formats/mp2t/ts_section.h"
namespace media {
-class DecryptConfig;
-
namespace mp2t {
class TsSectionCetsEcm : public TsSection {
public:
- // RegisterDecryptConfigCb::Run(const DecryptConfig& decrypt_config);
- using RegisterDecryptConfigCb =
- base::Callback<void(const DecryptConfig& decrypt_config)>;
+ // RegisterNewKeyIdAndIvCB() may be called multiple times. From
+ // ISO/IEC 23001-9:2016, section 7.2: "Key/IV information for every
+ // encrypted PID should be carried in a separate ECM PID." So there may be
+ // ECM's for each audio and video stream (and more if key rotation is used).
+ using RegisterNewKeyIdAndIvCB =
+ base::RepeatingCallback<void(const std::string& key_id,
+ const std::string& iv)>;
+
explicit TsSectionCetsEcm(
- const RegisterDecryptConfigCb& register_decrypt_config_cb);
+ const RegisterNewKeyIdAndIvCB& register_new_key_id_and_iv_cb);
~TsSectionCetsEcm() override;
// TsSection implementation.
@@ -35,7 +39,7 @@ class TsSectionCetsEcm : public TsSection {
void Reset() override;
private:
- RegisterDecryptConfigCb register_decrypt_config_cb_;
+ RegisterNewKeyIdAndIvCB register_new_key_id_and_iv_cb_;
DISALLOW_COPY_AND_ASSIGN(TsSectionCetsEcm);
};
diff --git a/chromium/media/formats/mp4/box_definitions.cc b/chromium/media/formats/mp4/box_definitions.cc
index 307419e733f..6def180d143 100644
--- a/chromium/media/formats/mp4/box_definitions.cc
+++ b/chromium/media/formats/mp4/box_definitions.cc
@@ -17,7 +17,7 @@
#include "media/formats/mp4/es_descriptor.h"
#include "media/formats/mp4/rcheck.h"
#include "media/media_buildflags.h"
-#include "third_party/libaom/av1_features.h"
+#include "third_party/libaom/av1_buildflags.h"
#if BUILDFLAG(USE_PROPRIETARY_CODECS)
#include "media/formats/mp4/avc.h"
@@ -341,16 +341,25 @@ bool ProtectionSchemeInfo::Parse(BoxReader* reader) {
}
bool ProtectionSchemeInfo::HasSupportedScheme() const {
- FourCC fourCC = type.type;
- if (fourCC == FOURCC_CENC)
+ FourCC four_cc = type.type;
+ if (four_cc == FOURCC_CENC)
return true;
#if BUILDFLAG(ENABLE_CBCS_ENCRYPTION_SCHEME)
- if (fourCC == FOURCC_CBCS)
+ if (four_cc == FOURCC_CBCS)
return true;
#endif
return false;
}
+bool ProtectionSchemeInfo::IsCbcsEncryptionScheme() const {
+#if BUILDFLAG(ENABLE_CBCS_ENCRYPTION_SCHEME)
+ FourCC four_cc = type.type;
+ return (four_cc == FOURCC_CBCS);
+#else
+ return false;
+#endif
+}
+
MovieHeader::MovieHeader()
: version(0),
creation_time(0),
@@ -386,7 +395,7 @@ bool MovieHeader::Parse(BoxReader* reader) {
RCHECK(reader->Read4s(&rate) &&
reader->Read2s(&volume) &&
reader->SkipBytes(10) && // reserved
- reader->SkipBytes(36) && // matrix
+ reader->ReadDisplayMatrix(display_matrix) &&
reader->SkipBytes(24) && // predefined zero
reader->Read4(&next_track_id));
return true;
@@ -427,7 +436,7 @@ bool TrackHeader::Parse(BoxReader* reader) {
reader->Read2s(&alternate_group) &&
reader->Read2s(&volume) &&
reader->SkipBytes(2) && // reserved
- reader->SkipBytes(36) && // matrix
+ reader->ReadDisplayMatrix(display_matrix) &&
reader->Read4(&width) &&
reader->Read4(&height));
@@ -1031,10 +1040,6 @@ bool AudioSampleEntry::Parse(BoxReader* reader) {
// Read the FLACSpecificBox, even if CENC is signalled.
if (format == FOURCC_FLAC ||
(format == FOURCC_ENCA && sinf.format.format == FOURCC_FLAC)) {
- RCHECK_MEDIA_LOGGED(base::FeatureList::IsEnabled(kMseFlacInIsobmff),
- reader->media_log(),
- "MSE support for FLAC in MP4 is not enabled.");
-
RCHECK_MEDIA_LOGGED(reader->ReadChild(&dfla), reader->media_log(),
"Failure parsing FLACSpecificBox (dfLa)");
diff --git a/chromium/media/formats/mp4/box_definitions.h b/chromium/media/formats/mp4/box_definitions.h
index c251c8b0e18..847c6b7e86b 100644
--- a/chromium/media/formats/mp4/box_definitions.h
+++ b/chromium/media/formats/mp4/box_definitions.h
@@ -155,6 +155,7 @@ struct MEDIA_EXPORT ProtectionSchemeInfo : Box {
SchemeInfo info;
bool HasSupportedScheme() const;
+ bool IsCbcsEncryptionScheme() const;
};
struct MEDIA_EXPORT MovieHeader : Box {
@@ -167,6 +168,12 @@ struct MEDIA_EXPORT MovieHeader : Box {
uint64_t duration;
int32_t rate;
int16_t volume;
+ // A 3x3 matrix of [ A B C ]
+ // [ D E F ]
+ // [ U V W ]
+ // Where A-F are 16.16 fixed point decimals
+ // And U, V, W are 2.30 fixed point decimals.
+ DisplayMatrix display_matrix;
uint32_t next_track_id;
};
@@ -180,6 +187,7 @@ struct MEDIA_EXPORT TrackHeader : Box {
int16_t layer;
int16_t alternate_group;
int16_t volume;
+ DisplayMatrix display_matrix; // See MovieHeader.display_matrix
uint32_t width;
uint32_t height;
};
diff --git a/chromium/media/formats/mp4/box_reader.cc b/chromium/media/formats/mp4/box_reader.cc
index bf7e2653c79..cbcd48cff26 100644
--- a/chromium/media/formats/mp4/box_reader.cc
+++ b/chromium/media/formats/mp4/box_reader.cc
@@ -204,6 +204,15 @@ bool BoxReader::ScanChildren() {
return true;
}
+bool BoxReader::ReadDisplayMatrix(DisplayMatrix matrix) {
+ for (int i = 0; i < kDisplayMatrixDimension; i++) {
+ if (!Read4s(&matrix[i])) {
+ return false;
+ }
+ }
+ return true;
+}
+
bool BoxReader::HasChild(Box* child) {
DCHECK(scanned_);
DCHECK(child);
diff --git a/chromium/media/formats/mp4/box_reader.h b/chromium/media/formats/mp4/box_reader.h
index 140818aaa4a..2da377323fd 100644
--- a/chromium/media/formats/mp4/box_reader.h
+++ b/chromium/media/formats/mp4/box_reader.h
@@ -24,6 +24,14 @@
namespace media {
namespace mp4 {
+enum DisplayMatrixSize {
+ kDisplayMatrixWidth = 3,
+ kDisplayMatrixHeight = 3,
+ kDisplayMatrixDimension = kDisplayMatrixHeight * kDisplayMatrixWidth
+};
+
+using DisplayMatrix = int32_t[kDisplayMatrixDimension];
+
class BoxReader;
struct MEDIA_EXPORT Box {
@@ -145,6 +153,10 @@ class MEDIA_EXPORT BoxReader : public BufferReader {
// read or on child absent.
bool MaybeReadChild(Box* child) WARN_UNUSED_RESULT;
+ // ISO-BMFF streams files use a 3x3 matrix consisting of 6 16.16 fixed point
+ // decimals and 3 2.30 fixed point decimals.
+ bool ReadDisplayMatrix(DisplayMatrix matrix);
+
// Read at least one child. False means error or no such child present.
template<typename T> bool ReadChildren(
std::vector<T>* children) WARN_UNUSED_RESULT;
diff --git a/chromium/media/formats/mp4/fourccs.h b/chromium/media/formats/mp4/fourccs.h
index bdf3d5faf5e..6d028ac788a 100644
--- a/chromium/media/formats/mp4/fourccs.h
+++ b/chromium/media/formats/mp4/fourccs.h
@@ -8,7 +8,7 @@
#include <string>
#include "media/media_buildflags.h"
-#include "third_party/libaom/av1_features.h"
+#include "third_party/libaom/av1_buildflags.h"
namespace media {
namespace mp4 {
@@ -67,6 +67,9 @@ enum FourCC {
FOURCC_META = 0x6d657461,
FOURCC_MFHD = 0x6d666864,
FOURCC_MFRA = 0x6d667261,
+#if BUILDFLAG(ENABLE_MPEG_H_AUDIO_DEMUXING)
+ FOURCC_MHM1 = 0x6d686d31,
+#endif
FOURCC_MINF = 0x6d696e66,
FOURCC_MOOF = 0x6d6f6f66,
FOURCC_MOOV = 0x6d6f6f76,
diff --git a/chromium/media/formats/mp4/mp4_stream_parser.cc b/chromium/media/formats/mp4/mp4_stream_parser.cc
index f2027534916..ee14479e26a 100644
--- a/chromium/media/formats/mp4/mp4_stream_parser.cc
+++ b/chromium/media/formats/mp4/mp4_stream_parser.cc
@@ -13,6 +13,7 @@
#include "base/callback_helpers.h"
#include "base/logging.h"
+#include "base/numerics/math_constants.h"
#include "base/strings/string_number_conversions.h"
#include "base/time/time.h"
#include "build/build_config.h"
@@ -37,6 +38,7 @@ namespace media {
namespace mp4 {
namespace {
+
const int kMaxEmptySampleLogs = 20;
const int kMaxInvalidConversionLogs = 20;
@@ -89,7 +91,6 @@ MP4StreamParser::MP4StreamParser(const std::set<int>& audio_object_types,
has_flac_(has_flac),
num_empty_samples_skipped_(0),
num_invalid_conversions_(0) {
- DCHECK(!has_flac || base::FeatureList::IsEnabled(kMseFlacInIsobmff));
}
MP4StreamParser::~MP4StreamParser() = default;
@@ -238,13 +239,77 @@ ParseResult MP4StreamParser::ParseBox() {
return ParseResult::kOk;
}
+static inline double FixedToFloatingPoint(const int32_t& i) {
+ return static_cast<double>(i >> 16);
+}
+
+VideoRotation MP4StreamParser::CalculateRotation(const TrackHeader& track,
+ const MovieHeader& movie) {
+ static_assert(kDisplayMatrixDimension == 9, "Display matrix must be 3x3");
+ // 3x3 matrix: [ a b c ]
+ // [ d e f ]
+ // [ x y z ]
+ int32_t rotation_matrix[kDisplayMatrixDimension] = {0};
+
+ // Shift values for fixed point multiplications.
+ const int32_t shifts[kDisplayMatrixHeight] = {16, 16, 30};
+
+ // Matrix multiplication for
+ // track.display_matrix * movie.display_matrix
+ // with special consideration taken that entries a-f are 16.16 fixed point
+ // decimals and x-z are 2.30 fixed point decimals.
+ for (int i = 0; i < kDisplayMatrixWidth; i++) {
+ for (int j = 0; j < kDisplayMatrixHeight; j++) {
+ for (int e = 0; e < kDisplayMatrixHeight; e++) {
+ rotation_matrix[i * kDisplayMatrixHeight + j] +=
+ ((int64_t)track.display_matrix[i * kDisplayMatrixHeight + e] *
+ movie.display_matrix[e * kDisplayMatrixHeight + j]) >>
+ shifts[e];
+ }
+ }
+ }
+
+ // Rotation by angle Θ is represented in the matrix as:
+ // [ cos(Θ), -sin(Θ), ...]
+ // [ sin(Θ), cos(Θ), ...]
+ // [ ..., ..., 1 ]
+ // But we only need cos(Θ) for the angle and sin(Θ) for the quadrant.
+ double angle = acos(FixedToFloatingPoint(rotation_matrix[0]))
+ * 180 / base::kPiDouble;
+
+ if (angle < 0)
+ angle += 360;
+
+ if (angle >= 360)
+ angle -= 360;
+
+ // 16 bits of fixed point decimal is enough to give 6 decimals of precision
+ // to cos(Θ). A delta of ±0.000001 causes acos(cos(Θ)) to differ by a minimum
+ // of 0.0002, which is why we only need to check that the angle is only
+ // accurate to within four decimal places. This is preferred to checking for
+ // a more precise accuracy, as the 'double' type is architecture dependant and
+ // ther may variance in floating point errors.
+ if (abs(angle - 0) < 1e-4)
+ return VIDEO_ROTATION_0;
+
+ if (abs(angle - 180) < 1e-4)
+ return VIDEO_ROTATION_180;
+
+ if (abs(angle - 90) < 1e-4) {
+ bool quadrant = asin(FixedToFloatingPoint(rotation_matrix[3])) < 0;
+ return quadrant ? VIDEO_ROTATION_90 : VIDEO_ROTATION_270;
+ }
+
+ // TODO(tmathmeyer): Record this event and the faulty matrix somewhere.
+ return VIDEO_ROTATION_0;
+}
+
bool MP4StreamParser::ParseMoov(BoxReader* reader) {
moov_.reset(new Movie);
RCHECK(moov_->Parse(reader));
runs_.reset();
audio_track_ids_.clear();
video_track_ids_.clear();
- is_track_encrypted_.clear();
has_audio_ = false;
has_video_ = false;
@@ -292,12 +357,14 @@ bool MP4StreamParser::ParseMoov(BoxReader* reader) {
? entry.sinf.format.format
: entry.format;
+ if (audio_format != FOURCC_FLAC &&
#if BUILDFLAG(ENABLE_AC3_EAC3_AUDIO_DEMUXING)
- if (audio_format != FOURCC_MP4A && audio_format != FOURCC_FLAC &&
- audio_format != FOURCC_AC3 && audio_format != FOURCC_EAC3) {
-#else
- if (audio_format != FOURCC_MP4A && audio_format != FOURCC_FLAC) {
+ audio_format != FOURCC_AC3 && audio_format != FOURCC_EAC3 &&
#endif
+#if BUILDFLAG(ENABLE_MPEG_H_AUDIO_DEMUXING)
+ audio_format != FOURCC_MHM1 &&
+#endif
+ audio_format != FOURCC_MP4A) {
MEDIA_LOG(ERROR, media_log_) << "Unsupported audio format 0x"
<< std::hex << entry.format
<< " in stsd box.";
@@ -324,6 +391,13 @@ bool MP4StreamParser::ParseMoov(BoxReader* reader) {
sample_per_second = entry.samplerate;
extra_data = entry.dfla.stream_info;
#if BUILDFLAG(USE_PROPRIETARY_CODECS)
+#if BUILDFLAG(ENABLE_MPEG_H_AUDIO_DEMUXING)
+ } else if (audio_format == FOURCC_MHM1) {
+ codec = kCodecMpegHAudio;
+ channel_layout = CHANNEL_LAYOUT_BITSTREAM;
+ sample_per_second = entry.samplerate;
+ extra_data = entry.dfla.stream_info;
+#endif
} else {
uint8_t audio_type = entry.esds.object_type;
#if BUILDFLAG(ENABLE_AC3_EAC3_AUDIO_DEMUXING)
@@ -394,7 +468,6 @@ bool MP4StreamParser::ParseMoov(BoxReader* reader) {
return false;
}
bool is_track_encrypted = entry.sinf.info.track_encryption.is_encrypted;
- is_track_encrypted_[audio_track_id] = is_track_encrypted;
EncryptionScheme scheme = Unencrypted();
if (is_track_encrypted) {
scheme = GetEncryptionScheme(entry.sinf);
@@ -463,7 +536,6 @@ bool MP4StreamParser::ParseMoov(BoxReader* reader) {
return false;
}
bool is_track_encrypted = entry.sinf.info.track_encryption.is_encrypted;
- is_track_encrypted_[video_track_id] = is_track_encrypted;
EncryptionScheme scheme = Unencrypted();
if (is_track_encrypted) {
scheme = GetEncryptionScheme(entry.sinf);
@@ -472,8 +544,8 @@ bool MP4StreamParser::ParseMoov(BoxReader* reader) {
}
video_config.Initialize(entry.video_codec, entry.video_codec_profile,
PIXEL_FORMAT_I420, COLOR_SPACE_HD_REC709,
- VIDEO_ROTATION_0, coded_size, visible_rect,
- natural_size,
+ CalculateRotation(track->header, moov_->header),
+ coded_size, visible_rect, natural_size,
// No decoder-specific buffer needed for AVC;
// SPS/PPS are embedded in the video stream
EmptyExtraData(), scheme);
@@ -753,15 +825,12 @@ ParseResult MP4StreamParser::EnqueueSample(BufferQueueMap* buffers) {
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));
+ decrypt_config.reset(
+ new DecryptConfig(decrypt_config->encryption_mode(),
+ decrypt_config->key_id(), decrypt_config->iv(),
+ subsamples, decrypt_config->encryption_pattern()));
}
// else, use the existing config.
- } else if (is_track_encrypted_[runs_->track_id()]) {
- // 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", "", std::vector<SubsampleEntry>()));
}
StreamParserBuffer::Type buffer_type = audio ? DemuxerStream::AUDIO :
diff --git a/chromium/media/formats/mp4/mp4_stream_parser.h b/chromium/media/formats/mp4/mp4_stream_parser.h
index 97bdfd66972..585a789e807 100644
--- a/chromium/media/formats/mp4/mp4_stream_parser.h
+++ b/chromium/media/formats/mp4/mp4_stream_parser.h
@@ -28,6 +28,8 @@ namespace media {
namespace mp4 {
struct Movie;
+struct MovieHeader;
+struct TrackHeader;
class BoxReader;
class MEDIA_EXPORT MP4StreamParser : public StreamParser {
@@ -48,6 +50,10 @@ class MEDIA_EXPORT MP4StreamParser : public StreamParser {
void Flush() override;
bool Parse(const uint8_t* buf, int size) override;
+ // Calculates the rotation value from the track header display matricies.
+ VideoRotation CalculateRotation(const TrackHeader& track,
+ const MovieHeader& movie);
+
private:
enum State {
kWaitingForInit,
@@ -134,7 +140,6 @@ class MEDIA_EXPORT MP4StreamParser : public StreamParser {
const std::set<int> audio_object_types_;
const bool has_sbr_;
const bool has_flac_;
- std::map<uint32_t, bool> is_track_encrypted_;
// Tracks the number of MEDIA_LOGS for skipping empty trun samples.
int num_empty_samples_skipped_;
diff --git a/chromium/media/formats/mp4/mp4_stream_parser_unittest.cc b/chromium/media/formats/mp4/mp4_stream_parser_unittest.cc
index 588ebafa7d3..dac384d7c87 100644
--- a/chromium/media/formats/mp4/mp4_stream_parser_unittest.cc
+++ b/chromium/media/formats/mp4/mp4_stream_parser_unittest.cc
@@ -10,6 +10,7 @@
#include <algorithm>
#include <memory>
#include <string>
+#include <tuple>
#include "base/bind.h"
#include "base/bind_helpers.h"
@@ -33,6 +34,7 @@
#include "media/formats/mp4/fourccs.h"
#include "media/media_buildflags.h"
#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest-param-test.h"
#include "testing/gtest/include/gtest/gtest.h"
using ::testing::InSequence;
@@ -470,10 +472,6 @@ TEST_F(MP4StreamParserTest, DemuxingEAC3) {
}
TEST_F(MP4StreamParserTest, Flac) {
- // The feature is disabled by default. Enable it.
- base::test::ScopedFeatureList features;
- features.InitAndEnableFeature(kMseFlacInIsobmff);
-
parser_.reset(new MP4StreamParser(std::set<int>(), false, true));
auto params = GetDefaultInitParametersExpectations();
@@ -485,10 +483,6 @@ TEST_F(MP4StreamParserTest, Flac) {
}
TEST_F(MP4StreamParserTest, Flac192kHz) {
- // The feature is disabled by default. Enable it.
- base::test::ScopedFeatureList features;
- features.InitAndEnableFeature(kMseFlacInIsobmff);
-
parser_.reset(new MP4StreamParser(std::set<int>(), false, true));
auto params = GetDefaultInitParametersExpectations();
@@ -586,5 +580,55 @@ TEST_F(MP4StreamParserTest, MultiTrackFile) {
EXPECT_EQ(audio_track2.language(), "und");
}
+// <cos(θ), sin(θ), θ expressed as a rotation Enum>
+using MatrixRotationTestCaseParam = std::tuple<double, double, VideoRotation>;
+
+class MP4StreamParserRotationMatrixEvaluatorTest
+ : public ::testing::TestWithParam<MatrixRotationTestCaseParam> {
+ public:
+ MP4StreamParserRotationMatrixEvaluatorTest() {
+ std::set<int> audio_object_types;
+ audio_object_types.insert(kISO_14496_3);
+ parser_.reset(new MP4StreamParser(audio_object_types, false, false));
+ }
+
+ protected:
+ std::unique_ptr<MP4StreamParser> parser_;
+};
+
+TEST_P(MP4StreamParserRotationMatrixEvaluatorTest, RotationCalculation) {
+ TrackHeader track_header;
+ MovieHeader movie_header;
+
+ // Identity matrix, with 16.16 and 2.30 fixed points.
+ uint32_t identity_matrix[9] = {1 << 16, 0, 0, 0, 1 << 16, 0, 0, 0, 1 << 30};
+
+ memcpy(movie_header.display_matrix, identity_matrix, sizeof(identity_matrix));
+ memcpy(track_header.display_matrix, identity_matrix, sizeof(identity_matrix));
+
+ MatrixRotationTestCaseParam data = GetParam();
+
+ // Insert fixed point decimal data into the rotation matrix.
+ track_header.display_matrix[0] = std::get<0>(data) * (1 << 16);
+ track_header.display_matrix[4] = std::get<0>(data) * (1 << 16);
+ track_header.display_matrix[1] = -(std::get<1>(data) * (1 << 16));
+ track_header.display_matrix[3] = std::get<1>(data) * (1 << 16);
+
+ EXPECT_EQ(parser_->CalculateRotation(track_header, movie_header),
+ std::get<2>(data));
+}
+
+MatrixRotationTestCaseParam rotation_test_cases[6] = {
+ {1, 0, VIDEO_ROTATION_0}, // cos(0) = 1, sin(0) = 0
+ {0, -1, VIDEO_ROTATION_90}, // cos(90) = 0, sin(90) =-1
+ {-1, 0, VIDEO_ROTATION_180}, // cos(180)=-1, sin(180)= 0
+ {0, 1, VIDEO_ROTATION_270}, // cos(270)= 0, sin(270)= 1
+ {1, 1, VIDEO_ROTATION_0}, // Error case
+ {5, 5, VIDEO_ROTATION_0}, // Error case
+};
+INSTANTIATE_TEST_CASE_P(CheckMath,
+ MP4StreamParserRotationMatrixEvaluatorTest,
+ testing::ValuesIn(rotation_test_cases));
+
} // namespace mp4
} // namespace media
diff --git a/chromium/media/formats/mp4/track_run_iterator.cc b/chromium/media/formats/mp4/track_run_iterator.cc
index 1e35058e6cd..cb797448675 100644
--- a/chromium/media/formats/mp4/track_run_iterator.cc
+++ b/chromium/media/formats/mp4/track_run_iterator.cc
@@ -13,6 +13,8 @@
#include "base/numerics/checked_math.h"
#include "base/numerics/safe_conversions.h"
#include "media/base/demuxer_memory_limit.h"
+#include "media/base/encryption_scheme.h"
+#include "media/base/media_util.h"
#include "media/base/timestamp_constants.h"
#include "media/formats/mp4/rcheck.h"
#include "media/formats/mp4/sample_to_group_iterator.h"
@@ -52,6 +54,8 @@ struct TrackRunInfo {
std::vector<uint8_t> aux_info_sizes; // Populated if default_size == 0.
int aux_info_total_size;
+ EncryptionScheme encryption_scheme;
+
std::vector<CencSampleEncryptionInfoEntry> fragment_sample_encryption_info;
TrackRunInfo();
@@ -342,20 +346,40 @@ bool TrackRunIterator::Init(const MovieFragment& moof) {
traf.sample_group_description.entries;
const TrackEncryption* track_encryption;
+ const ProtectionSchemeInfo* sinf;
tri.is_audio = (stsd.type == kAudio);
if (tri.is_audio) {
RCHECK(!stsd.audio_entries.empty());
if (desc_idx >= stsd.audio_entries.size())
desc_idx = 0;
tri.audio_description = &stsd.audio_entries[desc_idx];
+ sinf = &tri.audio_description->sinf;
track_encryption = &tri.audio_description->sinf.info.track_encryption;
} else {
RCHECK(!stsd.video_entries.empty());
if (desc_idx >= stsd.video_entries.size())
desc_idx = 0;
tri.video_description = &stsd.video_entries[desc_idx];
+ sinf = &tri.video_description->sinf;
track_encryption = &tri.video_description->sinf.info.track_encryption;
}
+
+ if (!sinf->HasSupportedScheme()) {
+ tri.encryption_scheme = Unencrypted();
+ } else {
+#if BUILDFLAG(ENABLE_CBCS_ENCRYPTION_SCHEME)
+ tri.encryption_scheme = EncryptionScheme(
+ sinf->IsCbcsEncryptionScheme()
+ ? EncryptionScheme::CIPHER_MODE_AES_CBC
+ : EncryptionScheme::CIPHER_MODE_AES_CTR,
+ EncryptionPattern(track_encryption->default_crypt_byte_block,
+ track_encryption->default_skip_byte_block));
+#else
+ DCHECK(!sinf->IsCbcsEncryptionScheme());
+ tri.encryption_scheme = AesCtrEncryptionScheme();
+#endif
+ }
+
// Initialize aux_info variables only if no sample encryption entries.
if (sample_encryption_entries_count == 0 &&
traf.auxiliary_offset.offsets.size() > j) {
@@ -670,16 +694,21 @@ bool TrackRunIterator::is_keyframe() const {
return sample_itr_->is_keyframe;
}
-const TrackEncryption& TrackRunIterator::track_encryption() const {
+const ProtectionSchemeInfo& TrackRunIterator::protection_scheme_info() const {
if (is_audio())
- return audio_description().sinf.info.track_encryption;
- return video_description().sinf.info.track_encryption;
+ return audio_description().sinf;
+ return video_description().sinf;
+}
+
+const TrackEncryption& TrackRunIterator::track_encryption() const {
+ return protection_scheme_info().info.track_encryption;
}
std::unique_ptr<DecryptConfig> TrackRunIterator::GetDecryptConfig() {
DCHECK(is_encrypted());
size_t sample_idx = sample_itr_ - run_itr_->samples.begin();
const std::vector<uint8_t>& kid = GetKeyId(sample_idx);
+ std::string key_id(kid.begin(), kid.end());
if (run_itr_->sample_encryption_entries.empty()) {
DCHECK_EQ(0, aux_info_size());
@@ -688,36 +717,60 @@ std::unique_ptr<DecryptConfig> TrackRunIterator::GetDecryptConfig() {
// with full sample encryption. That case will fall through to here.
SampleEncryptionEntry sample_encryption_entry;
if (ApplyConstantIv(sample_idx, &sample_encryption_entry)) {
- return std::unique_ptr<DecryptConfig>(new DecryptConfig(
- std::string(reinterpret_cast<const char*>(&kid[0]), kid.size()),
- std::string(reinterpret_cast<const char*>(
- sample_encryption_entry.initialization_vector),
- arraysize(sample_encryption_entry.initialization_vector)),
- sample_encryption_entry.subsamples));
+ std::string iv(reinterpret_cast<const char*>(
+ sample_encryption_entry.initialization_vector),
+ arraysize(sample_encryption_entry.initialization_vector));
+ switch (run_itr_->encryption_scheme.mode()) {
+ case EncryptionScheme::CIPHER_MODE_UNENCRYPTED:
+ return nullptr;
+ case EncryptionScheme::CIPHER_MODE_AES_CTR:
+ return DecryptConfig::CreateCencConfig(
+ key_id, iv, sample_encryption_entry.subsamples);
+ case EncryptionScheme::CIPHER_MODE_AES_CBC:
+ return DecryptConfig::CreateCbcsConfig(
+ key_id, iv, sample_encryption_entry.subsamples,
+ run_itr_->encryption_scheme.pattern());
+ }
}
#endif
MEDIA_LOG(ERROR, media_log_) << "Sample encryption info is not available.";
- return std::unique_ptr<DecryptConfig>();
+ return nullptr;
}
DCHECK_LT(sample_idx, run_itr_->sample_encryption_entries.size());
const SampleEncryptionEntry& sample_encryption_entry =
run_itr_->sample_encryption_entries[sample_idx];
+ std::string iv(reinterpret_cast<const char*>(
+ sample_encryption_entry.initialization_vector),
+ arraysize(sample_encryption_entry.initialization_vector));
size_t total_size = 0;
if (!sample_encryption_entry.subsamples.empty() &&
(!sample_encryption_entry.GetTotalSizeOfSubsamples(&total_size) ||
total_size != static_cast<size_t>(sample_size()))) {
MEDIA_LOG(ERROR, media_log_) << "Incorrect CENC subsample size.";
- return std::unique_ptr<DecryptConfig>();
+ return nullptr;
}
- return std::unique_ptr<DecryptConfig>(new DecryptConfig(
- std::string(reinterpret_cast<const char*>(&kid[0]), kid.size()),
- std::string(reinterpret_cast<const char*>(
- sample_encryption_entry.initialization_vector),
- arraysize(sample_encryption_entry.initialization_vector)),
- sample_encryption_entry.subsamples));
+#if BUILDFLAG(ENABLE_CBCS_ENCRYPTION_SCHEME)
+ if (protection_scheme_info().IsCbcsEncryptionScheme()) {
+ uint32_t index = GetGroupDescriptionIndex(sample_idx);
+ uint32_t encrypt_blocks =
+ (index == 0)
+ ? track_encryption().default_crypt_byte_block
+ : GetSampleEncryptionInfoEntry(*run_itr_, index)->crypt_byte_block;
+ uint32_t skip_blocks =
+ (index == 0)
+ ? track_encryption().default_skip_byte_block
+ : GetSampleEncryptionInfoEntry(*run_itr_, index)->skip_byte_block;
+ return DecryptConfig::CreateCbcsConfig(
+ key_id, iv, sample_encryption_entry.subsamples,
+ EncryptionPattern(encrypt_blocks, skip_blocks));
+ }
+#endif
+
+ return DecryptConfig::CreateCencConfig(key_id, iv,
+ sample_encryption_entry.subsamples);
}
uint32_t TrackRunIterator::GetGroupDescriptionIndex(
diff --git a/chromium/media/formats/mp4/track_run_iterator.h b/chromium/media/formats/mp4/track_run_iterator.h
index 59521c36c50..213acd1f0f4 100644
--- a/chromium/media/formats/mp4/track_run_iterator.h
+++ b/chromium/media/formats/mp4/track_run_iterator.h
@@ -95,6 +95,7 @@ class MEDIA_EXPORT TrackRunIterator {
private:
bool UpdateCts();
bool ResetRun();
+ const ProtectionSchemeInfo& protection_scheme_info() const;
const TrackEncryption& track_encryption() const;
uint32_t GetGroupDescriptionIndex(uint32_t sample_index) const;
diff --git a/chromium/media/formats/mpeg/mpeg_audio_stream_parser_base.cc b/chromium/media/formats/mpeg/mpeg_audio_stream_parser_base.cc
index 80be6da0546..8717ac299f6 100644
--- a/chromium/media/formats/mpeg/mpeg_audio_stream_parser_base.cc
+++ b/chromium/media/formats/mpeg/mpeg_audio_stream_parser_base.cc
@@ -8,7 +8,6 @@
#include "base/bind.h"
#include "base/callback_helpers.h"
-#include "base/message_loop/message_loop.h"
#include "media/base/media_log.h"
#include "media/base/media_tracks.h"
#include "media/base/media_util.h"
diff --git a/chromium/media/formats/webm/webm_crypto_helpers.cc b/chromium/media/formats/webm/webm_crypto_helpers.cc
index 1f8447ab8bd..846e6b7650a 100644
--- a/chromium/media/formats/webm/webm_crypto_helpers.cc
+++ b/chromium/media/formats/webm/webm_crypto_helpers.cc
@@ -106,10 +106,6 @@ bool WebMCreateDecryptConfig(const uint8_t* data,
const uint8_t signal_byte = data[0];
int frame_offset = sizeof(signal_byte);
-
- // Setting the DecryptConfig object of the buffer while leaving the
- // initialization vector empty will tell the decryptor that the frame is
- // unencrypted.
std::string counter_block;
std::vector<SubsampleEntry> subsample_entries;
@@ -145,9 +141,14 @@ bool WebMCreateDecryptConfig(const uint8_t* data,
}
}
- decrypt_config->reset(new DecryptConfig(
- std::string(reinterpret_cast<const char*>(key_id), key_id_size),
- counter_block, subsample_entries));
+ if (counter_block.empty()) {
+ // If the frame is unencrypted the DecryptConfig object should be NULL.
+ decrypt_config->reset();
+ } else {
+ *decrypt_config = DecryptConfig::CreateCencConfig(
+ std::string(reinterpret_cast<const char*>(key_id), key_id_size),
+ counter_block, subsample_entries);
+ }
*data_offset = frame_offset;
return true;
diff --git a/chromium/media/formats/webm/webm_crypto_helpers.h b/chromium/media/formats/webm/webm_crypto_helpers.h
index 21e53f7409d..e1bf6c48115 100644
--- a/chromium/media/formats/webm/webm_crypto_helpers.h
+++ b/chromium/media/formats/webm/webm_crypto_helpers.h
@@ -14,11 +14,11 @@
namespace media {
-// 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
+// Fills |decrypt_config|, 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. If the frame is unencrypted
+// |*decrypt_config| will be null. 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
bool MEDIA_EXPORT
diff --git a/chromium/media/formats/webm/webm_crypto_helpers_unittest.cc b/chromium/media/formats/webm/webm_crypto_helpers_unittest.cc
index e6e184fa184..842cc0d7289 100644
--- a/chromium/media/formats/webm/webm_crypto_helpers_unittest.cc
+++ b/chromium/media/formats/webm/webm_crypto_helpers_unittest.cc
@@ -37,7 +37,7 @@ TEST(WebMCryptoHelpersTest, ClearData) {
sizeof(kKeyId), &decrypt_config,
&data_offset));
EXPECT_EQ(1, data_offset);
- EXPECT_FALSE(decrypt_config->is_encrypted());
+ EXPECT_FALSE(decrypt_config);
}
TEST(WebMCryptoHelpersTest, EncryptedButNotEnoughBytes) {
@@ -68,7 +68,7 @@ TEST(WebMCryptoHelpersTest, EncryptedNotPartitioned) {
ASSERT_TRUE(WebMCreateDecryptConfig(kData, sizeof(kData), kKeyId,
sizeof(kKeyId), &decrypt_config,
&data_offset));
- EXPECT_TRUE(decrypt_config->is_encrypted());
+ EXPECT_TRUE(decrypt_config);
EXPECT_EQ(std::string(kKeyId, kKeyId + sizeof(kKeyId)),
decrypt_config->key_id());
EXPECT_EQ(std::string(kExpectedIv, kExpectedIv + sizeof(kExpectedIv)),
@@ -191,7 +191,7 @@ TEST(WebMCryptoHelpersTest, EncryptedPartitionedEvenNumberOfPartitions) {
ASSERT_TRUE(WebMCreateDecryptConfig(kData, sizeof(kData), kKeyId,
sizeof(kKeyId), &decrypt_config,
&data_offset));
- EXPECT_TRUE(decrypt_config->is_encrypted());
+ EXPECT_TRUE(decrypt_config);
EXPECT_EQ(std::string(kKeyId, kKeyId + sizeof(kKeyId)),
decrypt_config->key_id());
EXPECT_EQ(std::string(kExpectedIv, kExpectedIv + sizeof(kExpectedIv)),
@@ -224,7 +224,7 @@ TEST(WebMCryptoHelpersTest, EncryptedPartitionedOddNumberOfPartitions) {
ASSERT_TRUE(WebMCreateDecryptConfig(kData, sizeof(kData), kKeyId,
sizeof(kKeyId), &decrypt_config,
&data_offset));
- EXPECT_TRUE(decrypt_config->is_encrypted());
+ EXPECT_TRUE(decrypt_config);
EXPECT_EQ(std::string(kKeyId, kKeyId + sizeof(kKeyId)),
decrypt_config->key_id());
EXPECT_EQ(std::string(kExpectedIv, kExpectedIv + sizeof(kExpectedIv)),
@@ -254,7 +254,7 @@ TEST(WebMCryptoHelpersTest, EncryptedPartitionedZeroNumberOfPartitions) {
ASSERT_TRUE(WebMCreateDecryptConfig(kData, sizeof(kData), kKeyId,
sizeof(kKeyId), &decrypt_config,
&data_offset));
- EXPECT_TRUE(decrypt_config->is_encrypted());
+ EXPECT_TRUE(decrypt_config);
EXPECT_EQ(std::string(kKeyId, kKeyId + sizeof(kKeyId)),
decrypt_config->key_id());
EXPECT_EQ(std::string(kExpectedIv, kExpectedIv + sizeof(kExpectedIv)),
diff --git a/chromium/media/formats/webm/webm_parser_unittest.cc b/chromium/media/formats/webm/webm_parser_unittest.cc
index b24fb485046..11f3380417b 100644
--- a/chromium/media/formats/webm/webm_parser_unittest.cc
+++ b/chromium/media/formats/webm/webm_parser_unittest.cc
@@ -27,7 +27,7 @@ enum { kBlockCount = 5 };
class MockWebMParserClient : public WebMParserClient {
public:
- virtual ~MockWebMParserClient() = default;
+ ~MockWebMParserClient() override = default;
// WebMParserClient methods.
MOCK_METHOD1(OnListStart, WebMParserClient*(int));
diff --git a/chromium/media/formats/webm/webm_stream_parser_unittest.cc b/chromium/media/formats/webm/webm_stream_parser_unittest.cc
index c009bb08f9f..cfc3d6fc66c 100644
--- a/chromium/media/formats/webm/webm_stream_parser_unittest.cc
+++ b/chromium/media/formats/webm/webm_stream_parser_unittest.cc
@@ -13,6 +13,7 @@
#include "media/base/mock_media_log.h"
#include "media/base/stream_parser.h"
#include "media/base/test_data_util.h"
+#include "media/base/test_helpers.h"
#include "media/base/text_track_config.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -91,7 +92,7 @@ class WebMStreamParserTest : public testing::Test {
};
TEST_F(WebMStreamParserTest, VerifyMediaTrackMetadata) {
- EXPECT_MEDIA_LOG(testing::HasSubstr("Estimating WebM block duration"))
+ EXPECT_MEDIA_LOG(WebMSimpleBlockDurationEstimatedAny())
.Times(testing::AnyNumber());
StreamParser::InitParameters params(kInfiniteDuration);
params.detected_audio_track_count = 1;
@@ -118,7 +119,7 @@ TEST_F(WebMStreamParserTest, VerifyMediaTrackMetadata) {
}
TEST_F(WebMStreamParserTest, VerifyDetectedTrack_AudioOnly) {
- EXPECT_MEDIA_LOG(testing::HasSubstr("Estimating WebM block duration"))
+ EXPECT_MEDIA_LOG(WebMSimpleBlockDurationEstimatedAny())
.Times(testing::AnyNumber());
StreamParser::InitParameters params(kInfiniteDuration);
params.detected_audio_track_count = 1;
@@ -140,7 +141,7 @@ TEST_F(WebMStreamParserTest, VerifyDetectedTrack_VideoOnly) {
}
TEST_F(WebMStreamParserTest, VerifyDetectedTracks_AVText) {
- EXPECT_MEDIA_LOG(testing::HasSubstr("Estimating WebM block duration"))
+ EXPECT_MEDIA_LOG(WebMSimpleBlockDurationEstimatedAny())
.Times(testing::AnyNumber());
StreamParser::InitParameters params(kInfiniteDuration);
params.detected_audio_track_count = 1;
@@ -153,7 +154,7 @@ TEST_F(WebMStreamParserTest, VerifyDetectedTracks_AVText) {
}
TEST_F(WebMStreamParserTest, ColourElement) {
- EXPECT_MEDIA_LOG(testing::HasSubstr("Estimating WebM block duration"))
+ EXPECT_MEDIA_LOG(WebMSimpleBlockDurationEstimatedAny())
.Times(testing::AnyNumber());
StreamParser::InitParameters params(kInfiniteDuration);
params.detected_audio_track_count = 0;
@@ -192,4 +193,27 @@ TEST_F(WebMStreamParserTest, ColourElement) {
EXPECT_EQ(mmdata.luminance_min, 30);
}
+TEST_F(WebMStreamParserTest, ColourElementWithUnspecifiedRange) {
+ EXPECT_MEDIA_LOG(WebMSimpleBlockDurationEstimatedAny())
+ .Times(testing::AnyNumber());
+ StreamParser::InitParameters params(kInfiniteDuration);
+ params.detected_audio_track_count = 0;
+ params.detected_video_track_count = 1;
+ params.detected_text_track_count = 0;
+ ParseWebMFile("colour_unspecified_range.webm", params);
+ EXPECT_EQ(media_tracks_->tracks().size(), 1u);
+
+ const auto& video_track = media_tracks_->tracks()[0];
+ EXPECT_EQ(video_track->type(), MediaTrack::Video);
+
+ const VideoDecoderConfig& video_config =
+ media_tracks_->getVideoConfig(video_track->bytestream_track_id());
+
+ VideoColorSpace expected_color_space(VideoColorSpace::PrimaryID::SMPTEST428_1,
+ VideoColorSpace::TransferID::LOG,
+ VideoColorSpace::MatrixID::RGB,
+ gfx::ColorSpace::RangeID::INVALID);
+ EXPECT_EQ(video_config.color_space_info(), expected_color_space);
+}
+
} // namespace media
diff --git a/chromium/media/formats/webm/webm_video_client.cc b/chromium/media/formats/webm/webm_video_client.cc
index 651b88f9a3d..61bc28ed979 100644
--- a/chromium/media/formats/webm/webm_video_client.cc
+++ b/chromium/media/formats/webm/webm_video_client.cc
@@ -6,7 +6,7 @@
#include "media/base/video_decoder_config.h"
#include "media/formats/webm/webm_constants.h"
-#include "third_party/libaom/av1_features.h"
+#include "third_party/libaom/av1_buildflags.h"
namespace media {