| 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 "base/strings/string_number_conversions.h" | 7 #include "base/strings/string_number_conversions.h" |
| 8 #include "base/strings/string_split.h" | 8 #include "base/strings/string_split.h" |
| 9 #include "base/strings/string_util.h" | 9 #include "base/strings/string_util.h" |
| 10 #include "build/build_config.h" | 10 #include "build/build_config.h" |
| (...skipping 15 matching lines...) Expand all Loading... |
| 26 }; | 26 }; |
| 27 | 27 |
| 28 // List of codec IDs that provide enough information to determine the | 28 // List of codec IDs that provide enough information to determine the |
| 29 // codec and profile being requested. | 29 // codec and profile being requested. |
| 30 // | 30 // |
| 31 // The "mp4a" strings come from RFC 6381. | 31 // The "mp4a" strings come from RFC 6381. |
| 32 static const CodecIDMappings kUnambiguousCodecStringMap[] = { | 32 static const CodecIDMappings kUnambiguousCodecStringMap[] = { |
| 33 {"1", MimeUtil::PCM}, // We only allow this for WAV so it isn't ambiguous. | 33 {"1", MimeUtil::PCM}, // We only allow this for WAV so it isn't ambiguous. |
| 34 // avc1/avc3.XXXXXX may be unambiguous; handled by ParseAVCCodecId(). | 34 // avc1/avc3.XXXXXX may be unambiguous; handled by ParseAVCCodecId(). |
| 35 // hev1/hvc1.XXXXXX may be unambiguous; handled by ParseHEVCCodecID(). | 35 // hev1/hvc1.XXXXXX may be unambiguous; handled by ParseHEVCCodecID(). |
| 36 // vp9, vp9.0, vp09.xx.xx.xx.xx.xx.xx.xx may be unambiguous; handled by | |
| 37 // ParseVp9CodecID(). | |
| 38 {"mp3", MimeUtil::MP3}, | 36 {"mp3", MimeUtil::MP3}, |
| 39 // Following is the list of RFC 6381 compliant audio codec strings: | 37 // Following is the list of RFC 6381 compliant audio codec strings: |
| 40 // mp4a.66 - MPEG-2 AAC MAIN | 38 // mp4a.66 - MPEG-2 AAC MAIN |
| 41 // mp4a.67 - MPEG-2 AAC LC | 39 // mp4a.67 - MPEG-2 AAC LC |
| 42 // mp4a.68 - MPEG-2 AAC SSR | 40 // mp4a.68 - MPEG-2 AAC SSR |
| 43 // mp4a.69 - MPEG-2 extension to MPEG-1 (MP3) | 41 // mp4a.69 - MPEG-2 extension to MPEG-1 (MP3) |
| 44 // mp4a.6B - MPEG-1 audio (MP3) | 42 // mp4a.6B - MPEG-1 audio (MP3) |
| 45 // mp4a.40.2 - MPEG-4 AAC LC | 43 // mp4a.40.2 - MPEG-4 AAC LC |
| 46 // mp4a.40.02 - MPEG-4 AAC LC (leading 0 in aud-oti for compatibility) | 44 // mp4a.40.02 - MPEG-4 AAC LC (leading 0 in aud-oti for compatibility) |
| 47 // mp4a.40.5 - MPEG-4 HE-AAC v1 (AAC LC + SBR) | 45 // mp4a.40.5 - MPEG-4 HE-AAC v1 (AAC LC + SBR) |
| (...skipping 21 matching lines...) Expand all Loading... |
| 69 {"mp4a.a5", MimeUtil::AC3}, | 67 {"mp4a.a5", MimeUtil::AC3}, |
| 70 {"mp4a.A5", MimeUtil::AC3}, | 68 {"mp4a.A5", MimeUtil::AC3}, |
| 71 {"ec-3", MimeUtil::EAC3}, | 69 {"ec-3", MimeUtil::EAC3}, |
| 72 {"mp4a.a6", MimeUtil::EAC3}, | 70 {"mp4a.a6", MimeUtil::EAC3}, |
| 73 {"mp4a.A6", MimeUtil::EAC3}, | 71 {"mp4a.A6", MimeUtil::EAC3}, |
| 74 #endif | 72 #endif |
| 75 {"vorbis", MimeUtil::VORBIS}, | 73 {"vorbis", MimeUtil::VORBIS}, |
| 76 {"opus", MimeUtil::OPUS}, | 74 {"opus", MimeUtil::OPUS}, |
| 77 {"vp8", MimeUtil::VP8}, | 75 {"vp8", MimeUtil::VP8}, |
| 78 {"vp8.0", MimeUtil::VP8}, | 76 {"vp8.0", MimeUtil::VP8}, |
| 77 {"vp9", MimeUtil::VP9}, |
| 78 {"vp9.0", MimeUtil::VP9}, |
| 79 {"theora", MimeUtil::THEORA}}; | 79 {"theora", MimeUtil::THEORA}}; |
| 80 | 80 |
| 81 // List of codec IDs that are ambiguous and don't provide | 81 // List of codec IDs that are ambiguous and don't provide |
| 82 // enough information to determine the codec and profile. | 82 // enough information to determine the codec and profile. |
| 83 // The codec in these entries indicate the codec and profile | 83 // The codec in these entries indicate the codec and profile |
| 84 // we assume the user is trying to indicate. | 84 // we assume the user is trying to indicate. |
| 85 static const CodecIDMappings kAmbiguousCodecStringMap[] = { | 85 static const CodecIDMappings kAmbiguousCodecStringMap[] = { |
| 86 {"mp4a.40", MimeUtil::MPEG4_AAC}, | 86 {"mp4a.40", MimeUtil::MPEG4_AAC}, |
| 87 {"avc1", MimeUtil::H264}, | 87 {"avc1", MimeUtil::H264}, |
| 88 {"avc3", MimeUtil::H264}, | 88 {"avc3", MimeUtil::H264}, |
| (...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 178 *is_ambiguous = false; | 178 *is_ambiguous = false; |
| 179 } | 179 } |
| 180 | 180 |
| 181 return true; | 181 return true; |
| 182 } | 182 } |
| 183 | 183 |
| 184 return false; | 184 return false; |
| 185 } | 185 } |
| 186 #endif | 186 #endif |
| 187 | 187 |
| 188 // Handle parsing of vp9 codec IDs. | |
| 189 static bool ParseVp9CodecID(const std::string& mime_type_lower_case, | |
| 190 const std::string& codec_id, | |
| 191 VideoCodecProfile* profile) { | |
| 192 if (mime_type_lower_case == "video/webm") { | |
| 193 if (codec_id == "vp9" || codec_id == "vp9.0") { | |
| 194 // Profile is not included in the codec string. Assuming profile 0 to be | |
| 195 // backward compatible. | |
| 196 *profile = VP9PROFILE_PROFILE0; | |
| 197 return true; | |
| 198 } | |
| 199 // TODO(kqyang): Should we support new codec string in WebM? | |
| 200 return false; | |
| 201 } else if (mime_type_lower_case == "audio/webm") { | |
| 202 return false; | |
| 203 } | |
| 204 | |
| 205 #if BUILDFLAG(ENABLE_MP4_VP9_DEMUXING) | |
| 206 std::vector<std::string> fields = base::SplitString( | |
| 207 codec_id, ".", base::KEEP_WHITESPACE, base::SPLIT_WANT_ALL); | |
| 208 if (fields.size() < 1) | |
| 209 return false; | |
| 210 | |
| 211 if (fields[0] != "vp09") | |
| 212 return false; | |
| 213 | |
| 214 if (fields.size() > 8) | |
| 215 return false; | |
| 216 | |
| 217 std::vector<int> values; | |
| 218 for (size_t i = 1; i < fields.size(); ++i) { | |
| 219 // Missing value is not allowed. | |
| 220 if (fields[i] == "") | |
| 221 return false; | |
| 222 int value; | |
| 223 if (!base::StringToInt(fields[i], &value)) | |
| 224 return false; | |
| 225 if (value < 0) | |
| 226 return false; | |
| 227 values.push_back(value); | |
| 228 } | |
| 229 | |
| 230 // The spec specifies 8 fields (7 values excluding the first codec field). | |
| 231 // We do not allow missing fields. | |
| 232 if (values.size() < 7) | |
| 233 return false; | |
| 234 | |
| 235 const int profile_idc = values[0]; | |
| 236 switch (profile_idc) { | |
| 237 case 0: | |
| 238 *profile = VP9PROFILE_PROFILE0; | |
| 239 break; | |
| 240 case 1: | |
| 241 *profile = VP9PROFILE_PROFILE1; | |
| 242 break; | |
| 243 case 2: | |
| 244 *profile = VP9PROFILE_PROFILE2; | |
| 245 break; | |
| 246 case 3: | |
| 247 *profile = VP9PROFILE_PROFILE3; | |
| 248 break; | |
| 249 default: | |
| 250 return false; | |
| 251 } | |
| 252 | |
| 253 const int bit_depth = values[2]; | |
| 254 if (bit_depth != 8 && bit_depth != 10 && bit_depth != 12) | |
| 255 return false; | |
| 256 | |
| 257 const int color_space = values[3]; | |
| 258 if (color_space > 7) | |
| 259 return false; | |
| 260 | |
| 261 const int chroma_subsampling = values[4]; | |
| 262 if (chroma_subsampling > 3) | |
| 263 return false; | |
| 264 | |
| 265 const int transfer_function = values[5]; | |
| 266 if (transfer_function > 1) | |
| 267 return false; | |
| 268 | |
| 269 const int video_full_range_flag = values[6]; | |
| 270 if (video_full_range_flag > 1) | |
| 271 return false; | |
| 272 | |
| 273 return true; | |
| 274 #else | |
| 275 return false; | |
| 276 #endif // #if BUILDFLAG(ENABLE_MP4_VP9_DEMUXING) | |
| 277 } | |
| 278 | |
| 279 MimeUtil::MimeUtil() : allow_proprietary_codecs_(false) { | 188 MimeUtil::MimeUtil() : allow_proprietary_codecs_(false) { |
| 280 #if defined(OS_ANDROID) | 189 #if defined(OS_ANDROID) |
| 281 platform_info_.is_unified_media_pipeline_enabled = | 190 platform_info_.is_unified_media_pipeline_enabled = |
| 282 IsUnifiedMediaPipelineEnabled(); | 191 IsUnifiedMediaPipelineEnabled(); |
| 283 // When the unified media pipeline is enabled, we need support for both GPU | 192 // When the unified media pipeline is enabled, we need support for both GPU |
| 284 // video decoders and MediaCodec; indicated by HasPlatformDecoderSupport(). | 193 // video decoders and MediaCodec; indicated by HasPlatformDecoderSupport(). |
| 285 // When the Android pipeline is used, we only need access to MediaCodec. | 194 // When the Android pipeline is used, we only need access to MediaCodec. |
| 286 platform_info_.has_platform_decoders = ArePlatformDecodersAvailable(); | 195 platform_info_.has_platform_decoders = ArePlatformDecodersAvailable(); |
| 287 platform_info_.has_platform_vp8_decoder = | 196 platform_info_.has_platform_vp8_decoder = |
| 288 MediaCodecUtil::IsVp8DecoderAvailable(); | 197 MediaCodecUtil::IsVp8DecoderAvailable(); |
| (...skipping 12 matching lines...) Expand all Loading... |
| 301 const std::vector<std::string>& codecs, | 210 const std::vector<std::string>& codecs, |
| 302 const std::string& mime_type_lower_case, | 211 const std::string& mime_type_lower_case, |
| 303 bool is_encrypted) const { | 212 bool is_encrypted) const { |
| 304 DCHECK(!supported_codecs.empty()); | 213 DCHECK(!supported_codecs.empty()); |
| 305 DCHECK(!codecs.empty()); | 214 DCHECK(!codecs.empty()); |
| 306 | 215 |
| 307 SupportsType result = IsSupported; | 216 SupportsType result = IsSupported; |
| 308 for (size_t i = 0; i < codecs.size(); ++i) { | 217 for (size_t i = 0; i < codecs.size(); ++i) { |
| 309 bool is_ambiguous = true; | 218 bool is_ambiguous = true; |
| 310 Codec codec = INVALID_CODEC; | 219 Codec codec = INVALID_CODEC; |
| 311 if (!StringToCodec(mime_type_lower_case, codecs[i], &codec, &is_ambiguous, | 220 if (!StringToCodec(codecs[i], &codec, &is_ambiguous, is_encrypted)) |
| 312 is_encrypted)) { | |
| 313 return IsNotSupported; | 221 return IsNotSupported; |
| 314 } | |
| 315 | 222 |
| 316 if (!IsCodecSupported(codec, mime_type_lower_case, is_encrypted) || | 223 if (!IsCodecSupported(codec, mime_type_lower_case, is_encrypted) || |
| 317 supported_codecs.find(codec) == supported_codecs.end()) { | 224 supported_codecs.find(codec) == supported_codecs.end()) { |
| 318 return IsNotSupported; | 225 return IsNotSupported; |
| 319 } | 226 } |
| 320 | 227 |
| 321 if (is_ambiguous) | 228 if (is_ambiguous) |
| 322 result = MayBeSupported; | 229 result = MayBeSupported; |
| 323 } | 230 } |
| 324 | 231 |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 387 #if BUILDFLAG(ENABLE_AC3_EAC3_AUDIO_DEMUXING) | 294 #if BUILDFLAG(ENABLE_AC3_EAC3_AUDIO_DEMUXING) |
| 388 mp4_audio_codecs.insert(AC3); | 295 mp4_audio_codecs.insert(AC3); |
| 389 mp4_audio_codecs.insert(EAC3); | 296 mp4_audio_codecs.insert(EAC3); |
| 390 #endif // BUILDFLAG(ENABLE_AC3_EAC3_AUDIO_DEMUXING) | 297 #endif // BUILDFLAG(ENABLE_AC3_EAC3_AUDIO_DEMUXING) |
| 391 | 298 |
| 392 CodecSet mp4_video_codecs; | 299 CodecSet mp4_video_codecs; |
| 393 mp4_video_codecs.insert(H264); | 300 mp4_video_codecs.insert(H264); |
| 394 #if BUILDFLAG(ENABLE_HEVC_DEMUXING) | 301 #if BUILDFLAG(ENABLE_HEVC_DEMUXING) |
| 395 mp4_video_codecs.insert(HEVC_MAIN); | 302 mp4_video_codecs.insert(HEVC_MAIN); |
| 396 #endif // BUILDFLAG(ENABLE_HEVC_DEMUXING) | 303 #endif // BUILDFLAG(ENABLE_HEVC_DEMUXING) |
| 397 #if BUILDFLAG(ENABLE_MP4_VP9_DEMUXING) | |
| 398 // Only VP9 with valid codec string vp09.xx.xx.xx.xx.xx.xx.xx is supported. | |
| 399 // See ParseVp9CodecID for details. | |
| 400 mp4_video_codecs.insert(VP9); | |
| 401 #endif // BUILDFLAG(ENABLE_MP4_VP9_DEMUXING) | |
| 402 CodecSet mp4_codecs(mp4_audio_codecs); | 304 CodecSet mp4_codecs(mp4_audio_codecs); |
| 403 mp4_codecs.insert(mp4_video_codecs.begin(), mp4_video_codecs.end()); | 305 mp4_codecs.insert(mp4_video_codecs.begin(), mp4_video_codecs.end()); |
| 404 #endif // defined(USE_PROPRIETARY_CODECS) | 306 #endif // defined(USE_PROPRIETARY_CODECS) |
| 405 | 307 |
| 406 AddContainerWithCodecs("audio/wav", wav_codecs, false); | 308 AddContainerWithCodecs("audio/wav", wav_codecs, false); |
| 407 AddContainerWithCodecs("audio/x-wav", wav_codecs, false); | 309 AddContainerWithCodecs("audio/x-wav", wav_codecs, false); |
| 408 AddContainerWithCodecs("audio/webm", webm_audio_codecs, false); | 310 AddContainerWithCodecs("audio/webm", webm_audio_codecs, false); |
| 409 DCHECK(!webm_video_codecs.empty()); | 311 DCHECK(!webm_video_codecs.empty()); |
| 410 AddContainerWithCodecs("video/webm", webm_codecs, false); | 312 AddContainerWithCodecs("video/webm", webm_codecs, false); |
| 411 AddContainerWithCodecs("audio/ogg", ogg_audio_codecs, false); | 313 AddContainerWithCodecs("audio/ogg", ogg_audio_codecs, false); |
| (...skipping 232 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 644 | 546 |
| 645 // MediaPlayer can always play VP8. Note: This is incorrect for MSE, but | 547 // MediaPlayer can always play VP8. Note: This is incorrect for MSE, but |
| 646 // MSE does not use this code. http://crbug.com/587303. | 548 // MSE does not use this code. http://crbug.com/587303. |
| 647 return true; | 549 return true; |
| 648 | 550 |
| 649 case VP9: { | 551 case VP9: { |
| 650 // If clear, the unified pipeline can always decode VP9 in software. | 552 // If clear, the unified pipeline can always decode VP9 in software. |
| 651 if (!is_encrypted && platform_info.is_unified_media_pipeline_enabled) | 553 if (!is_encrypted && platform_info.is_unified_media_pipeline_enabled) |
| 652 return true; | 554 return true; |
| 653 | 555 |
| 654 if (!platform_info.has_platform_vp9_decoder) | 556 // Otherwise, platform support is required. |
| 655 return false; | 557 return platform_info.has_platform_vp9_decoder; |
| 656 | |
| 657 // Encrypted content is demuxed so the container is irrelevant. | |
| 658 if (is_encrypted) | |
| 659 return true; | |
| 660 | |
| 661 // MediaPlayer only supports VP9 in WebM. | |
| 662 return mime_type_lower_case == "video/webm"; | |
| 663 } | 558 } |
| 664 } | 559 } |
| 665 | 560 |
| 666 return false; | 561 return false; |
| 667 } | 562 } |
| 668 | 563 |
| 669 bool MimeUtil::StringToCodec(const std::string& mime_type_lower_case, | 564 bool MimeUtil::StringToCodec(const std::string& codec_id, |
| 670 const std::string& codec_id, | |
| 671 Codec* codec, | 565 Codec* codec, |
| 672 bool* is_ambiguous, | 566 bool* is_ambiguous, |
| 673 bool is_encrypted) const { | 567 bool is_encrypted) const { |
| 674 StringToCodecMappings::const_iterator itr = | 568 StringToCodecMappings::const_iterator itr = |
| 675 string_to_codec_map_.find(codec_id); | 569 string_to_codec_map_.find(codec_id); |
| 676 if (itr != string_to_codec_map_.end()) { | 570 if (itr != string_to_codec_map_.end()) { |
| 677 *codec = itr->second.codec; | 571 *codec = itr->second.codec; |
| 678 *is_ambiguous = itr->second.is_ambiguous; | 572 *is_ambiguous = itr->second.is_ambiguous; |
| 679 return true; | 573 return true; |
| 680 } | 574 } |
| (...skipping 30 matching lines...) Expand all Loading... |
| 711 case H264PROFILE_MAIN: | 605 case H264PROFILE_MAIN: |
| 712 case H264PROFILE_HIGH: | 606 case H264PROFILE_HIGH: |
| 713 *is_ambiguous = !IsValidH264Level(level_idc); | 607 *is_ambiguous = !IsValidH264Level(level_idc); |
| 714 break; | 608 break; |
| 715 default: | 609 default: |
| 716 *is_ambiguous = true; | 610 *is_ambiguous = true; |
| 717 } | 611 } |
| 718 return true; | 612 return true; |
| 719 } | 613 } |
| 720 | 614 |
| 721 if (ParseVp9CodecID(mime_type_lower_case, codec_id, &profile)) { | |
| 722 *codec = MimeUtil::VP9; | |
| 723 switch (profile) { | |
| 724 case VP9PROFILE_PROFILE0: | |
| 725 // Profile 0 should always be supported if VP9 is supported. | |
| 726 *is_ambiguous = false; | |
| 727 break; | |
| 728 default: | |
| 729 // We don't know if the underlying platform supports these profiles. | |
| 730 // Need to add platform level querying to get supported profiles | |
| 731 // (crbug/604566). | |
| 732 *is_ambiguous = true; | |
| 733 } | |
| 734 return true; | |
| 735 } | |
| 736 | |
| 737 DVLOG(4) << __FUNCTION__ << ": Unrecognized codec id " << codec_id; | 615 DVLOG(4) << __FUNCTION__ << ": Unrecognized codec id " << codec_id; |
| 738 return false; | 616 return false; |
| 739 } | 617 } |
| 740 | 618 |
| 741 bool MimeUtil::IsCodecSupported(Codec codec, | 619 bool MimeUtil::IsCodecSupported(Codec codec, |
| 742 const std::string& mime_type_lower_case, | 620 const std::string& mime_type_lower_case, |
| 743 bool is_encrypted) const { | 621 bool is_encrypted) const { |
| 744 DCHECK_NE(codec, INVALID_CODEC); | 622 DCHECK_NE(codec, INVALID_CODEC); |
| 745 | 623 |
| 746 #if defined(OS_ANDROID) | 624 #if defined(OS_ANDROID) |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 798 const std::string& mime_type_lower_case, | 676 const std::string& mime_type_lower_case, |
| 799 bool is_encrypted) const { | 677 bool is_encrypted) const { |
| 800 Codec default_codec = Codec::INVALID_CODEC; | 678 Codec default_codec = Codec::INVALID_CODEC; |
| 801 if (!GetDefaultCodecLowerCase(mime_type_lower_case, &default_codec)) | 679 if (!GetDefaultCodecLowerCase(mime_type_lower_case, &default_codec)) |
| 802 return false; | 680 return false; |
| 803 return IsCodecSupported(default_codec, mime_type_lower_case, is_encrypted); | 681 return IsCodecSupported(default_codec, mime_type_lower_case, is_encrypted); |
| 804 } | 682 } |
| 805 | 683 |
| 806 } // namespace internal | 684 } // namespace internal |
| 807 } // namespace media | 685 } // namespace media |
| OLD | NEW |