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