Index: net/base/mime_util.cc |
diff --git a/net/base/mime_util.cc b/net/base/mime_util.cc |
index 2f02da13dc4ffabf81b4118d704b54007c406363..9d15256172ff9fc99f2a5c9e27021cfd785a6263 100644 |
--- a/net/base/mime_util.cc |
+++ b/net/base/mime_util.cc |
@@ -83,7 +83,7 @@ class MimeUtil : public PlatformMimeUtil { |
bool strip); |
bool IsStrictMediaMimeType(const std::string& mime_type) const; |
- bool IsSupportedStrictMediaMimeType( |
+ SupportsType IsSupportedStrictMediaMimeType( |
const std::string& mime_type, |
const std::vector<std::string>& codecs) const; |
@@ -95,12 +95,21 @@ class MimeUtil : public PlatformMimeUtil { |
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> |
+ StrictExpressionMappings; |
+ |
MimeUtil(); |
// 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( |
+ const MimeExpressionMappings& supported_codecs, |
+ const std::vector<std::string>& codecs); |
// For faster lookup, keep hash sets. |
void InitializeMimeTypeMaps(); |
@@ -116,7 +125,11 @@ class MimeUtil : public PlatformMimeUtil { |
MimeMappings javascript_map_; |
MimeMappings 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_; |
}; // class MimeUtil |
// This variable is Leaky because we need to access it from WorkerPool threads. |
@@ -465,6 +478,37 @@ static const MediaFormatStrict format_codec_mappings[] = { |
{ "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 |
+// |
+// avc1.42E0xx - H.264 Baseline |
+// avc1.4D40xx - H.264 Main |
+// avc1.6400xx - H.264 High |
+// |
+// 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 } |
+}; |
+ |
MimeUtil::MimeUtil() { |
InitializeMimeTypeMaps(); |
} |
@@ -482,6 +526,41 @@ bool MimeUtil::AreSupportedCodecs(const MimeMappings& supported_codecs, |
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( |
+ const MimeExpressionMappings& supported_codecs, |
+ const std::vector<std::string>& codecs) { |
+ DCHECK(!supported_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; |
+ } |
+ // If suffix exists, check whether it is hexadecimal. |
+ for (size_t wildcard_pos = supported_codecs[j].find('?'); |
+ wildcard_pos != std::string::npos && |
+ wildcard_pos < supported_codecs[j].length(); |
+ wildcard_pos = supported_codecs[j].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() || |
+ !IsHexDigit(codecs[i].at(wildcard_pos))) { |
+ return false; |
+ } |
+ } |
+ codec_matched = true; |
+ break; |
+ } |
+ if (!codec_matched) |
+ return false; |
+ } |
+ return !codecs.empty(); |
+} |
+ |
void MimeUtil::InitializeMimeTypeMaps() { |
for (size_t i = 0; i < arraysize(supported_image_types); ++i) |
image_map_.insert(supported_image_types[i]); |
@@ -552,6 +631,16 @@ void MimeUtil::InitializeMimeTypeMaps() { |
} |
strict_format_map_[format_codec_mappings[i].mime_type] = codecs; |
} |
+ for (size_t i = 0; i < arraysize(format_mp4_codec_mappings); ++i) { |
+ std::vector<std::string> mime_type_codecs; |
+ ParseCodecString( |
+ format_mp4_codec_mappings[i].codecs_list, &mime_type_codecs, false); |
+ |
+ MimeExpressionMappings codecs; |
+ for (size_t j = 0; j < mime_type_codecs.size(); ++j) |
+ codecs.push_back(mime_type_codecs[j]); |
+ strict_mp4_format_map_[format_mp4_codec_mappings[i].mime_type] = codecs; |
+ } |
} |
bool MimeUtil::IsSupportedImageMimeType(const std::string& mime_type) const { |
@@ -732,17 +821,33 @@ 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()) |
+ if (strict_format_map_.find(mime_type) == strict_format_map_.end() && |
+ strict_mp4_format_map_.find(mime_type) == strict_mp4_format_map_.end()) |
return false; |
return true; |
} |
-bool MimeUtil::IsSupportedStrictMediaMimeType( |
+SupportsType MimeUtil::IsSupportedStrictMediaMimeType( |
const std::string& mime_type, |
const std::vector<std::string>& codecs) const { |
- StrictMappings::const_iterator it = strict_format_map_.find(mime_type); |
- return (it != strict_format_map_.end()) && |
- AreSupportedCodecs(it->second, codecs); |
+ StrictMappings::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)) { |
+ 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; |
+ } |
+ |
+ if (codecs.empty()) |
+ return MayBeSupported; |
+ |
+ return IsNotSupported; |
} |
void MimeUtil::RemoveProprietaryMediaTypesAndCodecsForTests() { |
@@ -827,8 +932,9 @@ bool IsStrictMediaMimeType(const std::string& mime_type) { |
return g_mime_util.Get().IsStrictMediaMimeType(mime_type); |
} |
-bool IsSupportedStrictMediaMimeType(const std::string& mime_type, |
- const std::vector<std::string>& codecs) { |
+SupportsType IsSupportedStrictMediaMimeType( |
+ const std::string& mime_type, |
+ const std::vector<std::string>& codecs) { |
return g_mime_util.Get().IsSupportedStrictMediaMimeType(mime_type, codecs); |
} |