| Index: net/base/mime_util.cc
|
| diff --git a/net/base/mime_util.cc b/net/base/mime_util.cc
|
| index 9d15256172ff9fc99f2a5c9e27021cfd785a6263..893edd308ad582152c9694f2cb9f39bf4b5704e7 100644
|
| --- a/net/base/mime_util.cc
|
| +++ b/net/base/mime_util.cc
|
| @@ -93,7 +93,6 @@ class MimeUtil : public PlatformMimeUtil {
|
| friend struct base::DefaultLazyInstanceTraits<MimeUtil>;
|
|
|
| typedef base::hash_set<std::string> MimeMappings;
|
| - typedef std::map<std::string, MimeMappings> StrictMappings;
|
|
|
| typedef std::vector<std::string> MimeExpressionMappings;
|
| typedef std::map<std::string, MimeExpressionMappings>
|
| @@ -103,14 +102,17 @@ class MimeUtil : public PlatformMimeUtil {
|
|
|
| // Returns true if |codecs| is nonempty and all the items in it are present in
|
| // |supported_codecs|.
|
| - static bool AreSupportedCodecs(const MimeMappings& supported_codecs,
|
| - const std::vector<std::string>& codecs);
|
| - // Returns true is |codecs| is nonempty and all the items in it match with the
|
| - // codecs expression in |supported_codecs|.
|
| - static bool AreSupportedCodecsWithProfile(
|
| + static bool AreCodecsListedInSingleLookupTable(
|
| const MimeExpressionMappings& supported_codecs,
|
| const std::vector<std::string>& codecs);
|
|
|
| + // Returns true if |codecs| is nonempty and all the items in it are present in
|
| + // either |confirmed_supported_codecs| or |mightbe_supported_codecs|.
|
| + static bool AreCodecsListedInMultipleLookupTables(
|
| + const MimeExpressionMappings& confirmed_supported_codecs,
|
| + const MimeExpressionMappings& mightbe_supported_codecs,
|
| + const std::vector<std::string>& codecs);
|
| +
|
| // For faster lookup, keep hash sets.
|
| void InitializeMimeTypeMaps();
|
|
|
| @@ -123,13 +125,14 @@ class MimeUtil : public PlatformMimeUtil {
|
| MimeMappings non_image_map_;
|
| MimeMappings unsupported_text_map_;
|
| MimeMappings javascript_map_;
|
| - MimeMappings codecs_map_;
|
| + MimeExpressionMappings codecs_map_;
|
|
|
| // A map of mime_types and hash map of the supported codecs for the mime_type.
|
| - StrictMappings strict_format_map_;
|
| - // A map of MP4 mime_types which expect codecs with profile parameter and
|
| - // vector of supported codecs expressions for the mime_type.
|
| - StrictExpressionMappings strict_mp4_format_map_;
|
| + StrictExpressionMappings strict_format_map_;
|
| + // A map of mime_types, which expect codecs which are RFC compliant but do not
|
| + // have sufficient informatation whether they are supported or not, and vector
|
| + // of supported codecs expressions for the mime_type.
|
| + StrictExpressionMappings inconclusive_format_map_;
|
| }; // class MimeUtil
|
|
|
| // This variable is Leaky because we need to access it from WorkerPool threads.
|
| @@ -286,13 +289,12 @@ static const char* const supported_image_types[] = {
|
| // A list of media types: http://en.wikipedia.org/wiki/Internet_media_type
|
| // A comprehensive mime type list: http://plugindoc.mozdev.org/winmime.php
|
| // This set of codecs is supported by all variations of Chromium.
|
| +// (Except for 'video/ogg', which is not supported by Android.)
|
| static const char* const common_media_types[] = {
|
| // Ogg.
|
| "audio/ogg",
|
| "application/ogg",
|
| -#if !defined(OS_ANDROID) // Android doesn't support Ogg Theora.
|
| "video/ogg",
|
| -#endif
|
|
|
| // WebM.
|
| "video/webm",
|
| @@ -325,6 +327,8 @@ static const char* const proprietary_media_types[] = {
|
|
|
| // List of supported codecs when passed in with <source type="...">.
|
| // This set of codecs is supported by all variations of Chromium.
|
| +// (Except for 'theora' and 'opus' (http://crbug.com/318436), which are not
|
| +// supported by Android.)
|
| //
|
| // Refer to http://wiki.whatwg.org/wiki/Video_type_parameters#Browser_Support
|
| // for more information.
|
| @@ -332,9 +336,7 @@ static const char* const proprietary_media_types[] = {
|
| // The codecs for WAV are integers as defined in Appendix A of RFC2361:
|
| // http://tools.ietf.org/html/rfc2361
|
| static const char* const common_media_codecs[] = {
|
| -#if !defined(OS_ANDROID) // Android doesn't support Ogg Theora.
|
| "theora",
|
| -#endif
|
| "opus",
|
| "vorbis",
|
| "vp8",
|
| @@ -443,19 +445,35 @@ static bool IsCodecSupportedOnAndroid(const std::string& codec) {
|
|
|
| // TODO(vigneshv): Change this similar to the VP9 check once Opus is
|
| // supported on Android (http://crbug.com/318436).
|
| - if (!codec.compare("opus")) {
|
| + if (!codec.compare("opus"))
|
| + return false;
|
| +
|
| + // MPEG-2 AAC is not supported on Android
|
| + if (!codec.compare("mp4a.67"))
|
| + return false;
|
| +
|
| + // H.264 Main and High profiles are not supported on Android
|
| + if (!codec.compare("avc1.4d40??") || !codec.compare("avc3.4d40??") ||
|
| + !codec.compare("avc1.4D40??") || !codec.compare("avc3.4D40??") ||
|
| + !codec.compare("avc1.6400??") || !codec.compare("avc3.6400??")) {
|
| return false;
|
| }
|
| +
|
| return true;
|
| }
|
|
|
| static bool IsMimeTypeSupportedOnAndroid(const std::string& mimeType) {
|
| + // Ogg Theora is not supported on Android
|
| + if (!mimeType.compare("video/ogg"))
|
| + return false;
|
| +
|
| // HLS codecs are supported in ICS and above (API level 14)
|
| if ((!mimeType.compare("application/vnd.apple.mpegurl") ||
|
| !mimeType.compare("application/x-mpegurl")) &&
|
| base::android::BuildInfo::GetInstance()->sdk_int() < 14) {
|
| return false;
|
| }
|
| +
|
| return true;
|
| }
|
| #endif
|
| @@ -465,48 +483,64 @@ struct MediaFormatStrict {
|
| const char* codecs_list;
|
| };
|
|
|
| -static const MediaFormatStrict format_codec_mappings[] = {
|
| - { "video/webm", "opus,vorbis,vp8,vp8.0,vp9,vp9.0" },
|
| - { "audio/webm", "opus,vorbis" },
|
| - { "audio/wav", "1" },
|
| - { "audio/x-wav", "1" },
|
| - { "video/ogg", "opus,theora,vorbis" },
|
| - { "audio/ogg", "opus,vorbis" },
|
| - { "application/ogg", "opus,theora,vorbis" },
|
| - { "audio/mpeg", "" },
|
| - { "audio/mp3", "" },
|
| - { "audio/x-mp3", "" }
|
| -};
|
| -
|
| // Following is the list of RFC 6381 compliant codecs:
|
| // mp4a.6B - MPEG-1 audio
|
| // mp4a.69 - MPEG-2 extension to MPEG-1
|
| // mp4a.67 - MPEG-2 AAC
|
| // mp4a.40.2 - MPEG-4 AAC
|
| -// mp4a.40.5 - MPEG-4 HE-AAC
|
| +// mp4a.40.5 - MPEG-4 HE-AACv1
|
| //
|
| // avc1.42E0xx - H.264 Baseline
|
| // avc1.4D40xx - H.264 Main
|
| // avc1.6400xx - H.264 High
|
| +static const char kProprietaryAudioCodecsExpression[] =
|
| + "mp4a.6B,mp4a.69,mp4a.67,mp4a.40.2,mp4a.40.5";
|
| +static const char kProprietaryCodecsExpression[] =
|
| + "avc1.42E0??,avc1.42e0??,avc1.4D40??,avc1.4d40??,avc1.6400??,"
|
| + "avc3.42E0??,avc3.42e0??,avc3.4D40??,avc3.4d40??,avc3.6400??,"
|
| + "mp4a.6B,mp4a.69,mp4a.67,mp4a.40.2,mp4a.40.5";
|
| +
|
| +static const MediaFormatStrict format_codec_mappings[] = {
|
| + {"video/webm", "opus,vorbis,vp8,vp8.0,vp9,vp9.0"},
|
| + {"audio/webm", "opus,vorbis"},
|
| + {"audio/wav", "1"},
|
| + {"audio/x-wav", "1"},
|
| + {"video/ogg", "opus,theora,vorbis"},
|
| + {"audio/ogg", "opus,vorbis"},
|
| + {"application/ogg", "opus,theora,vorbis"},
|
| + {"audio/mpeg", ""},
|
| + {"audio/mp3", ""},
|
| + {"audio/x-mp3", ""},
|
| + {"audio/mp4", kProprietaryAudioCodecsExpression},
|
| + {"audio/x-m4a", kProprietaryAudioCodecsExpression},
|
| + {"video/mp4", kProprietaryCodecsExpression},
|
| + {"video/x-m4v", kProprietaryCodecsExpression},
|
| + {"application/x-mpegurl", kProprietaryCodecsExpression},
|
| + {"application/vnd.apple.mpegurl", kProprietaryCodecsExpression}
|
| +};
|
| +
|
| +// Following is the list of codecs that are RFC 6381 compliant, but support for
|
| +// which varies with platform and cannot be determined beforehand.
|
| +// mp4a.40
|
| +// avc1
|
| +// avc3
|
| //
|
| // Additionally, several non-RFC compliant codecs are allowed, due to their
|
| // existing use on web.
|
| -// mp4a.40
|
| // avc1.xxxxxx
|
| // avc3.xxxxxx
|
| -// mp4a.6x
|
| -static const char kProprietaryAudioCodecsExpression[] =
|
| - "mp4a.6?,mp4a.40,mp4a.40.?";
|
| -static const char kProprietaryCodecsExpression[] =
|
| - "avc1,avc3,avc1.??????,avc3.??????,mp4a.6?,mp4a.40,mp4a.40.?";
|
| -
|
| -static const MediaFormatStrict format_mp4_codec_mappings[] = {
|
| - { "audio/mp4", kProprietaryAudioCodecsExpression },
|
| - { "audio/x-m4a", kProprietaryAudioCodecsExpression },
|
| - { "video/mp4", kProprietaryCodecsExpression },
|
| - { "video/x-m4v", kProprietaryCodecsExpression },
|
| - { "application/x-mpegurl", kProprietaryCodecsExpression },
|
| - { "application/vnd.apple.mpegurl", kProprietaryCodecsExpression }
|
| +static const char kInconclusiveProprietaryAudioCodecsExpression[] =
|
| + "mp4a.40,mp4a.66,mp4a.68";
|
| +static const char kInconclusiveProprietaryCodecsExpression[] =
|
| + "avc1,avc1.??????,avc3,avc3.??????,mp4a.40,mp4a.66,mp4a.68";
|
| +
|
| +static const MediaFormatStrict format_inconclusive_codec_mappings[] = {
|
| + {"audio/mp4", kInconclusiveProprietaryAudioCodecsExpression},
|
| + {"audio/x-m4a", kInconclusiveProprietaryAudioCodecsExpression},
|
| + {"video/mp4", kInconclusiveProprietaryCodecsExpression},
|
| + {"video/x-m4v", kInconclusiveProprietaryCodecsExpression},
|
| + {"application/x-mpegurl", kInconclusiveProprietaryCodecsExpression},
|
| + {"application/vnd.apple.mpegurl", kInconclusiveProprietaryCodecsExpression},
|
| };
|
|
|
| MimeUtil::MimeUtil() {
|
| @@ -514,37 +548,53 @@ MimeUtil::MimeUtil() {
|
| }
|
|
|
| // static
|
| -bool MimeUtil::AreSupportedCodecs(const MimeMappings& supported_codecs,
|
| - const std::vector<std::string>& codecs) {
|
| - if (supported_codecs.empty())
|
| - return codecs.empty();
|
| -
|
| - for (size_t i = 0; i < codecs.size(); ++i) {
|
| - if (supported_codecs.find(codecs[i]) == supported_codecs.end())
|
| - return false;
|
| - }
|
| - return !codecs.empty();
|
| -}
|
| -
|
| // Checks all the codecs present in the |codecs| against the entries in
|
| // |supported_codecs|. Returns true only if |codecs| is non-empty and all the
|
| // codecs match |supported_codecs| expressions.
|
| -bool MimeUtil::AreSupportedCodecsWithProfile(
|
| +bool MimeUtil::AreCodecsListedInSingleLookupTable(
|
| const MimeExpressionMappings& supported_codecs,
|
| const std::vector<std::string>& codecs) {
|
| - DCHECK(!supported_codecs.empty());
|
| + MimeExpressionMappings empty_vector;
|
| + return AreCodecsListedInMultipleLookupTables(
|
| + supported_codecs, empty_vector, codecs);
|
| +}
|
| +
|
| +// static
|
| +// Checks all the codecs present in the |codecs| against the entries in
|
| +// |supported_codecs|. Returns true only if |codecs| is non-empty and all the
|
| +// codecs match expression in either |confirmed_supported_codecs| or
|
| +// |mightbe_supported_codecs|.
|
| +bool MimeUtil::AreCodecsListedInMultipleLookupTables(
|
| + const MimeExpressionMappings& confirmed_supported_codecs,
|
| + const MimeExpressionMappings& mightbe_supported_codecs,
|
| + const std::vector<std::string>& codecs) {
|
| + if (confirmed_supported_codecs.empty() && mightbe_supported_codecs.empty())
|
| + return codecs.empty();
|
| +
|
| for (size_t i = 0; i < codecs.size(); ++i) {
|
| - bool codec_matched = false;
|
| - for (size_t j = 0; j < supported_codecs.size(); ++j) {
|
| - if (!MatchPattern(base::StringPiece(codecs[i]),
|
| - base::StringPiece(supported_codecs[j]))) {
|
| - continue;
|
| + std::string matched_codec;
|
| + for (size_t j = 0; j < confirmed_supported_codecs.size(); ++j) {
|
| + if (MatchPattern(base::StringPiece(codecs[i]),
|
| + base::StringPiece(confirmed_supported_codecs[j]))) {
|
| + matched_codec = confirmed_supported_codecs[j];
|
| + break;
|
| + }
|
| + }
|
| + for (size_t j = 0;
|
| + j < mightbe_supported_codecs.size() && matched_codec.empty();
|
| + ++j) {
|
| + if (MatchPattern(base::StringPiece(codecs[i]),
|
| + base::StringPiece(mightbe_supported_codecs[j]))) {
|
| + matched_codec = mightbe_supported_codecs[j];
|
| + break;
|
| }
|
| + }
|
| + if (!matched_codec.empty()) {
|
| // If suffix exists, check whether it is hexadecimal.
|
| - for (size_t wildcard_pos = supported_codecs[j].find('?');
|
| + for (size_t wildcard_pos = matched_codec.find('?');
|
| wildcard_pos != std::string::npos &&
|
| - wildcard_pos < supported_codecs[j].length();
|
| - wildcard_pos = supported_codecs[j].find('?', wildcard_pos + 1)) {
|
| + wildcard_pos < matched_codec.length();
|
| + wildcard_pos = matched_codec.find('?', wildcard_pos + 1)) {
|
| // Don't enforce case sensitivity, even though it's called for, as it
|
| // would break some websites.
|
| if (wildcard_pos >= codecs[i].length() ||
|
| @@ -552,12 +602,11 @@ bool MimeUtil::AreSupportedCodecsWithProfile(
|
| return false;
|
| }
|
| }
|
| - codec_matched = true;
|
| - break;
|
| - }
|
| - if (!codec_matched)
|
| + } else {
|
| return false;
|
| + }
|
| }
|
| +
|
| return !codecs.empty();
|
| }
|
|
|
| @@ -607,11 +656,11 @@ void MimeUtil::InitializeMimeTypeMaps() {
|
| if (!IsCodecSupportedOnAndroid(common_media_codecs[i]))
|
| continue;
|
| #endif
|
| - codecs_map_.insert(common_media_codecs[i]);
|
| + codecs_map_.push_back(common_media_codecs[i]);
|
| }
|
| #if defined(USE_PROPRIETARY_CODECS)
|
| for (size_t i = 0; i < arraysize(proprietary_media_codecs); ++i)
|
| - codecs_map_.insert(proprietary_media_codecs[i]);
|
| + codecs_map_.push_back(proprietary_media_codecs[i]);
|
| #endif
|
|
|
| // Initialize the strict supported media types.
|
| @@ -621,25 +670,32 @@ void MimeUtil::InitializeMimeTypeMaps() {
|
| &mime_type_codecs,
|
| false);
|
|
|
| - MimeMappings codecs;
|
| + MimeExpressionMappings codecs;
|
| for (size_t j = 0; j < mime_type_codecs.size(); ++j) {
|
| #if defined(OS_ANDROID)
|
| if (!IsCodecSupportedOnAndroid(mime_type_codecs[j]))
|
| continue;
|
| #endif
|
| - codecs.insert(mime_type_codecs[j]);
|
| + codecs.push_back(mime_type_codecs[j]);
|
| }
|
| strict_format_map_[format_codec_mappings[i].mime_type] = codecs;
|
| }
|
| - for (size_t i = 0; i < arraysize(format_mp4_codec_mappings); ++i) {
|
| + for (size_t i = 0; i < arraysize(format_inconclusive_codec_mappings); ++i) {
|
| std::vector<std::string> mime_type_codecs;
|
| - ParseCodecString(
|
| - format_mp4_codec_mappings[i].codecs_list, &mime_type_codecs, false);
|
| + ParseCodecString(format_inconclusive_codec_mappings[i].codecs_list,
|
| + &mime_type_codecs,
|
| + false);
|
|
|
| MimeExpressionMappings codecs;
|
| - for (size_t j = 0; j < mime_type_codecs.size(); ++j)
|
| + for (size_t j = 0; j < mime_type_codecs.size(); ++j) {
|
| +#if defined(OS_ANDROID)
|
| + if (!IsCodecSupportedOnAndroid(mime_type_codecs[j]))
|
| + continue;
|
| +#endif
|
| codecs.push_back(mime_type_codecs[j]);
|
| - strict_mp4_format_map_[format_mp4_codec_mappings[i].mime_type] = codecs;
|
| + }
|
| + inconclusive_format_map_[format_inconclusive_codec_mappings[i].mime_type] =
|
| + codecs;
|
| }
|
| }
|
|
|
| @@ -797,7 +853,7 @@ bool MimeUtil::IsValidTopLevelMimeType(const std::string& type_string) const {
|
|
|
| bool MimeUtil::AreSupportedMediaCodecs(
|
| const std::vector<std::string>& codecs) const {
|
| - return AreSupportedCodecs(codecs_map_, codecs);
|
| + return AreCodecsListedInSingleLookupTable(codecs_map_, codecs);
|
| }
|
|
|
| void MimeUtil::ParseCodecString(const std::string& codecs,
|
| @@ -821,8 +877,7 @@ void MimeUtil::ParseCodecString(const std::string& codecs,
|
| }
|
|
|
| bool MimeUtil::IsStrictMediaMimeType(const std::string& mime_type) const {
|
| - if (strict_format_map_.find(mime_type) == strict_format_map_.end() &&
|
| - strict_mp4_format_map_.find(mime_type) == strict_mp4_format_map_.end())
|
| + if (strict_format_map_.find(mime_type) == strict_format_map_.end())
|
| return false;
|
| return true;
|
| }
|
| @@ -830,18 +885,28 @@ bool MimeUtil::IsStrictMediaMimeType(const std::string& mime_type) const {
|
| SupportsType MimeUtil::IsSupportedStrictMediaMimeType(
|
| const std::string& mime_type,
|
| const std::vector<std::string>& codecs) const {
|
| - StrictMappings::const_iterator it_strict_map =
|
| + StrictExpressionMappings::const_iterator it_strict_map =
|
| strict_format_map_.find(mime_type);
|
| if ((it_strict_map != strict_format_map_.end()) &&
|
| - AreSupportedCodecs(it_strict_map->second, codecs)) {
|
| + AreCodecsListedInSingleLookupTable(it_strict_map->second, codecs)) {
|
| return IsSupported;
|
| }
|
|
|
| StrictExpressionMappings::const_iterator it_expression_map =
|
| - strict_mp4_format_map_.find(mime_type);
|
| - if ((it_expression_map != strict_mp4_format_map_.end()) &&
|
| - AreSupportedCodecsWithProfile(it_expression_map->second, codecs)) {
|
| - return MayBeSupported;
|
| + inconclusive_format_map_.find(mime_type);
|
| + if (it_expression_map != inconclusive_format_map_.end()) {
|
| + bool maybe = false;
|
| + if (it_strict_map != strict_format_map_.end()) {
|
| + maybe = AreCodecsListedInMultipleLookupTables(it_strict_map->second,
|
| + it_expression_map->second,
|
| + codecs);
|
| + } else {
|
| + maybe = AreCodecsListedInSingleLookupTable(it_expression_map->second,
|
| + codecs);
|
| + }
|
| +
|
| + if (maybe)
|
| + return MayBeSupported;
|
| }
|
|
|
| if (codecs.empty())
|
| @@ -855,8 +920,12 @@ void MimeUtil::RemoveProprietaryMediaTypesAndCodecsForTests() {
|
| non_image_map_.erase(proprietary_media_types[i]);
|
| media_map_.erase(proprietary_media_types[i]);
|
| }
|
| - for (size_t i = 0; i < arraysize(proprietary_media_codecs); ++i)
|
| - codecs_map_.erase(proprietary_media_codecs[i]);
|
| + for (size_t i = 0; i < arraysize(proprietary_media_codecs); ++i) {
|
| + codecs_map_.erase(std::remove(codecs_map_.begin(),
|
| + codecs_map_.end(),
|
| + proprietary_media_codecs[i]),
|
| + codecs_map_.end());
|
| + }
|
| }
|
|
|
| //----------------------------------------------------------------------------
|
|
|