Index: media/base/mime_util.cc |
diff --git a/media/base/mime_util.cc b/media/base/mime_util.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..338aa31ee2413d1617081499fb0ad7f6262a0d10 |
--- /dev/null |
+++ b/media/base/mime_util.cc |
@@ -0,0 +1,683 @@ |
+// Copyright 2015 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#include <algorithm> |
+#include <iterator> |
+#include <map> |
+#include <string> |
+ |
+#include "base/containers/hash_tables.h" |
+#include "base/lazy_instance.h" |
+#include "base/logging.h" |
+#include "base/stl_util.h" |
+#include "base/strings/string_number_conversions.h" |
+#include "base/strings/string_split.h" |
+#include "base/strings/string_util.h" |
+#include "media/base/mime_util.h" |
+ |
+#if defined(OS_ANDROID) |
+#include "base/android/build_info.h" |
+#endif |
+ |
+namespace media { |
+ |
+// Singleton utility class for mime types. |
+class MimeUtil { |
+ public: |
+ enum Codec { |
+ INVALID_CODEC, |
+ PCM, |
+ MP3, |
+ MPEG2_AAC_LC, |
+ MPEG2_AAC_MAIN, |
+ MPEG2_AAC_SSR, |
+ MPEG4_AAC_LC, |
+ MPEG4_AAC_SBR_v1, |
+ MPEG4_AAC_SBR_PS_v2, |
+ VORBIS, |
+ OPUS, |
+ H264_BASELINE, |
+ H264_MAIN, |
+ H264_HIGH, |
+ VP8, |
+ VP9, |
+ THEORA |
+ }; |
+ |
+ bool IsSupportedMediaMimeType(const std::string& mime_type) const; |
+ |
+ bool AreSupportedMediaCodecs(const std::vector<std::string>& codecs) const; |
+ |
+ void ParseCodecString(const std::string& codecs, |
+ std::vector<std::string>* codecs_out, |
+ bool strip); |
+ |
+ bool IsStrictMediaMimeType(const std::string& mime_type) const; |
+ SupportsType IsSupportedStrictMediaMimeType( |
+ const std::string& mime_type, |
+ const std::vector<std::string>& codecs) const; |
+ |
+ void RemoveProprietaryMediaTypesAndCodecsForTests(); |
+ |
+ private: |
+ friend struct base::DefaultLazyInstanceTraits<MimeUtil>; |
+ |
+ typedef base::hash_set<std::string> MimeMappings; |
+ |
+ typedef base::hash_set<int> CodecSet; |
+ typedef std::map<std::string, CodecSet> StrictMappings; |
+ struct CodecEntry { |
+ CodecEntry() : codec(INVALID_CODEC), is_ambiguous(true) {} |
+ CodecEntry(Codec c, bool ambiguous) : codec(c), is_ambiguous(ambiguous) {} |
+ Codec codec; |
+ bool is_ambiguous; |
+ }; |
+ typedef std::map<std::string, CodecEntry> StringToCodecMappings; |
+ |
+ MimeUtil(); |
+ |
+ // Returns IsSupported if all codec IDs in |codecs| are unambiguous |
+ // and are supported by the platform. MayBeSupported is returned if |
+ // at least one codec ID in |codecs| is ambiguous but all the codecs |
+ // are supported by the platform. IsNotSupported is returned if at |
+ // least one codec ID is not supported by the platform. |
+ SupportsType AreSupportedCodecs( |
+ const CodecSet& supported_codecs, |
+ const std::vector<std::string>& codecs) const; |
+ |
+ // For faster lookup, keep hash sets. |
+ void InitializeMimeTypeMaps(); |
+ |
+ // Converts a codec ID into an Codec enum value and indicates |
+ // whether the conversion was ambiguous. |
+ // Returns true if this method was able to map |codec_id| to a specific |
+ // Codec enum value. |codec| and |is_ambiguous| are only valid if true |
+ // is returned. Otherwise their value is undefined after the call. |
+ // |is_ambiguous| is true if |codec_id| did not have enough information to |
+ // unambiguously determine the proper Codec enum value. If |is_ambiguous| |
+ // is true |codec| contains the best guess for the intended Codec enum value. |
+ bool StringToCodec(const std::string& codec_id, |
+ Codec* codec, |
+ bool* is_ambiguous) const; |
+ |
+ // Returns true if |codec| is supported by the platform. |
+ // Note: This method will return false if the platform supports proprietary |
+ // codecs but |allow_proprietary_codecs_| is set to false. |
+ bool IsCodecSupported(Codec codec) const; |
+ |
+ // Returns true if |codec| refers to a proprietary codec. |
+ bool IsCodecProprietary(Codec codec) const; |
+ |
+ // Returns true and sets |*default_codec| if |mime_type| has a default codec |
+ // associated with it. Returns false otherwise and the value of |
+ // |*default_codec| is undefined. |
+ bool GetDefaultCodecLowerCase(const std::string& mime_type_lower_case, |
+ Codec* default_codec) const; |
+ |
+ // Returns true if |mime_type_lower_case| has a default codec associated with |
+ // it and IsCodecSupported() returns true for that particular codec. |
+ bool IsDefaultCodecSupportedLowerCase( |
+ const std::string& mime_type_lower_case) const; |
+ |
+ MimeMappings media_map_; |
+ |
+ // A map of mime_types and hash map of the supported codecs for the mime_type. |
+ StrictMappings strict_format_map_; |
+ |
+ // Keeps track of whether proprietary codec support should be |
+ // advertised to callers. |
+ bool allow_proprietary_codecs_; |
+ |
+ // Lookup table for string compare based string -> Codec mappings. |
+ StringToCodecMappings string_to_codec_map_; |
+}; // class MimeUtil |
+ |
+// This variable is Leaky because we need to access it from WorkerPool threads. |
+static base::LazyInstance<MimeUtil>::Leaky g_mime_util = |
+ LAZY_INSTANCE_INITIALIZER; |
+ |
+// 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. |
+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", |
+ "audio/webm", |
+ |
+ // Wav. |
+ "audio/wav", |
+ "audio/x-wav", |
+ |
+#if defined(OS_ANDROID) |
+ // HLS. Supported by Android ICS and above. |
+ "application/vnd.apple.mpegurl", |
+ "application/x-mpegurl", |
+#endif |
+}; |
+ |
+// List of proprietary types only supported by Google Chrome. |
+static const char* const proprietary_media_types[] = { |
+ // MPEG-4. |
+ "video/mp4", |
+ "video/x-m4v", |
+ "audio/mp4", |
+ "audio/x-m4a", |
+ |
+ // MP3. |
+ "audio/mp3", |
+ "audio/x-mp3", |
+ "audio/mpeg", |
+ "audio/aac", |
+ |
+#if defined(ENABLE_MPEG2TS_STREAM_PARSER) |
+ // MPEG-2 TS. |
+ "video/mp2t", |
+#endif |
+}; |
+ |
+#if defined(OS_ANDROID) |
+static bool IsCodecSupportedOnAndroid(MimeUtil::Codec codec) { |
+ switch (codec) { |
+ case MimeUtil::INVALID_CODEC: |
+ return false; |
+ |
+ case MimeUtil::PCM: |
+ case MimeUtil::MP3: |
+ case MimeUtil::MPEG4_AAC_LC: |
+ case MimeUtil::MPEG4_AAC_SBR_v1: |
+ case MimeUtil::MPEG4_AAC_SBR_PS_v2: |
+ case MimeUtil::H264_BASELINE: |
+ case MimeUtil::H264_MAIN: |
+ case MimeUtil::H264_HIGH: |
+ case MimeUtil::VP8: |
+ case MimeUtil::VORBIS: |
+ return true; |
+ |
+ case MimeUtil::MPEG2_AAC_LC: |
+ case MimeUtil::MPEG2_AAC_MAIN: |
+ case MimeUtil::MPEG2_AAC_SSR: |
+ // MPEG-2 variants of AAC are not supported on Android. |
+ return false; |
+ |
+ case MimeUtil::VP9: |
+ // VP9 is supported only in KitKat+ (API Level 19). |
+ return base::android::BuildInfo::GetInstance()->sdk_int() >= 19; |
+ |
+ case MimeUtil::OPUS: |
+ // Opus is supported only in Lollipop+ (API Level 21). |
+ return base::android::BuildInfo::GetInstance()->sdk_int() >= 21; |
+ |
+ case MimeUtil::THEORA: |
+ return false; |
+ } |
+ |
+ return false; |
+} |
+ |
+static bool IsMimeTypeSupportedOnAndroid(const std::string& mimeType) { |
+ // 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 |
+ |
+struct MediaFormatStrict { |
+ const char* const mime_type; |
+ const char* const codecs_list; |
+}; |
+ |
+// Following is the list of RFC 6381 compliant codecs: |
+// mp4a.66 - MPEG-2 AAC MAIN |
+// mp4a.67 - MPEG-2 AAC LC |
+// mp4a.68 - MPEG-2 AAC SSR |
+// mp4a.69 - MPEG-2 extension to MPEG-1 |
+// mp4a.6B - MPEG-1 audio |
+// mp4a.40.2 - MPEG-4 AAC LC |
+// mp4a.40.02 - MPEG-4 AAC LC (leading 0 in aud-oti for compatibility) |
+// mp4a.40.5 - MPEG-4 HE-AAC v1 (AAC LC + SBR) |
+// mp4a.40.05 - MPEG-4 HE-AAC v1 (AAC LC + SBR) (leading 0 in aud-oti for |
+// compatibility) |
+// mp4a.40.29 - MPEG-4 HE-AAC v2 (AAC LC + SBR + PS) |
+// |
+// avc1.42E0xx - H.264 Baseline |
+// avc1.4D40xx - H.264 Main |
+// avc1.6400xx - H.264 High |
+static const char kMP4AudioCodecsExpression[] = |
+ "mp4a.66,mp4a.67,mp4a.68,mp4a.69,mp4a.6B,mp4a.40.2,mp4a.40.02,mp4a.40.5," |
+ "mp4a.40.05,mp4a.40.29"; |
+static const char kMP4VideoCodecsExpression[] = |
+ // This is not a complete list of supported avc1 codecs. It is simply used |
+ // to register support for the corresponding Codec enum. Instead of using |
+ // strings in these three arrays, we should use the Codec enum values. |
+ // This will avoid confusion and unnecessary parsing at runtime. |
+ // kUnambiguousCodecStringMap/kAmbiguousCodecStringMap should be the only |
+ // mapping from strings to codecs. See crbug.com/461009. |
+ "avc1.42E00A,avc1.4D400A,avc1.64000A," |
+ "mp4a.66,mp4a.67,mp4a.68,mp4a.69,mp4a.6B,mp4a.40.2,mp4a.40.02,mp4a.40.5," |
+ "mp4a.40.05,mp4a.40.29"; |
+ |
+// These containers are also included in |
+// common_media_types/proprietary_media_types. See crbug.com/461012. |
+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"}, |
+// Android does not support Opus in Ogg container. |
+#if defined(OS_ANDROID) |
+ {"video/ogg", "theora,vorbis"}, |
+ {"audio/ogg", "vorbis"}, |
+ {"application/ogg", "theora,vorbis"}, |
+#else |
+ {"video/ogg", "opus,theora,vorbis"}, |
+ {"audio/ogg", "opus,vorbis"}, |
+ {"application/ogg", "opus,theora,vorbis"}, |
+#endif |
+ {"audio/mpeg", "mp3"}, |
+ {"audio/mp3", ""}, |
+ {"audio/x-mp3", ""}, |
+ {"audio/mp4", kMP4AudioCodecsExpression}, |
+ {"audio/x-m4a", kMP4AudioCodecsExpression}, |
+ {"video/mp4", kMP4VideoCodecsExpression}, |
+ {"video/x-m4v", kMP4VideoCodecsExpression}, |
+ {"application/x-mpegurl", kMP4VideoCodecsExpression}, |
+ {"application/vnd.apple.mpegurl", kMP4VideoCodecsExpression}}; |
+ |
+struct CodecIDMappings { |
+ const char* const codec_id; |
+ MimeUtil::Codec codec; |
+}; |
+ |
+// List of codec IDs that provide enough information to determine the |
+// codec and profile being requested. |
+// |
+// The "mp4a" strings come from RFC 6381. |
+static const CodecIDMappings kUnambiguousCodecStringMap[] = { |
+ {"1", MimeUtil::PCM}, // We only allow this for WAV so it isn't ambiguous. |
+ // avc1/avc3.XXXXXX may be unambiguous; handled by ParseH264CodecID(). |
+ {"mp3", MimeUtil::MP3}, |
+ {"mp4a.66", MimeUtil::MPEG2_AAC_MAIN}, |
+ {"mp4a.67", MimeUtil::MPEG2_AAC_LC}, |
+ {"mp4a.68", MimeUtil::MPEG2_AAC_SSR}, |
+ {"mp4a.69", MimeUtil::MP3}, |
+ {"mp4a.6B", MimeUtil::MP3}, |
+ {"mp4a.40.2", MimeUtil::MPEG4_AAC_LC}, |
+ {"mp4a.40.02", MimeUtil::MPEG4_AAC_LC}, |
+ {"mp4a.40.5", MimeUtil::MPEG4_AAC_SBR_v1}, |
+ {"mp4a.40.05", MimeUtil::MPEG4_AAC_SBR_v1}, |
+ {"mp4a.40.29", MimeUtil::MPEG4_AAC_SBR_PS_v2}, |
+ {"vorbis", MimeUtil::VORBIS}, |
+ {"opus", MimeUtil::OPUS}, |
+ {"vp8", MimeUtil::VP8}, |
+ {"vp8.0", MimeUtil::VP8}, |
+ {"vp9", MimeUtil::VP9}, |
+ {"vp9.0", MimeUtil::VP9}, |
+ {"theora", MimeUtil::THEORA}}; |
+ |
+// List of codec IDs that are ambiguous and don't provide |
+// enough information to determine the codec and profile. |
+// The codec in these entries indicate the codec and profile |
+// we assume the user is trying to indicate. |
+static const CodecIDMappings kAmbiguousCodecStringMap[] = { |
+ {"mp4a.40", MimeUtil::MPEG4_AAC_LC}, |
+ {"avc1", MimeUtil::H264_BASELINE}, |
+ {"avc3", MimeUtil::H264_BASELINE}, |
+ // avc1/avc3.XXXXXX may be ambiguous; handled by ParseH264CodecID(). |
+}; |
+ |
+MimeUtil::MimeUtil() : allow_proprietary_codecs_(false) { |
+ InitializeMimeTypeMaps(); |
+} |
+ |
+SupportsType MimeUtil::AreSupportedCodecs( |
+ const CodecSet& supported_codecs, |
+ const std::vector<std::string>& codecs) const { |
+ DCHECK(!supported_codecs.empty()); |
+ DCHECK(!codecs.empty()); |
+ |
+ SupportsType result = IsSupported; |
+ for (size_t i = 0; i < codecs.size(); ++i) { |
+ bool is_ambiguous = true; |
+ Codec codec = INVALID_CODEC; |
+ if (!StringToCodec(codecs[i], &codec, &is_ambiguous)) |
+ return IsNotSupported; |
+ |
+ if (!IsCodecSupported(codec) || |
+ supported_codecs.find(codec) == supported_codecs.end()) { |
+ return IsNotSupported; |
+ } |
+ |
+ if (is_ambiguous) |
+ result = MayBeSupported; |
+ } |
+ |
+ return result; |
+} |
+ |
+void MimeUtil::InitializeMimeTypeMaps() { |
+ // Initialize the supported media types. |
+ for (size_t i = 0; i < arraysize(common_media_types); ++i) { |
+#if defined(OS_ANDROID) |
+ if (!IsMimeTypeSupportedOnAndroid(common_media_types[i])) |
+ continue; |
+#endif |
+ media_map_.insert(common_media_types[i]); |
+ } |
+#if defined(USE_PROPRIETARY_CODECS) |
+ allow_proprietary_codecs_ = true; |
+ for (size_t i = 0; i < arraysize(proprietary_media_types); ++i) |
+ media_map_.insert(proprietary_media_types[i]); |
+#endif |
+ |
+ for (size_t i = 0; i < arraysize(kUnambiguousCodecStringMap); ++i) { |
+ string_to_codec_map_[kUnambiguousCodecStringMap[i].codec_id] = |
+ CodecEntry(kUnambiguousCodecStringMap[i].codec, false); |
+ } |
+ |
+ for (size_t i = 0; i < arraysize(kAmbiguousCodecStringMap); ++i) { |
+ string_to_codec_map_[kAmbiguousCodecStringMap[i].codec_id] = |
+ CodecEntry(kAmbiguousCodecStringMap[i].codec, true); |
+ } |
+ |
+ // Initialize the strict supported media types. |
+ for (size_t i = 0; i < arraysize(format_codec_mappings); ++i) { |
+ std::vector<std::string> mime_type_codecs; |
+ ParseCodecString(format_codec_mappings[i].codecs_list, |
+ &mime_type_codecs, |
+ false); |
+ |
+ CodecSet codecs; |
+ for (size_t j = 0; j < mime_type_codecs.size(); ++j) { |
+ Codec codec = INVALID_CODEC; |
+ bool is_ambiguous = true; |
+ CHECK(StringToCodec(mime_type_codecs[j], &codec, &is_ambiguous)); |
+ DCHECK(!is_ambiguous); |
+ codecs.insert(codec); |
+ } |
+ |
+ strict_format_map_[format_codec_mappings[i].mime_type] = codecs; |
+ } |
+} |
+ |
+bool MimeUtil::IsSupportedMediaMimeType(const std::string& mime_type) const { |
+ return media_map_.find(base::StringToLowerASCII(mime_type)) != |
+ media_map_.end(); |
+} |
+ |
+bool MimeUtil::AreSupportedMediaCodecs( |
+ const std::vector<std::string>& codecs) const { |
+ for (size_t i = 0; i < codecs.size(); ++i) { |
+ Codec codec = INVALID_CODEC; |
+ bool is_ambiguous = true; |
+ if (!StringToCodec(codecs[i], &codec, &is_ambiguous) || |
+ !IsCodecSupported(codec)) { |
+ return false; |
+ } |
+ } |
+ return true; |
+} |
+ |
+void MimeUtil::ParseCodecString(const std::string& codecs, |
+ std::vector<std::string>* codecs_out, |
+ bool strip) { |
+ std::string no_quote_codecs; |
+ base::TrimString(codecs, "\"", &no_quote_codecs); |
+ base::SplitString(no_quote_codecs, ',', codecs_out); |
+ |
+ if (!strip) |
+ return; |
+ |
+ // Strip everything past the first '.' |
+ for (std::vector<std::string>::iterator it = codecs_out->begin(); |
+ it != codecs_out->end(); |
+ ++it) { |
+ size_t found = it->find_first_of('.'); |
+ if (found != std::string::npos) |
+ it->resize(found); |
+ } |
+} |
+ |
+bool MimeUtil::IsStrictMediaMimeType(const std::string& mime_type) const { |
+ return strict_format_map_.find(base::StringToLowerASCII(mime_type)) != |
+ strict_format_map_.end(); |
+} |
+ |
+SupportsType MimeUtil::IsSupportedStrictMediaMimeType( |
+ const std::string& mime_type, |
+ const std::vector<std::string>& codecs) const { |
+ const std::string mime_type_lower_case = base::StringToLowerASCII(mime_type); |
+ StrictMappings::const_iterator it_strict_map = |
+ strict_format_map_.find(mime_type_lower_case); |
+ if (it_strict_map == strict_format_map_.end()) |
+ return codecs.empty() ? MayBeSupported : IsNotSupported; |
+ |
+ if (it_strict_map->second.empty()) { |
+ // We get here if the mimetype does not expect a codecs parameter. |
+ return (codecs.empty() && |
+ IsDefaultCodecSupportedLowerCase(mime_type_lower_case)) |
+ ? IsSupported |
+ : IsNotSupported; |
+ } |
+ |
+ if (codecs.empty()) { |
+ // We get here if the mimetype expects to get a codecs parameter, |
+ // but didn't get one. If |mime_type_lower_case| does not have a default |
+ // codec the best we can do is say "maybe" because we don't have enough |
+ // information. |
+ Codec default_codec = INVALID_CODEC; |
+ if (!GetDefaultCodecLowerCase(mime_type_lower_case, &default_codec)) |
+ return MayBeSupported; |
+ |
+ return IsCodecSupported(default_codec) ? IsSupported : IsNotSupported; |
+ } |
+ |
+ return AreSupportedCodecs(it_strict_map->second, codecs); |
+} |
+ |
+void MimeUtil::RemoveProprietaryMediaTypesAndCodecsForTests() { |
+ for (size_t i = 0; i < arraysize(proprietary_media_types); ++i) { |
+ media_map_.erase(proprietary_media_types[i]); |
+ } |
+ allow_proprietary_codecs_ = false; |
+} |
+ |
+// Returns true iff |profile_str| conforms to hex string "42y0", where y is one |
+// of [8..F]. Requiring constraint_set0_flag be set and profile_idc be 0x42 is |
+// taken from ISO-14496-10 7.3.2.1, 7.4.2.1, and Annex A.2.1. |
+// |
+// |profile_str| is the first four characters of the H.264 suffix string |
+// (ignoring the last 2 characters of the full 6 character suffix that are |
+// level_idc). From ISO-14496-10 7.3.2.1, it consists of: |
+// 8 bits: profile_idc: required to be 0x42 here. |
+// 1 bit: constraint_set0_flag : required to be true here. |
+// 1 bit: constraint_set1_flag : ignored here. |
+// 1 bit: constraint_set2_flag : ignored here. |
+// 1 bit: constraint_set3_flag : ignored here. |
+// 4 bits: reserved : required to be 0 here. |
+// |
+// The spec indicates other ways, not implemented here, that a |profile_str| |
+// can indicate a baseline conforming decoder is sufficient for decode in Annex |
+// A.2.1: "[profile_idc not necessarily 0x42] with constraint_set0_flag set and |
+// in which level_idc and constraint_set3_flag represent a level less than or |
+// equal to the specified level." |
+static bool IsValidH264BaselineProfile(const std::string& profile_str) { |
+ uint32 constraint_set_bits; |
+ if (profile_str.size() != 4 || |
+ profile_str[0] != '4' || |
+ profile_str[1] != '2' || |
+ profile_str[3] != '0' || |
+ !base::HexStringToUInt(base::StringPiece(profile_str.c_str() + 2, 1), |
+ &constraint_set_bits)) { |
+ return false; |
+ } |
+ |
+ return constraint_set_bits >= 8; |
+} |
+ |
+static bool IsValidH264Level(const std::string& level_str) { |
+ uint32 level; |
+ if (level_str.size() != 2 || !base::HexStringToUInt(level_str, &level)) |
+ return false; |
+ |
+ // Valid levels taken from Table A-1 in ISO-14496-10. |
+ // Essentially |level_str| is toHex(10 * level). |
+ return ((level >= 10 && level <= 13) || |
+ (level >= 20 && level <= 22) || |
+ (level >= 30 && level <= 32) || |
+ (level >= 40 && level <= 42) || |
+ (level >= 50 && level <= 51)); |
+} |
+ |
+// Handle parsing H.264 codec IDs as outlined in RFC 6381 and ISO-14496-10. |
+// avc1.42y0xx, y >= 8 - H.264 Baseline |
+// avc1.4D40xx - H.264 Main |
+// avc1.6400xx - H.264 High |
+// |
+// avc1.xxxxxx & avc3.xxxxxx are considered ambiguous forms that are trying to |
+// signal H.264 Baseline. For example, the idc_level, profile_idc and |
+// constraint_set3_flag pieces may explicitly require decoder to conform to |
+// baseline profile at the specified level (see Annex A and constraint_set0 in |
+// ISO-14496-10). |
+static bool ParseH264CodecID(const std::string& codec_id, |
+ MimeUtil::Codec* codec, |
+ bool* is_ambiguous) { |
+ // Make sure we have avc1.xxxxxx or avc3.xxxxxx |
+ if (codec_id.size() != 11 || |
+ (!StartsWithASCII(codec_id, "avc1.", true) && |
+ !StartsWithASCII(codec_id, "avc3.", true))) { |
+ return false; |
+ } |
+ |
+ std::string profile = StringToUpperASCII(codec_id.substr(5, 4)); |
+ if (IsValidH264BaselineProfile(profile)) { |
+ *codec = MimeUtil::H264_BASELINE; |
+ } else if (profile == "4D40") { |
+ *codec = MimeUtil::H264_MAIN; |
+ } else if (profile == "6400") { |
+ *codec = MimeUtil::H264_HIGH; |
+ } else { |
+ *codec = MimeUtil::H264_BASELINE; |
+ *is_ambiguous = true; |
+ return true; |
+ } |
+ |
+ *is_ambiguous = !IsValidH264Level(StringToUpperASCII(codec_id.substr(9))); |
+ return true; |
+} |
+ |
+bool MimeUtil::StringToCodec(const std::string& codec_id, |
+ Codec* codec, |
+ bool* is_ambiguous) const { |
+ StringToCodecMappings::const_iterator itr = |
+ string_to_codec_map_.find(codec_id); |
+ if (itr != string_to_codec_map_.end()) { |
+ *codec = itr->second.codec; |
+ *is_ambiguous = itr->second.is_ambiguous; |
+ return true; |
+ } |
+ |
+ // If |codec_id| is not in |string_to_codec_map_|, then we assume that it is |
+ // an H.264 codec ID because currently those are the only ones that can't be |
+ // stored in the |string_to_codec_map_| and require parsing. |
+ return ParseH264CodecID(codec_id, codec, is_ambiguous); |
+} |
+ |
+bool MimeUtil::IsCodecSupported(Codec codec) const { |
+ DCHECK_NE(codec, INVALID_CODEC); |
+ |
+#if defined(OS_ANDROID) |
+ if (!IsCodecSupportedOnAndroid(codec)) |
+ return false; |
+#endif |
+ |
+ return allow_proprietary_codecs_ || !IsCodecProprietary(codec); |
+} |
+ |
+bool MimeUtil::IsCodecProprietary(Codec codec) const { |
+ switch (codec) { |
+ case INVALID_CODEC: |
+ case MP3: |
+ case MPEG2_AAC_LC: |
+ case MPEG2_AAC_MAIN: |
+ case MPEG2_AAC_SSR: |
+ case MPEG4_AAC_LC: |
+ case MPEG4_AAC_SBR_v1: |
+ case MPEG4_AAC_SBR_PS_v2: |
+ case H264_BASELINE: |
+ case H264_MAIN: |
+ case H264_HIGH: |
+ return true; |
+ |
+ case PCM: |
+ case VORBIS: |
+ case OPUS: |
+ case VP8: |
+ case VP9: |
+ case THEORA: |
+ return false; |
+ } |
+ |
+ return true; |
+} |
+ |
+bool MimeUtil::GetDefaultCodecLowerCase(const std::string& mime_type_lower_case, |
+ Codec* default_codec) const { |
+ if (mime_type_lower_case == "audio/mpeg" || |
+ mime_type_lower_case == "audio/mp3" || |
+ mime_type_lower_case == "audio/x-mp3") { |
+ *default_codec = MimeUtil::MP3; |
+ return true; |
+ } |
+ |
+ return false; |
+} |
+ |
+bool MimeUtil::IsDefaultCodecSupportedLowerCase( |
+ const std::string& mime_type_lower_case) const { |
+ Codec default_codec = Codec::INVALID_CODEC; |
+ if (!GetDefaultCodecLowerCase(mime_type_lower_case, &default_codec)) |
+ return false; |
+ return IsCodecSupported(default_codec); |
+} |
+ |
+bool IsSupportedMediaMimeType(const std::string& mime_type) { |
+ return g_mime_util.Get().IsSupportedMediaMimeType(mime_type); |
+} |
+ |
+bool AreSupportedMediaCodecs(const std::vector<std::string>& codecs) { |
+ return g_mime_util.Get().AreSupportedMediaCodecs(codecs); |
+} |
+ |
+bool IsStrictMediaMimeType(const std::string& mime_type) { |
+ return g_mime_util.Get().IsStrictMediaMimeType(mime_type); |
+} |
+ |
+SupportsType IsSupportedStrictMediaMimeType( |
+ const std::string& mime_type, |
+ const std::vector<std::string>& codecs) { |
+ return g_mime_util.Get().IsSupportedStrictMediaMimeType(mime_type, codecs); |
+} |
+ |
+void ParseCodecString(const std::string& codecs, |
+ std::vector<std::string>* codecs_out, |
+ const bool strip) { |
+ g_mime_util.Get().ParseCodecString(codecs, codecs_out, strip); |
+} |
+ |
+void RemoveProprietaryMediaTypesAndCodecsForTests() { |
+ g_mime_util.Get().RemoveProprietaryMediaTypesAndCodecsForTests(); |
+} |
+ |
+} // namespace media |