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()); |
+ } |
} |
//---------------------------------------------------------------------------- |