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> | 7 #include <map> |
8 | 8 |
9 #include "base/command_line.h" | 9 #include "base/command_line.h" |
10 #include "base/strings/string_number_conversions.h" | 10 #include "base/strings/string_number_conversions.h" |
11 #include "base/strings/string_split.h" | 11 #include "base/strings/string_split.h" |
12 #include "base/strings/string_util.h" | 12 #include "base/strings/string_util.h" |
13 #include "build/build_config.h" | 13 #include "build/build_config.h" |
14 #include "media/base/media.h" | 14 #include "media/base/media.h" |
15 #include "media/base/media_client.h" | 15 #include "media/base/media_client.h" |
16 #include "media/base/media_switches.h" | 16 #include "media/base/media_switches.h" |
17 #include "media/base/video_codecs.h" | 17 #include "media/base/video_codecs.h" |
| 18 #include "media/base/video_color_space.h" |
18 #include "media/media_features.h" | 19 #include "media/media_features.h" |
19 | 20 |
20 #if defined(OS_ANDROID) | 21 #if defined(OS_ANDROID) |
21 #include "base/android/build_info.h" | 22 #include "base/android/build_info.h" |
22 #include "media/base/android/media_codec_util.h" | 23 #include "media/base/android/media_codec_util.h" |
23 #endif | 24 #endif |
24 | 25 |
25 namespace media { | 26 namespace media { |
26 namespace internal { | 27 namespace internal { |
27 | 28 |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
79 {"theora", MimeUtil::THEORA} | 80 {"theora", MimeUtil::THEORA} |
80 }; | 81 }; |
81 | 82 |
82 return kStringToCodecMap; | 83 return kStringToCodecMap; |
83 } | 84 } |
84 | 85 |
85 static bool ParseVp9CodecID(const std::string& mime_type_lower_case, | 86 static bool ParseVp9CodecID(const std::string& mime_type_lower_case, |
86 const std::string& codec_id, | 87 const std::string& codec_id, |
87 VideoCodecProfile* out_profile, | 88 VideoCodecProfile* out_profile, |
88 uint8_t* out_level, | 89 uint8_t* out_level, |
89 gfx::ColorSpace::TransferID* out_eotf) { | 90 VideoColorSpace* out_color_space) { |
90 if (mime_type_lower_case == "video/mp4") { | 91 if (mime_type_lower_case == "video/mp4") { |
91 if (base::CommandLine::ForCurrentProcess()->HasSwitch( | 92 if (base::CommandLine::ForCurrentProcess()->HasSwitch( |
92 switches::kEnableVp9InMp4)) { | 93 switches::kEnableVp9InMp4)) { |
93 // Only new style is allowed for mp4. | 94 // Only new style is allowed for mp4. |
94 return ParseNewStyleVp9CodecID(codec_id, out_profile, out_level, | 95 return ParseNewStyleVp9CodecID(codec_id, out_profile, out_level, |
95 out_eotf); | 96 out_color_space); |
96 } | 97 } |
97 } else if (mime_type_lower_case == "video/webm") { | 98 } else if (mime_type_lower_case == "video/webm") { |
98 if (HasNewVp9CodecStringSupport() && | 99 if (HasNewVp9CodecStringSupport() && |
99 ParseNewStyleVp9CodecID(codec_id, out_profile, out_level, out_eotf)) { | 100 ParseNewStyleVp9CodecID(codec_id, out_profile, out_level, |
| 101 out_color_space)) { |
100 return true; | 102 return true; |
101 } | 103 } |
102 | 104 |
103 return ParseLegacyVp9CodecID(codec_id, out_profile, out_level); | 105 return ParseLegacyVp9CodecID(codec_id, out_profile, out_level); |
104 } | 106 } |
105 return false; | 107 return false; |
106 } | 108 } |
107 | 109 |
108 static bool IsValidH264Level(uint8_t level_idc) { | 110 static bool IsValidH264Level(uint8_t level_idc) { |
109 // Valid levels taken from Table A-1 in ISO/IEC 14496-10. | 111 // Valid levels taken from Table A-1 in ISO/IEC 14496-10. |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
164 DCHECK_EQ(base::ToLowerASCII(mime_type_lower_case), mime_type_lower_case); | 166 DCHECK_EQ(base::ToLowerASCII(mime_type_lower_case), mime_type_lower_case); |
165 | 167 |
166 SupportsType combined_result = IsSupported; | 168 SupportsType combined_result = IsSupported; |
167 | 169 |
168 for (size_t i = 0; i < codecs.size(); ++i) { | 170 for (size_t i = 0; i < codecs.size(); ++i) { |
169 // Parse the string. | 171 // Parse the string. |
170 bool ambiguous_codec_string = false; | 172 bool ambiguous_codec_string = false; |
171 Codec codec = INVALID_CODEC; | 173 Codec codec = INVALID_CODEC; |
172 VideoCodecProfile video_profile = VIDEO_CODEC_PROFILE_UNKNOWN; | 174 VideoCodecProfile video_profile = VIDEO_CODEC_PROFILE_UNKNOWN; |
173 uint8_t video_level = 0; | 175 uint8_t video_level = 0; |
174 gfx::ColorSpace::TransferID eotf = gfx::ColorSpace::TransferID::INVALID; | 176 VideoColorSpace color_space; |
175 if (!ParseCodecString(mime_type_lower_case, codecs[i], &codec, | 177 if (!ParseCodecString(mime_type_lower_case, codecs[i], &codec, |
176 &ambiguous_codec_string, &video_profile, &video_level, | 178 &ambiguous_codec_string, &video_profile, &video_level, |
177 &eotf)) { | 179 &color_space)) { |
178 return IsNotSupported; | 180 return IsNotSupported; |
179 } | 181 } |
180 | 182 |
181 // Bail if codec not in supported list for given container. | 183 // Bail if codec not in supported list for given container. |
182 if (supported_codecs.find(codec) == supported_codecs.end()) | 184 if (supported_codecs.find(codec) == supported_codecs.end()) |
183 return IsNotSupported; | 185 return IsNotSupported; |
184 | 186 |
185 // Make conservative guesses to resolve ambiguity before checking platform | 187 // Make conservative guesses to resolve ambiguity before checking platform |
186 // support. H264 and VP9 are the only allowed ambiguous video codec. DO NOT | 188 // support. H264 and VP9 are the only allowed ambiguous video codec. DO NOT |
187 // ADD SUPPORT FOR MORE AMIBIGUOUS STRINGS. | 189 // ADD SUPPORT FOR MORE AMIBIGUOUS STRINGS. |
188 if (codec == MimeUtil::H264 && ambiguous_codec_string) { | 190 if (codec == MimeUtil::H264 && ambiguous_codec_string) { |
189 if (video_profile == VIDEO_CODEC_PROFILE_UNKNOWN) | 191 if (video_profile == VIDEO_CODEC_PROFILE_UNKNOWN) |
190 video_profile = H264PROFILE_BASELINE; | 192 video_profile = H264PROFILE_BASELINE; |
191 if (!IsValidH264Level(video_level)) | 193 if (!IsValidH264Level(video_level)) |
192 video_level = 10; | 194 video_level = 10; |
193 } else if (codec == MimeUtil::VP9 && video_level == 0) { | 195 } else if (codec == MimeUtil::VP9 && video_level == 0) { |
194 // Original VP9 content type (codecs="vp9") does not specify the level. | 196 // Original VP9 content type (codecs="vp9") does not specify the level. |
195 // TODO(chcunningham): Mark this string as ambiguous when new multi-part | 197 // TODO(chcunningham): Mark this string as ambiguous when new multi-part |
196 // VP9 content type is published. | 198 // VP9 content type is published. |
197 video_level = 10; | 199 video_level = 10; |
198 } | 200 } |
199 | 201 |
200 // Check platform support. | 202 // Check platform support. |
201 SupportsType result = | 203 SupportsType result = |
202 IsCodecSupported(mime_type_lower_case, codec, video_profile, | 204 IsCodecSupported(mime_type_lower_case, codec, video_profile, |
203 video_level, eotf, is_encrypted); | 205 video_level, color_space, is_encrypted); |
204 if (result == IsNotSupported) | 206 if (result == IsNotSupported) |
205 return IsNotSupported; | 207 return IsNotSupported; |
206 | 208 |
207 // If any codec is "MayBeSupported", return Maybe for the combined result. | 209 // If any codec is "MayBeSupported", return Maybe for the combined result. |
208 // Downgrade to MayBeSupported if we had to guess the meaning of one of the | 210 // Downgrade to MayBeSupported if we had to guess the meaning of one of the |
209 // codec strings. | 211 // codec strings. |
210 if (result == MayBeSupported || | 212 if (result == MayBeSupported || |
211 (result == IsSupported && ambiguous_codec_string)) | 213 (result == IsSupported && ambiguous_codec_string)) |
212 combined_result = MayBeSupported; | 214 combined_result = MayBeSupported; |
213 } | 215 } |
(...skipping 344 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
558 | 560 |
559 return false; | 561 return false; |
560 } | 562 } |
561 | 563 |
562 bool MimeUtil::ParseCodecString(const std::string& mime_type_lower_case, | 564 bool MimeUtil::ParseCodecString(const std::string& mime_type_lower_case, |
563 const std::string& codec_id, | 565 const std::string& codec_id, |
564 Codec* codec, | 566 Codec* codec, |
565 bool* ambiguous_codec_string, | 567 bool* ambiguous_codec_string, |
566 VideoCodecProfile* out_profile, | 568 VideoCodecProfile* out_profile, |
567 uint8_t* out_level, | 569 uint8_t* out_level, |
568 gfx::ColorSpace::TransferID* out_eotf) const { | 570 VideoColorSpace* out_color_space) const { |
569 DCHECK_EQ(base::ToLowerASCII(mime_type_lower_case), mime_type_lower_case); | 571 DCHECK_EQ(base::ToLowerASCII(mime_type_lower_case), mime_type_lower_case); |
570 DCHECK(codec); | 572 DCHECK(codec); |
571 DCHECK(out_profile); | 573 DCHECK(out_profile); |
572 DCHECK(out_level); | 574 DCHECK(out_level); |
573 | 575 |
574 *codec = INVALID_CODEC; | 576 *codec = INVALID_CODEC; |
575 *ambiguous_codec_string = false; | 577 *ambiguous_codec_string = false; |
576 *out_profile = VIDEO_CODEC_PROFILE_UNKNOWN; | 578 *out_profile = VIDEO_CODEC_PROFILE_UNKNOWN; |
577 *out_level = 0; | 579 *out_level = 0; |
578 | 580 |
579 // Most codec strings do not yet specify EOTF. We choose 709 as default color | 581 // Most codec strings do not yet specify color. We choose 709 as default color |
580 // space elsewhere, so defaulting to 709 EOTF as well. See here for context: | 582 // space elsewhere, so defaulting to 709 here as well. See here for context: |
581 // https://crrev.com/1221903003/ | 583 // https://crrev.com/1221903003/ |
582 *out_eotf = gfx::ColorSpace::TransferID::BT709; | 584 *out_color_space = VideoColorSpace::BT709(); |
583 | 585 |
584 std::map<std::string, Codec>::const_iterator itr = | 586 std::map<std::string, Codec>::const_iterator itr = |
585 GetStringToCodecMap().find(codec_id); | 587 GetStringToCodecMap().find(codec_id); |
586 if (itr != GetStringToCodecMap().end()) { | 588 if (itr != GetStringToCodecMap().end()) { |
587 *codec = itr->second; | 589 *codec = itr->second; |
588 | 590 |
589 return true; | 591 return true; |
590 } | 592 } |
591 | 593 |
592 // Check codec string against short list of allowed ambiguous codecs. | 594 // Check codec string against short list of allowed ambiguous codecs. |
593 // Hard-coded to discourage expansion. DO NOT ADD TO THIS LIST. DO NOT | 595 // Hard-coded to discourage expansion. DO NOT ADD TO THIS LIST. DO NOT |
594 // INCREASE PLACES WHERE |ambiguous_codec_string| = true. | 596 // INCREASE PLACES WHERE |ambiguous_codec_string| = true. |
595 // NOTE: avc1/avc3.XXXXXX may be ambiguous handled after ParseAVCCodecId(). | 597 // NOTE: avc1/avc3.XXXXXX may be ambiguous handled after ParseAVCCodecId(). |
596 if (codec_id == "avc1" || codec_id == "avc3") { | 598 if (codec_id == "avc1" || codec_id == "avc3") { |
597 *codec = MimeUtil::H264; | 599 *codec = MimeUtil::H264; |
598 *ambiguous_codec_string = true; | 600 *ambiguous_codec_string = true; |
599 return true; | 601 return true; |
600 } else if (codec_id == "mp4a.40") { | 602 } else if (codec_id == "mp4a.40") { |
601 *codec = MimeUtil::MPEG4_AAC; | 603 *codec = MimeUtil::MPEG4_AAC; |
602 *ambiguous_codec_string = true; | 604 *ambiguous_codec_string = true; |
603 return true; | 605 return true; |
604 } | 606 } |
605 | 607 |
606 // If |codec_id| is not in |kStringToCodecMap|, then we assume that it is | 608 // If |codec_id| is not in |kStringToCodecMap|, then we assume that it is |
607 // either VP9, H.264 or HEVC/H.265 codec ID because currently those are the | 609 // either VP9, H.264 or HEVC/H.265 codec ID because currently those are the |
608 // only ones that are not added to the |kStringToCodecMap| and require | 610 // only ones that are not added to the |kStringToCodecMap| and require |
609 // parsing. | 611 // parsing. |
610 if (ParseVp9CodecID(mime_type_lower_case, codec_id, out_profile, out_level, | 612 if (ParseVp9CodecID(mime_type_lower_case, codec_id, out_profile, out_level, |
611 out_eotf)) { | 613 out_color_space)) { |
612 *codec = MimeUtil::VP9; | 614 *codec = MimeUtil::VP9; |
613 return true; | 615 return true; |
614 } | 616 } |
615 | 617 |
616 if (ParseAVCCodecId(codec_id, out_profile, out_level)) { | 618 if (ParseAVCCodecId(codec_id, out_profile, out_level)) { |
617 *codec = MimeUtil::H264; | 619 *codec = MimeUtil::H264; |
618 // Allowed string ambiguity since 2014. DO NOT ADD NEW CASES FOR AMBIGUITY. | 620 // Allowed string ambiguity since 2014. DO NOT ADD NEW CASES FOR AMBIGUITY. |
619 *ambiguous_codec_string = !IsValidH264Level(*out_level); | 621 *ambiguous_codec_string = !IsValidH264Level(*out_level); |
620 return true; | 622 return true; |
621 } | 623 } |
(...skipping 19 matching lines...) Expand all Loading... |
641 SupportsType MimeUtil::IsSimpleCodecSupported( | 643 SupportsType MimeUtil::IsSimpleCodecSupported( |
642 const std::string& mime_type_lower_case, | 644 const std::string& mime_type_lower_case, |
643 Codec codec, | 645 Codec codec, |
644 bool is_encrypted) const { | 646 bool is_encrypted) const { |
645 // Video codecs are not "simple" because they require a profile and level to | 647 // Video codecs are not "simple" because they require a profile and level to |
646 // be specified. There is no "default" video codec for a given container. | 648 // be specified. There is no "default" video codec for a given container. |
647 DCHECK_EQ(MimeUtilToVideoCodec(codec), kUnknownVideoCodec); | 649 DCHECK_EQ(MimeUtilToVideoCodec(codec), kUnknownVideoCodec); |
648 | 650 |
649 SupportsType result = IsCodecSupported( | 651 SupportsType result = IsCodecSupported( |
650 mime_type_lower_case, codec, VIDEO_CODEC_PROFILE_UNKNOWN, | 652 mime_type_lower_case, codec, VIDEO_CODEC_PROFILE_UNKNOWN, |
651 0 /* video_level */, gfx::ColorSpace::TransferID::INVALID, is_encrypted); | 653 0 /* video_level */, VideoColorSpace::BT709(), is_encrypted); |
652 | 654 |
653 // Platform support should never be ambiguous for simple codecs (no range of | 655 // Platform support should never be ambiguous for simple codecs (no range of |
654 // profiles to consider). | 656 // profiles to consider). |
655 DCHECK_NE(result, MayBeSupported); | 657 DCHECK_NE(result, MayBeSupported); |
656 return result; | 658 return result; |
657 } | 659 } |
658 | 660 |
659 SupportsType MimeUtil::IsCodecSupported(const std::string& mime_type_lower_case, | 661 SupportsType MimeUtil::IsCodecSupported(const std::string& mime_type_lower_case, |
660 Codec codec, | 662 Codec codec, |
661 VideoCodecProfile video_profile, | 663 VideoCodecProfile video_profile, |
662 uint8_t video_level, | 664 uint8_t video_level, |
663 gfx::ColorSpace::TransferID eotf, | 665 const VideoColorSpace& color_space, |
664 bool is_encrypted) const { | 666 bool is_encrypted) const { |
665 DCHECK_EQ(base::ToLowerASCII(mime_type_lower_case), mime_type_lower_case); | 667 DCHECK_EQ(base::ToLowerASCII(mime_type_lower_case), mime_type_lower_case); |
666 DCHECK_NE(codec, INVALID_CODEC); | 668 DCHECK_NE(codec, INVALID_CODEC); |
667 | 669 |
668 VideoCodec video_codec = MimeUtilToVideoCodec(codec); | 670 VideoCodec video_codec = MimeUtilToVideoCodec(codec); |
669 if (video_codec != kUnknownVideoCodec && | 671 if (video_codec != kUnknownVideoCodec && |
670 // Theora and VP8 do not have profiles/levels. | 672 // Theora and VP8 do not have profiles/levels. |
671 video_codec != kCodecTheora && video_codec != kCodecVP8) { | 673 video_codec != kCodecTheora && video_codec != kCodecVP8) { |
672 DCHECK_NE(video_profile, VIDEO_CODEC_PROFILE_UNKNOWN); | 674 DCHECK_NE(video_profile, VIDEO_CODEC_PROFILE_UNKNOWN); |
673 DCHECK_GT(video_level, 0); | 675 DCHECK_GT(video_level, 0); |
(...skipping 29 matching lines...) Expand all Loading... |
703 } | 705 } |
704 } else if (codec == MimeUtil::VP9 && video_profile != VP9PROFILE_PROFILE0) { | 706 } else if (codec == MimeUtil::VP9 && video_profile != VP9PROFILE_PROFILE0) { |
705 // We don't know if the underlying platform supports these profiles. Need | 707 // We don't know if the underlying platform supports these profiles. Need |
706 // to add platform level querying to get supported profiles. | 708 // to add platform level querying to get supported profiles. |
707 // https://crbug.com/604566 | 709 // https://crbug.com/604566 |
708 ambiguous_platform_support = true; | 710 ambiguous_platform_support = true; |
709 } | 711 } |
710 | 712 |
711 if (GetMediaClient() && video_codec != kUnknownVideoCodec && | 713 if (GetMediaClient() && video_codec != kUnknownVideoCodec && |
712 !GetMediaClient()->IsSupportedVideoConfig( | 714 !GetMediaClient()->IsSupportedVideoConfig( |
713 {video_codec, video_profile, video_level, eotf})) { | 715 {video_codec, video_profile, video_level, color_space})) { |
714 return IsNotSupported; | 716 return IsNotSupported; |
715 } | 717 } |
716 | 718 |
717 #if defined(OS_ANDROID) | 719 #if defined(OS_ANDROID) |
718 // TODO(chcunningham): Delete this. Android platform support should be | 720 // TODO(chcunningham): Delete this. Android platform support should be |
719 // handled by (android specific) MediaClient. | 721 // handled by (android specific) MediaClient. |
720 if (!IsCodecSupportedOnAndroid(codec, mime_type_lower_case, is_encrypted, | 722 if (!IsCodecSupportedOnAndroid(codec, mime_type_lower_case, is_encrypted, |
721 platform_info_)) { | 723 platform_info_)) { |
722 return IsNotSupported; | 724 return IsNotSupported; |
723 } | 725 } |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
776 SupportsType MimeUtil::IsDefaultCodecSupported(const std::string& mime_type, | 778 SupportsType MimeUtil::IsDefaultCodecSupported(const std::string& mime_type, |
777 bool is_encrypted) const { | 779 bool is_encrypted) const { |
778 Codec default_codec = Codec::INVALID_CODEC; | 780 Codec default_codec = Codec::INVALID_CODEC; |
779 if (!GetDefaultCodec(mime_type, &default_codec)) | 781 if (!GetDefaultCodec(mime_type, &default_codec)) |
780 return IsNotSupported; | 782 return IsNotSupported; |
781 return IsSimpleCodecSupported(mime_type, default_codec, is_encrypted); | 783 return IsSimpleCodecSupported(mime_type, default_codec, is_encrypted); |
782 } | 784 } |
783 | 785 |
784 } // namespace internal | 786 } // namespace internal |
785 } // namespace media | 787 } // namespace media |
OLD | NEW |