Chromium Code Reviews| 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 13 matching lines...) Expand all Loading... | |
| 24 const char* const codec_id; | 24 const char* const codec_id; |
| 25 MimeUtil::Codec codec; | 25 MimeUtil::Codec codec; |
| 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 is handled by ParseAVCCodecId(). |
| 35 // hev1/hvc1.XXXXXX may be unambiguous; handled by ParseHEVCCodecID(). | 35 // hev1/hvc1.XXXXXX is handled by ParseHEVCCodecID(). |
| 36 // vp9, vp9.0, vp09.xx.xx.xx.xx.xx.xx.xx may be unambiguous; handled by | 36 // vp8, vp8.0, vp9, vp9.0, and vp09.xx.xx.xx.xx.xx.xx.xx are handled by |
|
kqyang
2016/04/21 00:59:48
vp8, vp8.0 are still handled in this map; only vp9
ddorwin
2016/04/21 02:09:50
Done. Thanks.
| |
| 37 // ParseVp9CodecID(). | 37 // ParseVp9CodecID(). |
| 38 {"mp3", MimeUtil::MP3}, | 38 {"mp3", MimeUtil::MP3}, |
| 39 // Following is the list of RFC 6381 compliant audio codec strings: | 39 // Following is the list of RFC 6381 compliant audio codec strings: |
| 40 // mp4a.66 - MPEG-2 AAC MAIN | 40 // mp4a.66 - MPEG-2 AAC MAIN |
| 41 // mp4a.67 - MPEG-2 AAC LC | 41 // mp4a.67 - MPEG-2 AAC LC |
| 42 // mp4a.68 - MPEG-2 AAC SSR | 42 // mp4a.68 - MPEG-2 AAC SSR |
| 43 // mp4a.69 - MPEG-2 extension to MPEG-1 (MP3) | 43 // mp4a.69 - MPEG-2 extension to MPEG-1 (MP3) |
| 44 // mp4a.6B - MPEG-1 audio (MP3) | 44 // mp4a.6B - MPEG-1 audio (MP3) |
| 45 // mp4a.40.2 - MPEG-4 AAC LC | 45 // mp4a.40.2 - MPEG-4 AAC LC |
| 46 // mp4a.40.02 - MPEG-4 AAC LC (leading 0 in aud-oti for compatibility) | 46 // mp4a.40.02 - MPEG-4 AAC LC (leading 0 in aud-oti for compatibility) |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 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}, |
| 89 // avc1/avc3.XXXXXX may be ambiguous; handled by ParseAVCCodecId(). | |
| 90 }; | 89 }; |
| 91 | 90 |
| 92 #if BUILDFLAG(ENABLE_MSE_MPEG2TS_STREAM_PARSER) | 91 #if BUILDFLAG(ENABLE_MSE_MPEG2TS_STREAM_PARSER) |
| 93 static const char kHexString[] = "0123456789ABCDEF"; | 92 static const char kHexString[] = "0123456789ABCDEF"; |
| 94 static char IntToHex(int i) { | 93 static char IntToHex(int i) { |
| 95 DCHECK_GE(i, 0) << i << " not a hex value"; | 94 DCHECK_GE(i, 0) << i << " not a hex value"; |
| 96 DCHECK_LE(i, 15) << i << " not a hex value"; | 95 DCHECK_LE(i, 15) << i << " not a hex value"; |
| 97 return kHexString[i]; | 96 return kHexString[i]; |
| 98 } | 97 } |
| 99 | 98 |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 151 | 150 |
| 152 #if BUILDFLAG(ENABLE_HEVC_DEMUXING) | 151 #if BUILDFLAG(ENABLE_HEVC_DEMUXING) |
| 153 // ISO/IEC FDIS 14496-15 standard section E.3 describes the syntax of codec ids | 152 // ISO/IEC FDIS 14496-15 standard section E.3 describes the syntax of codec ids |
| 154 // reserved for HEVC. According to that spec HEVC codec id must start with | 153 // reserved for HEVC. According to that spec HEVC codec id must start with |
| 155 // either "hev1." or "hvc1.". We don't yet support full parsing of HEVC codec | 154 // either "hev1." or "hvc1.". We don't yet support full parsing of HEVC codec |
| 156 // ids, but since no other codec id starts with those string we'll just treat | 155 // ids, but since no other codec id starts with those string we'll just treat |
| 157 // any string starting with "hev1." or "hvc1." as valid HEVC codec ids. | 156 // any string starting with "hev1." or "hvc1." as valid HEVC codec ids. |
| 158 // crbug.com/482761 | 157 // crbug.com/482761 |
| 159 static bool ParseHEVCCodecID(const std::string& codec_id, | 158 static bool ParseHEVCCodecID(const std::string& codec_id, |
| 160 MimeUtil::Codec* codec, | 159 MimeUtil::Codec* codec, |
| 161 bool* is_ambiguous) { | 160 bool* is_known_supported) { |
| 162 if (base::StartsWith(codec_id, "hev1.", base::CompareCase::SENSITIVE) || | 161 if (base::StartsWith(codec_id, "hev1.", base::CompareCase::SENSITIVE) || |
| 163 base::StartsWith(codec_id, "hvc1.", base::CompareCase::SENSITIVE)) { | 162 base::StartsWith(codec_id, "hvc1.", base::CompareCase::SENSITIVE)) { |
| 164 *codec = MimeUtil::HEVC_MAIN; | 163 *codec = MimeUtil::HEVC_MAIN; |
| 165 | 164 |
| 166 // TODO(servolk): Full HEVC codec id parsing is not implemented yet (see | 165 // TODO(servolk): Full HEVC codec id parsing is not implemented yet (see |
| 167 // crbug.com/482761). So treat HEVC codec ids as ambiguous for now. | 166 // crbug.com/482761). So treat HEVC as not known supported for now. |
| 168 *is_ambiguous = true; | 167 *is_known_supported = false; |
| 169 | |
| 170 // TODO(servolk): Most HEVC codec ids are treated as ambiguous (see above), | |
| 171 // but we need to recognize at least one valid unambiguous HEVC codec id, | |
| 172 // which is added into kMP4VideoCodecsExpression. We need it to be | |
| 173 // unambiguous to avoid DCHECK(!is_ambiguous) in InitializeMimeTypeMaps. We | |
| 174 // also use these in unit tests (see | |
| 175 // content/browser/media/media_canplaytype_browsertest.cc). | |
| 176 // Remove this workaround after crbug.com/482761 is fixed. | |
| 177 if (codec_id == "hev1.1.6.L93.B0" || codec_id == "hvc1.1.6.L93.B0") { | |
| 178 *is_ambiguous = false; | |
| 179 } | |
| 180 | |
| 181 return true; | 168 return true; |
| 182 } | 169 } |
| 183 | 170 |
| 184 return false; | 171 return false; |
| 185 } | 172 } |
| 186 #endif | 173 #endif |
| 187 | 174 |
| 188 // Handle parsing of vp9 codec IDs. | 175 // Handle parsing of vp9 codec IDs. |
| 189 static bool ParseVp9CodecID(const std::string& mime_type_lower_case, | 176 static bool ParseVp9CodecID(const std::string& mime_type_lower_case, |
| 190 const std::string& codec_id, | 177 const std::string& codec_id, |
| (...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 299 SupportsType MimeUtil::AreSupportedCodecs( | 286 SupportsType MimeUtil::AreSupportedCodecs( |
| 300 const CodecSet& supported_codecs, | 287 const CodecSet& supported_codecs, |
| 301 const std::vector<std::string>& codecs, | 288 const std::vector<std::string>& codecs, |
| 302 const std::string& mime_type_lower_case, | 289 const std::string& mime_type_lower_case, |
| 303 bool is_encrypted) const { | 290 bool is_encrypted) const { |
| 304 DCHECK(!supported_codecs.empty()); | 291 DCHECK(!supported_codecs.empty()); |
| 305 DCHECK(!codecs.empty()); | 292 DCHECK(!codecs.empty()); |
| 306 | 293 |
| 307 SupportsType result = IsSupported; | 294 SupportsType result = IsSupported; |
| 308 for (size_t i = 0; i < codecs.size(); ++i) { | 295 for (size_t i = 0; i < codecs.size(); ++i) { |
| 309 bool is_ambiguous = true; | 296 bool is_known_supported = false; |
| 310 Codec codec = INVALID_CODEC; | 297 Codec codec = INVALID_CODEC; |
| 311 if (!StringToCodec(mime_type_lower_case, codecs[i], &codec, &is_ambiguous, | 298 if (!StringToCodec(mime_type_lower_case, codecs[i], &codec, |
| 312 is_encrypted)) { | 299 &is_known_supported, is_encrypted)) { |
| 313 return IsNotSupported; | 300 return IsNotSupported; |
| 314 } | 301 } |
| 315 | 302 |
| 316 if (!IsCodecSupported(codec, mime_type_lower_case, is_encrypted) || | 303 if (!IsCodecSupported(codec, mime_type_lower_case, is_encrypted) || |
| 317 supported_codecs.find(codec) == supported_codecs.end()) { | 304 supported_codecs.find(codec) == supported_codecs.end()) { |
| 318 return IsNotSupported; | 305 return IsNotSupported; |
| 319 } | 306 } |
| 320 | 307 |
| 321 if (is_ambiguous) | 308 if (!is_known_supported) |
| 322 result = MayBeSupported; | 309 result = MayBeSupported; |
| 323 } | 310 } |
| 324 | 311 |
| 325 return result; | 312 return result; |
| 326 } | 313 } |
| 327 | 314 |
| 328 void MimeUtil::InitializeMimeTypeMaps() { | 315 void MimeUtil::InitializeMimeTypeMaps() { |
| 329 #if defined(USE_PROPRIETARY_CODECS) | 316 #if defined(USE_PROPRIETARY_CODECS) |
| 330 allow_proprietary_codecs_ = true; | 317 allow_proprietary_codecs_ = true; |
| 331 #endif | 318 #endif |
| (...skipping 330 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 662 return mime_type_lower_case == "video/webm"; | 649 return mime_type_lower_case == "video/webm"; |
| 663 } | 650 } |
| 664 } | 651 } |
| 665 | 652 |
| 666 return false; | 653 return false; |
| 667 } | 654 } |
| 668 | 655 |
| 669 bool MimeUtil::StringToCodec(const std::string& mime_type_lower_case, | 656 bool MimeUtil::StringToCodec(const std::string& mime_type_lower_case, |
| 670 const std::string& codec_id, | 657 const std::string& codec_id, |
| 671 Codec* codec, | 658 Codec* codec, |
| 672 bool* is_ambiguous, | 659 bool* is_known_supported, |
| 673 bool is_encrypted) const { | 660 bool is_encrypted) const { |
| 674 StringToCodecMappings::const_iterator itr = | 661 StringToCodecMappings::const_iterator itr = |
| 675 string_to_codec_map_.find(codec_id); | 662 string_to_codec_map_.find(codec_id); |
| 676 if (itr != string_to_codec_map_.end()) { | 663 if (itr != string_to_codec_map_.end()) { |
| 677 *codec = itr->second.codec; | 664 *codec = itr->second.codec; |
| 678 *is_ambiguous = itr->second.is_ambiguous; | 665 *is_known_supported = !itr->second.is_ambiguous; |
| 679 return true; | 666 return true; |
| 680 } | 667 } |
| 681 | 668 |
| 682 // If |codec_id| is not in |string_to_codec_map_|, then we assume that it is | 669 // If |codec_id| is not in |string_to_codec_map_|, then we assume that it is |
| 683 // either H.264 or HEVC/H.265 codec ID because currently those are the only | 670 // either H.264 or HEVC/H.265 codec ID because currently those are the only |
| 684 // ones that are not added to the |string_to_codec_map_| and require parsing. | 671 // ones that are not added to the |string_to_codec_map_| and require parsing. |
| 685 | 672 |
| 686 #if BUILDFLAG(ENABLE_HEVC_DEMUXING) | 673 #if BUILDFLAG(ENABLE_HEVC_DEMUXING) |
| 687 if (ParseHEVCCodecID(codec_id, codec, is_ambiguous)) { | 674 if (ParseHEVCCodecID(codec_id, codec, is_known_supported)) { |
| 688 return true; | 675 return true; |
| 689 } | 676 } |
| 690 #endif | 677 #endif |
| 691 | 678 |
| 692 VideoCodecProfile profile = VIDEO_CODEC_PROFILE_UNKNOWN; | 679 VideoCodecProfile profile = VIDEO_CODEC_PROFILE_UNKNOWN; |
| 693 uint8_t level_idc = 0; | 680 uint8_t level_idc = 0; |
| 694 if (ParseAVCCodecId(codec_id, &profile, &level_idc)) { | 681 if (ParseAVCCodecId(codec_id, &profile, &level_idc)) { |
| 695 *codec = MimeUtil::H264; | 682 *codec = MimeUtil::H264; |
| 696 switch (profile) { | 683 switch (profile) { |
| 697 // HIGH10PROFILE is supported through fallback to the ffmpeg decoder | 684 // HIGH10PROFILE is supported through fallback to the ffmpeg decoder |
| 698 // which is not available on Android, or if FFMPEG is not used. | 685 // which is not available on Android, or if FFMPEG is not used. |
| 699 #if !defined(MEDIA_DISABLE_FFMPEG) && !defined(OS_ANDROID) | 686 #if !defined(MEDIA_DISABLE_FFMPEG) && !defined(OS_ANDROID) |
| 700 case H264PROFILE_HIGH10PROFILE: | 687 case H264PROFILE_HIGH10PROFILE: |
| 701 if (is_encrypted) { | 688 if (is_encrypted) { |
| 702 // FFmpeg is not generally used for encrypted videos, so we do not | 689 // FFmpeg is not generally used for encrypted videos, so we do not |
| 703 // know whether 10-bit is supported. | 690 // know whether 10-bit is supported. |
| 704 *is_ambiguous = true; | 691 *is_known_supported = false; |
| 705 break; | 692 break; |
| 706 } | 693 } |
| 707 // Fall through. | 694 // Fall through. |
| 708 #endif | 695 #endif |
| 709 | 696 |
| 710 case H264PROFILE_BASELINE: | 697 case H264PROFILE_BASELINE: |
| 711 case H264PROFILE_MAIN: | 698 case H264PROFILE_MAIN: |
| 712 case H264PROFILE_HIGH: | 699 case H264PROFILE_HIGH: |
| 713 *is_ambiguous = !IsValidH264Level(level_idc); | 700 *is_known_supported = IsValidH264Level(level_idc); |
| 714 break; | 701 break; |
| 715 default: | 702 default: |
| 716 *is_ambiguous = true; | 703 *is_known_supported = false; |
| 717 } | 704 } |
| 718 return true; | 705 return true; |
| 719 } | 706 } |
| 720 | 707 |
| 721 if (ParseVp9CodecID(mime_type_lower_case, codec_id, &profile)) { | 708 if (ParseVp9CodecID(mime_type_lower_case, codec_id, &profile)) { |
| 722 *codec = MimeUtil::VP9; | 709 *codec = MimeUtil::VP9; |
| 723 switch (profile) { | 710 switch (profile) { |
| 724 case VP9PROFILE_PROFILE0: | 711 case VP9PROFILE_PROFILE0: |
| 725 // Profile 0 should always be supported if VP9 is supported. | 712 // Profile 0 should always be supported if VP9 is supported. |
| 726 *is_ambiguous = false; | 713 *is_known_supported = true; |
| 727 break; | 714 break; |
| 728 default: | 715 default: |
| 729 // We don't know if the underlying platform supports these profiles. | 716 // We don't know if the underlying platform supports these profiles. |
| 730 // Need to add platform level querying to get supported profiles | 717 // Need to add platform level querying to get supported profiles |
| 731 // (crbug/604566). | 718 // (crbug/604566). |
| 732 *is_ambiguous = true; | 719 *is_known_supported = false; |
| 733 } | 720 } |
| 734 return true; | 721 return true; |
| 735 } | 722 } |
| 736 | 723 |
| 737 DVLOG(4) << __FUNCTION__ << ": Unrecognized codec id " << codec_id; | 724 DVLOG(4) << __FUNCTION__ << ": Unrecognized codec id " << codec_id; |
| 738 return false; | 725 return false; |
| 739 } | 726 } |
| 740 | 727 |
| 741 bool MimeUtil::IsCodecSupported(Codec codec, | 728 bool MimeUtil::IsCodecSupported(Codec codec, |
| 742 const std::string& mime_type_lower_case, | 729 const std::string& mime_type_lower_case, |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 798 const std::string& mime_type_lower_case, | 785 const std::string& mime_type_lower_case, |
| 799 bool is_encrypted) const { | 786 bool is_encrypted) const { |
| 800 Codec default_codec = Codec::INVALID_CODEC; | 787 Codec default_codec = Codec::INVALID_CODEC; |
| 801 if (!GetDefaultCodecLowerCase(mime_type_lower_case, &default_codec)) | 788 if (!GetDefaultCodecLowerCase(mime_type_lower_case, &default_codec)) |
| 802 return false; | 789 return false; |
| 803 return IsCodecSupported(default_codec, mime_type_lower_case, is_encrypted); | 790 return IsCodecSupported(default_codec, mime_type_lower_case, is_encrypted); |
| 804 } | 791 } |
| 805 | 792 |
| 806 } // namespace internal | 793 } // namespace internal |
| 807 } // namespace media | 794 } // namespace media |
| OLD | NEW |