| OLD | NEW |
| 1 // Copyright 2012 The Chromium Authors. All rights reserved. | 1 // Copyright 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "media/base/mime_util_internal.h" | 5 #include "media/base/mime_util_internal.h" |
| 6 | 6 |
| 7 #include <map> |
| 8 |
| 7 #include "base/command_line.h" | 9 #include "base/command_line.h" |
| 8 #include "base/strings/string_number_conversions.h" | 10 #include "base/strings/string_number_conversions.h" |
| 9 #include "base/strings/string_split.h" | 11 #include "base/strings/string_split.h" |
| 10 #include "base/strings/string_util.h" | 12 #include "base/strings/string_util.h" |
| 11 #include "build/build_config.h" | 13 #include "build/build_config.h" |
| 12 #include "media/base/media.h" | 14 #include "media/base/media.h" |
| 13 #include "media/base/media_client.h" | 15 #include "media/base/media_client.h" |
| 14 #include "media/base/media_switches.h" | 16 #include "media/base/media_switches.h" |
| 15 #include "media/base/video_codecs.h" | 17 #include "media/base/video_codecs.h" |
| 16 #include "media/media_features.h" | 18 #include "media/media_features.h" |
| 17 | 19 |
| 18 #if defined(OS_ANDROID) | 20 #if defined(OS_ANDROID) |
| 19 #include "base/android/build_info.h" | 21 #include "base/android/build_info.h" |
| 20 #include "media/base/android/media_codec_util.h" | 22 #include "media/base/android/media_codec_util.h" |
| 21 #endif | 23 #endif |
| 22 | 24 |
| 23 namespace media { | 25 namespace media { |
| 24 namespace internal { | 26 namespace internal { |
| 25 | 27 |
| 26 struct CodecIDMappings { | 28 // Wrapped to avoid static initializer startup cost. |
| 27 const char* const codec_id; | 29 const std::map<std::string, MimeUtil::Codec>& GetStringToCodecMap() { |
| 28 MimeUtil::Codec codec; | 30 static const std::map<std::string, MimeUtil::Codec> kStringToCodecMap = { |
| 29 }; | 31 // We only allow this for WAV so it isn't ambiguous. |
| 30 | 32 {"1", MimeUtil::PCM}, |
| 31 // List of codec IDs that provide enough information to determine the | |
| 32 // codec and profile being requested. | |
| 33 // | |
| 34 // The "mp4a" strings come from RFC 6381. | |
| 35 static const CodecIDMappings kUnambiguousCodecStringMap[] = { | |
| 36 {"1", MimeUtil::PCM}, // We only allow this for WAV so it isn't ambiguous. | |
| 37 // avc1/avc3.XXXXXX may be unambiguous; handled by ParseAVCCodecId(). | 33 // avc1/avc3.XXXXXX may be unambiguous; handled by ParseAVCCodecId(). |
| 38 // hev1/hvc1.XXXXXX may be unambiguous; handled by ParseHEVCCodecID(). | 34 // hev1/hvc1.XXXXXX may be unambiguous; handled by ParseHEVCCodecID(). |
| 39 // vp9, vp9.0, vp09.xx.xx.xx.xx.xx.xx.xx may be unambiguous; handled by | 35 // vp9, vp9.0, vp09.xx.xx.xx.xx.xx.xx.xx may be unambiguous; handled by |
| 40 // ParseVp9CodecID(). | 36 // ParseVp9CodecID(). |
| 41 {"mp3", MimeUtil::MP3}, | 37 {"mp3", MimeUtil::MP3}, |
| 42 // Following is the list of RFC 6381 compliant audio codec strings: | 38 // Following is the list of RFC 6381 compliant audio codec strings: |
| 43 // mp4a.66 - MPEG-2 AAC MAIN | 39 // mp4a.66 - MPEG-2 AAC MAIN |
| 44 // mp4a.67 - MPEG-2 AAC LC | 40 // mp4a.67 - MPEG-2 AAC LC |
| 45 // mp4a.68 - MPEG-2 AAC SSR | 41 // mp4a.68 - MPEG-2 AAC SSR |
| 46 // mp4a.69 - MPEG-2 extension to MPEG-1 (MP3) | 42 // mp4a.69 - MPEG-2 extension to MPEG-1 (MP3) |
| 47 // mp4a.6B - MPEG-1 audio (MP3) | 43 // mp4a.6B - MPEG-1 audio (MP3) |
| 48 // mp4a.40.2 - MPEG-4 AAC LC | 44 // mp4a.40.2 - MPEG-4 AAC LC |
| 49 // mp4a.40.02 - MPEG-4 AAC LC (leading 0 in aud-oti for compatibility) | 45 // mp4a.40.02 - MPEG-4 AAC LC (leading 0 in aud-oti for compatibility) |
| 50 // mp4a.40.5 - MPEG-4 HE-AAC v1 (AAC LC + SBR) | 46 // mp4a.40.5 - MPEG-4 HE-AAC v1 (AAC LC + SBR) |
| 51 // mp4a.40.05 - MPEG-4 HE-AAC v1 (AAC LC + SBR) (leading 0 in aud-oti for | 47 // mp4a.40.05 - MPEG-4 HE-AAC v1 (AAC LC + SBR) (leading 0 in aud-oti |
| 52 // compatibility) | 48 // for compatibility) |
| 53 // mp4a.40.29 - MPEG-4 HE-AAC v2 (AAC LC + SBR + PS) | 49 // mp4a.40.29 - MPEG-4 HE-AAC v2 (AAC LC + SBR + PS) |
| 54 {"mp4a.66", MimeUtil::MPEG2_AAC}, | 50 {"mp4a.66", MimeUtil::MPEG2_AAC}, |
| 55 {"mp4a.67", MimeUtil::MPEG2_AAC}, | 51 {"mp4a.67", MimeUtil::MPEG2_AAC}, |
| 56 {"mp4a.68", MimeUtil::MPEG2_AAC}, | 52 {"mp4a.68", MimeUtil::MPEG2_AAC}, |
| 57 {"mp4a.69", MimeUtil::MP3}, | 53 {"mp4a.69", MimeUtil::MP3}, |
| 58 {"mp4a.6B", MimeUtil::MP3}, | 54 {"mp4a.6B", MimeUtil::MP3}, |
| 59 {"mp4a.40.2", MimeUtil::MPEG4_AAC}, | 55 {"mp4a.40.2", MimeUtil::MPEG4_AAC}, |
| 60 {"mp4a.40.02", MimeUtil::MPEG4_AAC}, | 56 {"mp4a.40.02", MimeUtil::MPEG4_AAC}, |
| 61 {"mp4a.40.5", MimeUtil::MPEG4_AAC}, | 57 {"mp4a.40.5", MimeUtil::MPEG4_AAC}, |
| 62 {"mp4a.40.05", MimeUtil::MPEG4_AAC}, | 58 {"mp4a.40.05", MimeUtil::MPEG4_AAC}, |
| 63 {"mp4a.40.29", MimeUtil::MPEG4_AAC}, | 59 {"mp4a.40.29", MimeUtil::MPEG4_AAC}, |
| 64 #if BUILDFLAG(ENABLE_AC3_EAC3_AUDIO_DEMUXING) | 60 #if BUILDFLAG(ENABLE_AC3_EAC3_AUDIO_DEMUXING) |
| 65 // TODO(servolk): Strictly speaking only mp4a.A5 and mp4a.A6 codec ids are | 61 // TODO(servolk): Strictly speaking only mp4a.A5 and mp4a.A6 codec ids are |
| 66 // valid according to RFC 6381 section 3.3, 3.4. Lower-case oti (mp4a.a5 and | 62 // valid according to RFC 6381 section 3.3, 3.4. Lower-case oti (mp4a.a5 |
| 67 // mp4a.a6) should be rejected. But we used to allow those in older versions | 63 // and mp4a.a6) should be rejected. But we used to allow those in older |
| 68 // of Chromecast firmware and some apps (notably MPL) depend on those codec | 64 // versions of Chromecast firmware and some apps (notably MPL) depend on |
| 69 // types being supported, so they should be allowed for now | 65 // those codec types being supported, so they should be allowed for now |
| 70 // (crbug.com/564960). | 66 // (crbug.com/564960). |
| 71 {"ac-3", MimeUtil::AC3}, | 67 {"ac-3", MimeUtil::AC3}, |
| 72 {"mp4a.a5", MimeUtil::AC3}, | 68 {"mp4a.a5", MimeUtil::AC3}, |
| 73 {"mp4a.A5", MimeUtil::AC3}, | 69 {"mp4a.A5", MimeUtil::AC3}, |
| 74 {"ec-3", MimeUtil::EAC3}, | 70 {"ec-3", MimeUtil::EAC3}, |
| 75 {"mp4a.a6", MimeUtil::EAC3}, | 71 {"mp4a.a6", MimeUtil::EAC3}, |
| 76 {"mp4a.A6", MimeUtil::EAC3}, | 72 {"mp4a.A6", MimeUtil::EAC3}, |
| 77 #endif | 73 #endif |
| 78 {"vorbis", MimeUtil::VORBIS}, | 74 {"vorbis", MimeUtil::VORBIS}, |
| 79 {"opus", MimeUtil::OPUS}, | 75 {"opus", MimeUtil::OPUS}, |
| 80 {"flac", MimeUtil::FLAC}, | 76 {"flac", MimeUtil::FLAC}, |
| 81 {"vp8", MimeUtil::VP8}, | 77 {"vp8", MimeUtil::VP8}, |
| 82 {"vp8.0", MimeUtil::VP8}, | 78 {"vp8.0", MimeUtil::VP8}, |
| 83 {"theora", MimeUtil::THEORA}}; | 79 {"theora", MimeUtil::THEORA} |
| 80 }; |
| 84 | 81 |
| 85 // List of codec IDs that are ambiguous and don't provide | 82 return kStringToCodecMap; |
| 86 // enough information to determine the codec and profile. | 83 } |
| 87 // The codec in these entries indicate the codec and profile | |
| 88 // we assume the user is trying to indicate. | |
| 89 static const CodecIDMappings kAmbiguousCodecStringMap[] = { | |
| 90 {"mp4a.40", MimeUtil::MPEG4_AAC}, | |
| 91 {"avc1", MimeUtil::H264}, | |
| 92 {"avc3", MimeUtil::H264}, | |
| 93 // avc1/avc3.XXXXXX may be ambiguous; handled by ParseAVCCodecId(). | |
| 94 }; | |
| 95 | 84 |
| 96 static bool ParseVp9CodecID(const std::string& mime_type_lower_case, | 85 static bool ParseVp9CodecID(const std::string& mime_type_lower_case, |
| 97 const std::string& codec_id, | 86 const std::string& codec_id, |
| 98 VideoCodecProfile* out_profile, | 87 VideoCodecProfile* out_profile, |
| 99 uint8_t* out_level) { | 88 uint8_t* out_level) { |
| 100 if (mime_type_lower_case == "video/mp4") { | 89 if (mime_type_lower_case == "video/mp4") { |
| 101 if (base::CommandLine::ForCurrentProcess()->HasSwitch( | 90 if (base::CommandLine::ForCurrentProcess()->HasSwitch( |
| 102 switches::kEnableVp9InMp4)) { | 91 switches::kEnableVp9InMp4)) { |
| 103 return ParseNewStyleVp9CodecID(codec_id, out_profile, out_level); | 92 return ParseNewStyleVp9CodecID(codec_id, out_profile, out_level); |
| 104 } | 93 } |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 157 return kUnknownVideoCodec; | 146 return kUnknownVideoCodec; |
| 158 } | 147 } |
| 159 | 148 |
| 160 SupportsType MimeUtil::AreSupportedCodecs( | 149 SupportsType MimeUtil::AreSupportedCodecs( |
| 161 const CodecSet& supported_codecs, | 150 const CodecSet& supported_codecs, |
| 162 const std::vector<std::string>& codecs, | 151 const std::vector<std::string>& codecs, |
| 163 const std::string& mime_type_lower_case, | 152 const std::string& mime_type_lower_case, |
| 164 bool is_encrypted) const { | 153 bool is_encrypted) const { |
| 165 DCHECK(!supported_codecs.empty()); | 154 DCHECK(!supported_codecs.empty()); |
| 166 DCHECK(!codecs.empty()); | 155 DCHECK(!codecs.empty()); |
| 156 DCHECK_EQ(base::ToLowerASCII(mime_type_lower_case), mime_type_lower_case); |
| 167 | 157 |
| 168 SupportsType result = IsSupported; | 158 SupportsType combined_result = IsSupported; |
| 159 |
| 169 for (size_t i = 0; i < codecs.size(); ++i) { | 160 for (size_t i = 0; i < codecs.size(); ++i) { |
| 170 bool is_ambiguous = true; | 161 // Parse the string. |
| 162 bool ambiguous_codec_string = false; |
| 171 Codec codec = INVALID_CODEC; | 163 Codec codec = INVALID_CODEC; |
| 172 VideoCodecProfile video_profile = VIDEO_CODEC_PROFILE_UNKNOWN; | 164 VideoCodecProfile video_profile = VIDEO_CODEC_PROFILE_UNKNOWN; |
| 173 uint8_t video_level = 0; | 165 uint8_t video_level = 0; |
| 174 if (!StringToCodec(mime_type_lower_case, codecs[i], &codec, &is_ambiguous, | 166 if (!ParseCodecString(mime_type_lower_case, codecs[i], &codec, |
| 175 &video_profile, &video_level, is_encrypted)) { | 167 &ambiguous_codec_string, &video_profile, |
| 168 &video_level)) { |
| 176 return IsNotSupported; | 169 return IsNotSupported; |
| 177 } | 170 } |
| 178 | 171 |
| 179 VideoCodec video_codec = MimeUtilToVideoCodec(codec); | 172 // Bail if codec not in supported list for given container. |
| 173 if (supported_codecs.find(codec) == supported_codecs.end()) |
| 174 return IsNotSupported; |
| 180 | 175 |
| 181 if (GetMediaClient() && video_codec != kUnknownVideoCodec && | 176 // Make conservative guesses to resolve ambiguity before checking platform |
| 182 !GetMediaClient()->IsSupportedVideoConfig(video_codec, video_profile, | 177 // support. H264 and VP9 are the only allowed ambiguous video codec. DO NOT |
| 183 video_level)) { | 178 // ADD SUPPORT FOR MORE AMIBIGUOUS STRINGS. |
| 184 return IsNotSupported; | 179 if (codec == MimeUtil::H264 && ambiguous_codec_string) { |
| 180 if (video_profile == VIDEO_CODEC_PROFILE_UNKNOWN) |
| 181 video_profile = H264PROFILE_BASELINE; |
| 182 if (!IsValidH264Level(video_level)) |
| 183 video_level = 10; |
| 184 } else if (codec == MimeUtil::VP9 && video_level == 0) { |
| 185 // Original VP9 content type (codecs="vp9") does not specify the level. |
| 186 // TODO(chcunningham): Mark this string as ambiguous when new multi-part |
| 187 // VP9 content type is published. |
| 188 video_level = 10; |
| 185 } | 189 } |
| 186 | 190 |
| 187 if (!IsCodecSupported(codec, mime_type_lower_case, is_encrypted) || | 191 // Check platform support. |
| 188 supported_codecs.find(codec) == supported_codecs.end()) { | 192 SupportsType result = IsCodecSupported( |
| 193 mime_type_lower_case, codec, video_profile, video_level, is_encrypted); |
| 194 if (result == IsNotSupported) |
| 189 return IsNotSupported; | 195 return IsNotSupported; |
| 190 } | |
| 191 | 196 |
| 192 if (is_ambiguous) | 197 // If any codec is "MayBeSupported", return Maybe for the combined result. |
| 193 result = MayBeSupported; | 198 // Downgrade to MayBeSupported if we had to guess the meaning of one of the |
| 199 // codec strings. |
| 200 if (result == MayBeSupported || |
| 201 (result == IsSupported && ambiguous_codec_string)) |
| 202 combined_result = MayBeSupported; |
| 194 } | 203 } |
| 195 | 204 |
| 196 return result; | 205 return combined_result; |
| 197 } | 206 } |
| 198 | 207 |
| 199 void MimeUtil::InitializeMimeTypeMaps() { | 208 void MimeUtil::InitializeMimeTypeMaps() { |
| 200 #if BUILDFLAG(USE_PROPRIETARY_CODECS) | 209 #if BUILDFLAG(USE_PROPRIETARY_CODECS) |
| 201 allow_proprietary_codecs_ = true; | 210 allow_proprietary_codecs_ = true; |
| 202 #endif | 211 #endif |
| 203 | 212 |
| 204 for (size_t i = 0; i < arraysize(kUnambiguousCodecStringMap); ++i) { | |
| 205 string_to_codec_map_[kUnambiguousCodecStringMap[i].codec_id] = | |
| 206 CodecEntry(kUnambiguousCodecStringMap[i].codec, false); | |
| 207 } | |
| 208 | |
| 209 for (size_t i = 0; i < arraysize(kAmbiguousCodecStringMap); ++i) { | |
| 210 string_to_codec_map_[kAmbiguousCodecStringMap[i].codec_id] = | |
| 211 CodecEntry(kAmbiguousCodecStringMap[i].codec, true); | |
| 212 } | |
| 213 | |
| 214 AddSupportedMediaFormats(); | 213 AddSupportedMediaFormats(); |
| 215 } | 214 } |
| 216 | 215 |
| 217 // Each call to AddContainerWithCodecs() contains a media type | 216 // Each call to AddContainerWithCodecs() contains a media type |
| 218 // (https://en.wikipedia.org/wiki/Media_type) and corresponding media codec(s) | 217 // (https://en.wikipedia.org/wiki/Media_type) and corresponding media codec(s) |
| 219 // supported by these types/containers. | 218 // supported by these types/containers. |
| 220 // TODO(ddorwin): Replace insert() calls with initializer_list when allowed. | 219 // TODO(ddorwin): Replace insert() calls with initializer_list when allowed. |
| 221 void MimeUtil::AddSupportedMediaFormats() { | 220 void MimeUtil::AddSupportedMediaFormats() { |
| 222 CodecSet implicit_codec; | 221 CodecSet implicit_codec; |
| 223 CodecSet wav_codecs; | 222 CodecSet wav_codecs; |
| (...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 332 | 331 |
| 333 if (is_proprietary_mime_type) | 332 if (is_proprietary_mime_type) |
| 334 proprietary_media_containers_.push_back(mime_type); | 333 proprietary_media_containers_.push_back(mime_type); |
| 335 } | 334 } |
| 336 | 335 |
| 337 bool MimeUtil::IsSupportedMediaMimeType(const std::string& mime_type) const { | 336 bool MimeUtil::IsSupportedMediaMimeType(const std::string& mime_type) const { |
| 338 return media_format_map_.find(base::ToLowerASCII(mime_type)) != | 337 return media_format_map_.find(base::ToLowerASCII(mime_type)) != |
| 339 media_format_map_.end(); | 338 media_format_map_.end(); |
| 340 } | 339 } |
| 341 | 340 |
| 342 void MimeUtil::ParseCodecString(const std::string& codecs, | 341 void MimeUtil::SplitCodecsToVector(const std::string& codecs, |
| 343 std::vector<std::string>* codecs_out, | 342 std::vector<std::string>* codecs_out, |
| 344 bool strip) { | 343 bool strip) { |
| 345 *codecs_out = | 344 *codecs_out = |
| 346 base::SplitString(base::TrimString(codecs, "\"", base::TRIM_ALL), ",", | 345 base::SplitString(base::TrimString(codecs, "\"", base::TRIM_ALL), ",", |
| 347 base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL); | 346 base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL); |
| 348 | 347 |
| 349 // Convert empty or all-whitespace input to 0 results. | 348 // Convert empty or all-whitespace input to 0 results. |
| 350 if (codecs_out->size() == 1 && (*codecs_out)[0].empty()) | 349 if (codecs_out->size() == 1 && (*codecs_out)[0].empty()) |
| 351 codecs_out->clear(); | 350 codecs_out->clear(); |
| 352 | 351 |
| 353 if (!strip) | 352 if (!strip) |
| 354 return; | 353 return; |
| (...skipping 12 matching lines...) Expand all Loading... |
| 367 const std::vector<std::string>& codecs, | 366 const std::vector<std::string>& codecs, |
| 368 bool is_encrypted) const { | 367 bool is_encrypted) const { |
| 369 const std::string mime_type_lower_case = base::ToLowerASCII(mime_type); | 368 const std::string mime_type_lower_case = base::ToLowerASCII(mime_type); |
| 370 MediaFormatMappings::const_iterator it_media_format_map = | 369 MediaFormatMappings::const_iterator it_media_format_map = |
| 371 media_format_map_.find(mime_type_lower_case); | 370 media_format_map_.find(mime_type_lower_case); |
| 372 if (it_media_format_map == media_format_map_.end()) | 371 if (it_media_format_map == media_format_map_.end()) |
| 373 return IsNotSupported; | 372 return IsNotSupported; |
| 374 | 373 |
| 375 if (it_media_format_map->second.empty()) { | 374 if (it_media_format_map->second.empty()) { |
| 376 // We get here if the mimetype does not expect a codecs parameter. | 375 // We get here if the mimetype does not expect a codecs parameter. |
| 377 return (codecs.empty() && IsDefaultCodecSupportedLowerCase( | 376 if (codecs.empty()) { |
| 378 mime_type_lower_case, is_encrypted)) | 377 return IsDefaultCodecSupported(mime_type_lower_case, is_encrypted); |
| 379 ? IsSupported | 378 } else { |
| 380 : IsNotSupported; | 379 return IsNotSupported; |
| 380 } |
| 381 } | 381 } |
| 382 | 382 |
| 383 if (codecs.empty()) { | 383 if (codecs.empty()) { |
| 384 // We get here if the mimetype expects to get a codecs parameter, | 384 // We get here if the mimetype expects to get a codecs parameter, |
| 385 // but didn't get one. If |mime_type_lower_case| does not have a default | 385 // but didn't get one. If |mime_type_lower_case| does not have a default |
| 386 // codec the best we can do is say "maybe" because we don't have enough | 386 // codec the best we can do is say "maybe" because we don't have enough |
| 387 // information. | 387 // information. |
| 388 Codec default_codec = INVALID_CODEC; | 388 Codec default_codec = INVALID_CODEC; |
| 389 if (!GetDefaultCodecLowerCase(mime_type_lower_case, &default_codec)) | 389 if (!GetDefaultCodec(mime_type_lower_case, &default_codec)) |
| 390 return MayBeSupported; | 390 return MayBeSupported; |
| 391 | 391 |
| 392 return IsCodecSupported(default_codec, mime_type_lower_case, is_encrypted) | 392 return IsSimpleCodecSupported(mime_type_lower_case, default_codec, |
| 393 ? IsSupported | 393 is_encrypted); |
| 394 : IsNotSupported; | |
| 395 } | 394 } |
| 396 | 395 |
| 397 #if BUILDFLAG(ENABLE_MSE_MPEG2TS_STREAM_PARSER) | 396 #if BUILDFLAG(ENABLE_MSE_MPEG2TS_STREAM_PARSER) |
| 398 if (mime_type_lower_case == "video/mp2t") { | 397 if (mime_type_lower_case == "video/mp2t") { |
| 399 std::vector<std::string> codecs_to_check; | 398 std::vector<std::string> codecs_to_check; |
| 400 for (const auto& codec_id : codecs) { | 399 for (const auto& codec_id : codecs) { |
| 401 codecs_to_check.push_back(TranslateLegacyAvc1CodecIds(codec_id)); | 400 codecs_to_check.push_back(TranslateLegacyAvc1CodecIds(codec_id)); |
| 402 } | 401 } |
| 403 return AreSupportedCodecs(it_media_format_map->second, codecs_to_check, | 402 return AreSupportedCodecs(it_media_format_map->second, codecs_to_check, |
| 404 mime_type_lower_case, is_encrypted); | 403 mime_type_lower_case, is_encrypted); |
| 405 } | 404 } |
| 406 #endif | 405 #endif |
| 407 | 406 |
| 408 return AreSupportedCodecs(it_media_format_map->second, codecs, | 407 return AreSupportedCodecs(it_media_format_map->second, codecs, |
| 409 mime_type_lower_case, is_encrypted); | 408 mime_type_lower_case, is_encrypted); |
| 410 } | 409 } |
| 411 | 410 |
| 412 void MimeUtil::RemoveProprietaryMediaTypesAndCodecs() { | 411 void MimeUtil::RemoveProprietaryMediaTypesAndCodecs() { |
| 413 for (const auto& container : proprietary_media_containers_) | 412 for (const auto& container : proprietary_media_containers_) |
| 414 media_format_map_.erase(container); | 413 media_format_map_.erase(container); |
| 415 allow_proprietary_codecs_ = false; | 414 allow_proprietary_codecs_ = false; |
| 416 } | 415 } |
| 417 | 416 |
| 418 // static | 417 // static |
| 419 bool MimeUtil::IsCodecSupportedOnPlatform( | 418 bool MimeUtil::IsCodecSupportedOnAndroid( |
| 420 Codec codec, | 419 Codec codec, |
| 421 const std::string& mime_type_lower_case, | 420 const std::string& mime_type_lower_case, |
| 422 bool is_encrypted, | 421 bool is_encrypted, |
| 423 const PlatformInfo& platform_info) { | 422 const PlatformInfo& platform_info) { |
| 424 DCHECK_NE(mime_type_lower_case, ""); | 423 DCHECK_NE(mime_type_lower_case, ""); |
| 425 | 424 |
| 426 // Encrypted block support is never available without platform decoders. | 425 // Encrypted block support is never available without platform decoders. |
| 427 if (is_encrypted && !platform_info.has_platform_decoders) | 426 if (is_encrypted && !platform_info.has_platform_decoders) |
| 428 return false; | 427 return false; |
| 429 | 428 |
| (...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 535 return true; | 534 return true; |
| 536 | 535 |
| 537 // MediaPlayer only supports VP9 in WebM. | 536 // MediaPlayer only supports VP9 in WebM. |
| 538 return mime_type_lower_case == "video/webm"; | 537 return mime_type_lower_case == "video/webm"; |
| 539 } | 538 } |
| 540 } | 539 } |
| 541 | 540 |
| 542 return false; | 541 return false; |
| 543 } | 542 } |
| 544 | 543 |
| 545 bool MimeUtil::StringToCodec(const std::string& mime_type_lower_case, | 544 bool MimeUtil::ParseCodecString(const std::string& mime_type_lower_case, |
| 546 const std::string& codec_id, | 545 const std::string& codec_id, |
| 547 Codec* codec, | 546 Codec* codec, |
| 548 bool* is_ambiguous, | 547 bool* ambiguous_codec_string, |
| 549 VideoCodecProfile* out_profile, | 548 VideoCodecProfile* out_profile, |
| 550 uint8_t* out_level, | 549 uint8_t* out_level) const { |
| 551 bool is_encrypted) const { | 550 DCHECK_EQ(base::ToLowerASCII(mime_type_lower_case), mime_type_lower_case); |
| 551 DCHECK(codec); |
| 552 DCHECK(out_profile); | 552 DCHECK(out_profile); |
| 553 DCHECK(out_level); | 553 DCHECK(out_level); |
| 554 |
| 555 *codec = INVALID_CODEC; |
| 556 *ambiguous_codec_string = false; |
| 554 *out_profile = VIDEO_CODEC_PROFILE_UNKNOWN; | 557 *out_profile = VIDEO_CODEC_PROFILE_UNKNOWN; |
| 555 *out_level = 0; | 558 *out_level = 0; |
| 556 | 559 |
| 557 StringToCodecMappings::const_iterator itr = | 560 std::map<std::string, Codec>::const_iterator itr = |
| 558 string_to_codec_map_.find(codec_id); | 561 GetStringToCodecMap().find(codec_id); |
| 559 if (itr != string_to_codec_map_.end()) { | 562 if (itr != GetStringToCodecMap().end()) { |
| 560 *codec = itr->second.codec; | 563 *codec = itr->second; |
| 561 *is_ambiguous = itr->second.is_ambiguous; | 564 |
| 562 return true; | 565 return true; |
| 563 } | 566 } |
| 564 | 567 |
| 565 // If |codec_id| is not in |string_to_codec_map_|, then we assume that it is | 568 // Check codec string against short list of allowed ambiguous codecs. |
| 569 // Hard-coded to discourage expansion. DO NOT ADD TO THIS LIST. DO NOT |
| 570 // INCREASE PLACES WHERE |ambiguous_codec_string| = true. |
| 571 // NOTE: avc1/avc3.XXXXXX may be ambiguous handled after ParseAVCCodecId(). |
| 572 if (codec_id == "avc1" || codec_id == "avc3") { |
| 573 *codec = MimeUtil::H264; |
| 574 *ambiguous_codec_string = true; |
| 575 return true; |
| 576 } else if (codec_id == "mp4a.40") { |
| 577 *codec = MimeUtil::MPEG4_AAC; |
| 578 *ambiguous_codec_string = true; |
| 579 return true; |
| 580 } |
| 581 |
| 582 // If |codec_id| is not in |kStringToCodecMap|, then we assume that it is |
| 566 // either VP9, H.264 or HEVC/H.265 codec ID because currently those are the | 583 // either VP9, H.264 or HEVC/H.265 codec ID because currently those are the |
| 567 // only ones that are not added to the |string_to_codec_map_| and require | 584 // only ones that are not added to the |kStringToCodecMap| and require |
| 568 // parsing. | 585 // parsing. |
| 569 if (ParseVp9CodecID(mime_type_lower_case, codec_id, out_profile, out_level)) { | 586 if (ParseVp9CodecID(mime_type_lower_case, codec_id, out_profile, out_level)) { |
| 570 *codec = MimeUtil::VP9; | 587 *codec = MimeUtil::VP9; |
| 571 switch (*out_profile) { | |
| 572 case VP9PROFILE_PROFILE0: | |
| 573 // Profile 0 should always be supported if VP9 is supported. | |
| 574 *is_ambiguous = false; | |
| 575 break; | |
| 576 default: | |
| 577 // We don't know if the underlying platform supports these profiles. | |
| 578 // Need to add platform level querying to get supported profiles | |
| 579 // (crbug/604566). | |
| 580 *is_ambiguous = true; | |
| 581 break; | |
| 582 } | |
| 583 return true; | 588 return true; |
| 584 } | 589 } |
| 585 | 590 |
| 586 if (ParseAVCCodecId(codec_id, out_profile, out_level)) { | 591 if (ParseAVCCodecId(codec_id, out_profile, out_level)) { |
| 587 *codec = MimeUtil::H264; | 592 *codec = MimeUtil::H264; |
| 588 switch (*out_profile) { | 593 // Allowed string ambiguity since 2014. DO NOT ADD NEW CASES FOR AMBIGUITY. |
| 589 // HIGH10PROFILE is supported through fallback to the ffmpeg decoder | 594 *ambiguous_codec_string = !IsValidH264Level(*out_level); |
| 590 // which is not available on Android, or if FFMPEG is not used. | |
| 591 #if !defined(MEDIA_DISABLE_FFMPEG) && !defined(OS_ANDROID) | |
| 592 case H264PROFILE_HIGH10PROFILE: | |
| 593 if (is_encrypted) { | |
| 594 // FFmpeg is not generally used for encrypted videos, so we do not | |
| 595 // know whether 10-bit is supported. | |
| 596 *is_ambiguous = true; | |
| 597 break; | |
| 598 } | |
| 599 // Fall through. | |
| 600 #endif | |
| 601 | |
| 602 case H264PROFILE_BASELINE: | |
| 603 case H264PROFILE_MAIN: | |
| 604 case H264PROFILE_HIGH: | |
| 605 *is_ambiguous = !IsValidH264Level(*out_level); | |
| 606 break; | |
| 607 default: | |
| 608 *is_ambiguous = true; | |
| 609 } | |
| 610 return true; | 595 return true; |
| 611 } | 596 } |
| 612 | 597 |
| 613 #if BUILDFLAG(ENABLE_HEVC_DEMUXING) | 598 #if BUILDFLAG(ENABLE_HEVC_DEMUXING) |
| 614 if (ParseHEVCCodecId(codec_id, out_profile, out_level)) { | 599 if (ParseHEVCCodecId(codec_id, out_profile, out_level)) { |
| 615 *codec = MimeUtil::HEVC; | 600 *codec = MimeUtil::HEVC; |
| 616 *is_ambiguous = false; | |
| 617 return true; | 601 return true; |
| 618 } | 602 } |
| 619 #endif | 603 #endif |
| 620 | 604 |
| 621 DVLOG(4) << __func__ << ": Unrecognized codec id " << codec_id; | 605 DVLOG(2) << __func__ << ": Unrecognized codec id " << codec_id; |
| 622 return false; | 606 return false; |
| 623 } | 607 } |
| 624 | 608 |
| 625 bool MimeUtil::IsCodecSupported(Codec codec, | 609 SupportsType MimeUtil::IsSimpleCodecSupported( |
| 626 const std::string& mime_type_lower_case, | 610 const std::string& mime_type_lower_case, |
| 627 bool is_encrypted) const { | 611 Codec codec, |
| 612 bool is_encrypted) const { |
| 613 // Video codecs are not "simple" because they require a profile and level to |
| 614 // be specified. There is no "default" video codec for a given container. |
| 615 DCHECK_EQ(MimeUtilToVideoCodec(codec), kUnknownVideoCodec); |
| 616 |
| 617 SupportsType result = |
| 618 IsCodecSupported(mime_type_lower_case, codec, VIDEO_CODEC_PROFILE_UNKNOWN, |
| 619 0 /* video_level */, is_encrypted); |
| 620 |
| 621 // Platform support should never be ambiguous for simple codecs (no range of |
| 622 // profiles to consider). |
| 623 DCHECK_NE(result, MayBeSupported); |
| 624 return result; |
| 625 } |
| 626 |
| 627 SupportsType MimeUtil::IsCodecSupported(const std::string& mime_type_lower_case, |
| 628 Codec codec, |
| 629 VideoCodecProfile video_profile, |
| 630 uint8_t video_level, |
| 631 bool is_encrypted) const { |
| 632 DCHECK_EQ(base::ToLowerASCII(mime_type_lower_case), mime_type_lower_case); |
| 628 DCHECK_NE(codec, INVALID_CODEC); | 633 DCHECK_NE(codec, INVALID_CODEC); |
| 629 | 634 |
| 635 VideoCodec video_codec = MimeUtilToVideoCodec(codec); |
| 636 if (video_codec != kUnknownVideoCodec && |
| 637 // Theora and VP8 do not have profiles/levels. |
| 638 video_codec != kCodecTheora && video_codec != kCodecVP8) { |
| 639 DCHECK_NE(video_profile, VIDEO_CODEC_PROFILE_UNKNOWN); |
| 640 DCHECK_GT(video_level, 0); |
| 641 } |
| 642 |
| 643 // Bail early for disabled proprietary codecs |
| 644 if (!allow_proprietary_codecs_ && IsCodecProprietary(codec)) { |
| 645 return IsNotSupported; |
| 646 } |
| 647 |
| 648 // Check for cases of ambiguous platform support. |
| 649 // TODO(chcunningham): DELETE THIS. Platform should know its capabilities. |
| 650 // Answer should come from MediaClient. |
| 651 bool ambiguous_platform_support = false; |
| 652 if (codec == MimeUtil::H264) { |
| 653 switch (video_profile) { |
| 654 // Always supported |
| 655 case H264PROFILE_BASELINE: |
| 656 case H264PROFILE_MAIN: |
| 657 case H264PROFILE_HIGH: |
| 658 break; |
| 659 // HIGH10PROFILE is supported through fallback to the ffmpeg decoder |
| 660 // which is not available on Android, or if FFMPEG is not used. |
| 661 #if !defined(MEDIA_DISABLE_FFMPEG) && !defined(OS_ANDROID) |
| 662 case H264PROFILE_HIGH10PROFILE: |
| 663 // FFmpeg is not generally used for encrypted videos, so we do not |
| 664 // know whether 10-bit is supported. |
| 665 ambiguous_platform_support = is_encrypted; |
| 666 break; |
| 667 #endif |
| 668 default: |
| 669 ambiguous_platform_support = true; |
| 670 } |
| 671 } else if (codec == MimeUtil::VP9 && video_profile != VP9PROFILE_PROFILE0) { |
| 672 // We don't know if the underlying platform supports these profiles. Need |
| 673 // to add platform level querying to get supported profiles. |
| 674 // https://crbug.com/604566 |
| 675 ambiguous_platform_support = true; |
| 676 } |
| 677 |
| 678 if (GetMediaClient() && video_codec != kUnknownVideoCodec && |
| 679 !GetMediaClient()->IsSupportedVideoConfig(video_codec, video_profile, |
| 680 video_level)) { |
| 681 return IsNotSupported; |
| 682 } |
| 683 |
| 630 #if defined(OS_ANDROID) | 684 #if defined(OS_ANDROID) |
| 631 if (!IsCodecSupportedOnPlatform(codec, mime_type_lower_case, is_encrypted, | 685 // TODO(chcunningham): Delete this. Android platform support should be |
| 632 platform_info_)) { | 686 // handled by (android specific) MediaClient. |
| 633 return false; | 687 if (!IsCodecSupportedOnAndroid(codec, mime_type_lower_case, is_encrypted, |
| 688 platform_info_)) { |
| 689 return IsNotSupported; |
| 634 } | 690 } |
| 635 #endif | 691 #endif |
| 636 | 692 |
| 637 return allow_proprietary_codecs_ || !IsCodecProprietary(codec); | 693 return ambiguous_platform_support ? MayBeSupported : IsSupported; |
| 638 } | 694 } |
| 639 | 695 |
| 640 bool MimeUtil::IsCodecProprietary(Codec codec) const { | 696 bool MimeUtil::IsCodecProprietary(Codec codec) const { |
| 641 switch (codec) { | 697 switch (codec) { |
| 642 case INVALID_CODEC: | 698 case INVALID_CODEC: |
| 643 case AC3: | 699 case AC3: |
| 644 case EAC3: | 700 case EAC3: |
| 645 case MP3: | 701 case MP3: |
| 646 case MPEG2_AAC: | 702 case MPEG2_AAC: |
| 647 case MPEG4_AAC: | 703 case MPEG4_AAC: |
| 648 case H264: | 704 case H264: |
| 649 case HEVC: | 705 case HEVC: |
| 650 return true; | 706 return true; |
| 651 | 707 |
| 652 case PCM: | 708 case PCM: |
| 653 case VORBIS: | 709 case VORBIS: |
| 654 case OPUS: | 710 case OPUS: |
| 655 case FLAC: | 711 case FLAC: |
| 656 case VP8: | 712 case VP8: |
| 657 case VP9: | 713 case VP9: |
| 658 case THEORA: | 714 case THEORA: |
| 659 return false; | 715 return false; |
| 660 } | 716 } |
| 661 | 717 |
| 662 return true; | 718 return true; |
| 663 } | 719 } |
| 664 | 720 |
| 665 bool MimeUtil::GetDefaultCodecLowerCase(const std::string& mime_type_lower_case, | 721 bool MimeUtil::GetDefaultCodec(const std::string& mime_type, |
| 666 Codec* default_codec) const { | 722 Codec* default_codec) const { |
| 667 if (mime_type_lower_case == "audio/mpeg" || | 723 if (mime_type == "audio/mpeg" || mime_type == "audio/mp3" || |
| 668 mime_type_lower_case == "audio/mp3" || | 724 mime_type == "audio/x-mp3") { |
| 669 mime_type_lower_case == "audio/x-mp3") { | |
| 670 *default_codec = MimeUtil::MP3; | 725 *default_codec = MimeUtil::MP3; |
| 671 return true; | 726 return true; |
| 672 } | 727 } |
| 673 | 728 |
| 674 if (mime_type_lower_case == "audio/aac") { | 729 if (mime_type == "audio/aac") { |
| 675 *default_codec = MimeUtil::MPEG4_AAC; | 730 *default_codec = MimeUtil::MPEG4_AAC; |
| 676 return true; | 731 return true; |
| 677 } | 732 } |
| 678 | 733 |
| 679 if (mime_type_lower_case == "audio/flac") { | 734 if (mime_type == "audio/flac") { |
| 680 *default_codec = MimeUtil::FLAC; | 735 *default_codec = MimeUtil::FLAC; |
| 681 return true; | 736 return true; |
| 682 } | 737 } |
| 683 | 738 |
| 684 return false; | 739 return false; |
| 685 } | 740 } |
| 686 | 741 |
| 687 bool MimeUtil::IsDefaultCodecSupportedLowerCase( | 742 SupportsType MimeUtil::IsDefaultCodecSupported(const std::string& mime_type, |
| 688 const std::string& mime_type_lower_case, | 743 bool is_encrypted) const { |
| 689 bool is_encrypted) const { | |
| 690 Codec default_codec = Codec::INVALID_CODEC; | 744 Codec default_codec = Codec::INVALID_CODEC; |
| 691 if (!GetDefaultCodecLowerCase(mime_type_lower_case, &default_codec)) | 745 if (!GetDefaultCodec(mime_type, &default_codec)) |
| 692 return false; | 746 return IsNotSupported; |
| 693 return IsCodecSupported(default_codec, mime_type_lower_case, is_encrypted); | 747 return IsSimpleCodecSupported(mime_type, default_codec, is_encrypted); |
| 694 } | 748 } |
| 695 | 749 |
| 696 } // namespace internal | 750 } // namespace internal |
| 697 } // namespace media | 751 } // namespace media |
| OLD | NEW |