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) { |
| 90 LOG(ERROR) << __func__; |
89 if (mime_type_lower_case == "video/mp4") { | 91 if (mime_type_lower_case == "video/mp4") { |
90 if (base::CommandLine::ForCurrentProcess()->HasSwitch( | 92 if (base::CommandLine::ForCurrentProcess()->HasSwitch( |
91 switches::kEnableVp9InMp4)) { | 93 switches::kEnableVp9InMp4)) { |
92 return ParseNewStyleVp9CodecID(codec_id, out_profile, out_level); | 94 // Only new style is allowed for mp4. |
| 95 return ParseNewStyleVp9CodecID(codec_id, out_profile, out_level, |
| 96 out_eotf); |
93 } | 97 } |
94 } else if (mime_type_lower_case == "video/webm") { | 98 } else if (mime_type_lower_case == "video/webm") { |
95 // Only legacy codec strings are supported in WebM. | 99 // Both styles allowed for WebM. |
96 // TODO(kqyang): Should we support new codec string in WebM? | 100 if (ParseNewStyleVp9CodecID(codec_id, out_profile, out_level, out_eotf)) |
| 101 return true; |
| 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 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
156 DCHECK_EQ(base::ToLowerASCII(mime_type_lower_case), mime_type_lower_case); | 162 DCHECK_EQ(base::ToLowerASCII(mime_type_lower_case), mime_type_lower_case); |
157 | 163 |
158 SupportsType combined_result = IsSupported; | 164 SupportsType combined_result = IsSupported; |
159 | 165 |
160 for (size_t i = 0; i < codecs.size(); ++i) { | 166 for (size_t i = 0; i < codecs.size(); ++i) { |
161 // Parse the string. | 167 // Parse the string. |
162 bool ambiguous_codec_string = false; | 168 bool ambiguous_codec_string = false; |
163 Codec codec = INVALID_CODEC; | 169 Codec codec = INVALID_CODEC; |
164 VideoCodecProfile video_profile = VIDEO_CODEC_PROFILE_UNKNOWN; | 170 VideoCodecProfile video_profile = VIDEO_CODEC_PROFILE_UNKNOWN; |
165 uint8_t video_level = 0; | 171 uint8_t video_level = 0; |
| 172 gfx::ColorSpace::TransferID eotf = gfx::ColorSpace::TransferID::INVALID; |
166 if (!ParseCodecString(mime_type_lower_case, codecs[i], &codec, | 173 if (!ParseCodecString(mime_type_lower_case, codecs[i], &codec, |
167 &ambiguous_codec_string, &video_profile, | 174 &ambiguous_codec_string, &video_profile, &video_level, |
168 &video_level)) { | 175 &eotf)) { |
169 return IsNotSupported; | 176 return IsNotSupported; |
170 } | 177 } |
171 | 178 |
172 // Bail if codec not in supported list for given container. | 179 // Bail if codec not in supported list for given container. |
173 if (supported_codecs.find(codec) == supported_codecs.end()) | 180 if (supported_codecs.find(codec) == supported_codecs.end()) |
174 return IsNotSupported; | 181 return IsNotSupported; |
175 | 182 |
176 // Make conservative guesses to resolve ambiguity before checking platform | 183 // Make conservative guesses to resolve ambiguity before checking platform |
177 // support. H264 and VP9 are the only allowed ambiguous video codec. DO NOT | 184 // support. H264 and VP9 are the only allowed ambiguous video codec. DO NOT |
178 // ADD SUPPORT FOR MORE AMIBIGUOUS STRINGS. | 185 // ADD SUPPORT FOR MORE AMIBIGUOUS STRINGS. |
179 if (codec == MimeUtil::H264 && ambiguous_codec_string) { | 186 if (codec == MimeUtil::H264 && ambiguous_codec_string) { |
180 if (video_profile == VIDEO_CODEC_PROFILE_UNKNOWN) | 187 if (video_profile == VIDEO_CODEC_PROFILE_UNKNOWN) |
181 video_profile = H264PROFILE_BASELINE; | 188 video_profile = H264PROFILE_BASELINE; |
182 if (!IsValidH264Level(video_level)) | 189 if (!IsValidH264Level(video_level)) |
183 video_level = 10; | 190 video_level = 10; |
184 } else if (codec == MimeUtil::VP9 && video_level == 0) { | 191 } else if (codec == MimeUtil::VP9 && video_level == 0) { |
185 // Original VP9 content type (codecs="vp9") does not specify the level. | 192 // Original VP9 content type (codecs="vp9") does not specify the level. |
186 // TODO(chcunningham): Mark this string as ambiguous when new multi-part | 193 // TODO(chcunningham): Mark this string as ambiguous when new multi-part |
187 // VP9 content type is published. | 194 // VP9 content type is published. |
188 video_level = 10; | 195 video_level = 10; |
189 } | 196 } |
190 | 197 |
191 // Check platform support. | 198 // Check platform support. |
192 SupportsType result = IsCodecSupported( | 199 SupportsType result = |
193 mime_type_lower_case, codec, video_profile, video_level, is_encrypted); | 200 IsCodecSupported(mime_type_lower_case, codec, video_profile, |
| 201 video_level, eotf, is_encrypted); |
194 if (result == IsNotSupported) | 202 if (result == IsNotSupported) |
195 return IsNotSupported; | 203 return IsNotSupported; |
196 | 204 |
197 // If any codec is "MayBeSupported", return Maybe for the combined result. | 205 // If any codec is "MayBeSupported", return Maybe for the combined result. |
198 // Downgrade to MayBeSupported if we had to guess the meaning of one of the | 206 // Downgrade to MayBeSupported if we had to guess the meaning of one of the |
199 // codec strings. | 207 // codec strings. |
200 if (result == MayBeSupported || | 208 if (result == MayBeSupported || |
201 (result == IsSupported && ambiguous_codec_string)) | 209 (result == IsSupported && ambiguous_codec_string)) |
202 combined_result = MayBeSupported; | 210 combined_result = MayBeSupported; |
203 } | 211 } |
(...skipping 335 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
539 } | 547 } |
540 | 548 |
541 return false; | 549 return false; |
542 } | 550 } |
543 | 551 |
544 bool MimeUtil::ParseCodecString(const std::string& mime_type_lower_case, | 552 bool MimeUtil::ParseCodecString(const std::string& mime_type_lower_case, |
545 const std::string& codec_id, | 553 const std::string& codec_id, |
546 Codec* codec, | 554 Codec* codec, |
547 bool* ambiguous_codec_string, | 555 bool* ambiguous_codec_string, |
548 VideoCodecProfile* out_profile, | 556 VideoCodecProfile* out_profile, |
549 uint8_t* out_level) const { | 557 uint8_t* out_level, |
| 558 gfx::ColorSpace::TransferID* out_eotf) const { |
550 DCHECK_EQ(base::ToLowerASCII(mime_type_lower_case), mime_type_lower_case); | 559 DCHECK_EQ(base::ToLowerASCII(mime_type_lower_case), mime_type_lower_case); |
551 DCHECK(codec); | 560 DCHECK(codec); |
552 DCHECK(out_profile); | 561 DCHECK(out_profile); |
553 DCHECK(out_level); | 562 DCHECK(out_level); |
554 | 563 |
555 *codec = INVALID_CODEC; | 564 *codec = INVALID_CODEC; |
556 *ambiguous_codec_string = false; | 565 *ambiguous_codec_string = false; |
557 *out_profile = VIDEO_CODEC_PROFILE_UNKNOWN; | 566 *out_profile = VIDEO_CODEC_PROFILE_UNKNOWN; |
558 *out_level = 0; | 567 *out_level = 0; |
559 | 568 |
| 569 // Most codec strings do not yet specify EOTF. We choose 709 as default color |
| 570 // space elsewhere, so defaulting to 709 EOTF as well. See here for context: |
| 571 // https://crrev.com/1221903003/ |
| 572 *out_eotf = gfx::ColorSpace::TransferID::BT709; |
| 573 |
560 std::map<std::string, Codec>::const_iterator itr = | 574 std::map<std::string, Codec>::const_iterator itr = |
561 GetStringToCodecMap().find(codec_id); | 575 GetStringToCodecMap().find(codec_id); |
562 if (itr != GetStringToCodecMap().end()) { | 576 if (itr != GetStringToCodecMap().end()) { |
563 *codec = itr->second; | 577 *codec = itr->second; |
564 | 578 |
565 return true; | 579 return true; |
566 } | 580 } |
567 | 581 |
568 // Check codec string against short list of allowed ambiguous codecs. | 582 // Check codec string against short list of allowed ambiguous codecs. |
569 // Hard-coded to discourage expansion. DO NOT ADD TO THIS LIST. DO NOT | 583 // Hard-coded to discourage expansion. DO NOT ADD TO THIS LIST. DO NOT |
570 // INCREASE PLACES WHERE |ambiguous_codec_string| = true. | 584 // INCREASE PLACES WHERE |ambiguous_codec_string| = true. |
571 // NOTE: avc1/avc3.XXXXXX may be ambiguous handled after ParseAVCCodecId(). | 585 // NOTE: avc1/avc3.XXXXXX may be ambiguous handled after ParseAVCCodecId(). |
572 if (codec_id == "avc1" || codec_id == "avc3") { | 586 if (codec_id == "avc1" || codec_id == "avc3") { |
573 *codec = MimeUtil::H264; | 587 *codec = MimeUtil::H264; |
574 *ambiguous_codec_string = true; | 588 *ambiguous_codec_string = true; |
575 return true; | 589 return true; |
576 } else if (codec_id == "mp4a.40") { | 590 } else if (codec_id == "mp4a.40") { |
577 *codec = MimeUtil::MPEG4_AAC; | 591 *codec = MimeUtil::MPEG4_AAC; |
578 *ambiguous_codec_string = true; | 592 *ambiguous_codec_string = true; |
579 return true; | 593 return true; |
580 } | 594 } |
581 | 595 |
582 // If |codec_id| is not in |kStringToCodecMap|, then we assume that it is | 596 // If |codec_id| is not in |kStringToCodecMap|, then we assume that it is |
583 // either VP9, H.264 or HEVC/H.265 codec ID because currently those are the | 597 // either VP9, H.264 or HEVC/H.265 codec ID because currently those are the |
584 // only ones that are not added to the |kStringToCodecMap| and require | 598 // only ones that are not added to the |kStringToCodecMap| and require |
585 // parsing. | 599 // parsing. |
586 if (ParseVp9CodecID(mime_type_lower_case, codec_id, out_profile, out_level)) { | 600 |
| 601 if (ParseVp9CodecID(mime_type_lower_case, codec_id, out_profile, out_level, |
| 602 out_eotf)) { |
587 *codec = MimeUtil::VP9; | 603 *codec = MimeUtil::VP9; |
588 return true; | 604 return true; |
589 } | 605 } |
590 | 606 |
591 if (ParseAVCCodecId(codec_id, out_profile, out_level)) { | 607 if (ParseAVCCodecId(codec_id, out_profile, out_level)) { |
592 *codec = MimeUtil::H264; | 608 *codec = MimeUtil::H264; |
593 // Allowed string ambiguity since 2014. DO NOT ADD NEW CASES FOR AMBIGUITY. | 609 // Allowed string ambiguity since 2014. DO NOT ADD NEW CASES FOR AMBIGUITY. |
594 *ambiguous_codec_string = !IsValidH264Level(*out_level); | 610 *ambiguous_codec_string = !IsValidH264Level(*out_level); |
595 return true; | 611 return true; |
596 } | 612 } |
(...skipping 10 matching lines...) Expand all Loading... |
607 } | 623 } |
608 | 624 |
609 SupportsType MimeUtil::IsSimpleCodecSupported( | 625 SupportsType MimeUtil::IsSimpleCodecSupported( |
610 const std::string& mime_type_lower_case, | 626 const std::string& mime_type_lower_case, |
611 Codec codec, | 627 Codec codec, |
612 bool is_encrypted) const { | 628 bool is_encrypted) const { |
613 // Video codecs are not "simple" because they require a profile and level to | 629 // 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. | 630 // be specified. There is no "default" video codec for a given container. |
615 DCHECK_EQ(MimeUtilToVideoCodec(codec), kUnknownVideoCodec); | 631 DCHECK_EQ(MimeUtilToVideoCodec(codec), kUnknownVideoCodec); |
616 | 632 |
617 SupportsType result = | 633 SupportsType result = IsCodecSupported( |
618 IsCodecSupported(mime_type_lower_case, codec, VIDEO_CODEC_PROFILE_UNKNOWN, | 634 mime_type_lower_case, codec, VIDEO_CODEC_PROFILE_UNKNOWN, |
619 0 /* video_level */, is_encrypted); | 635 0 /* video_level */, gfx::ColorSpace::TransferID::INVALID, is_encrypted); |
620 | 636 |
621 // Platform support should never be ambiguous for simple codecs (no range of | 637 // Platform support should never be ambiguous for simple codecs (no range of |
622 // profiles to consider). | 638 // profiles to consider). |
623 DCHECK_NE(result, MayBeSupported); | 639 DCHECK_NE(result, MayBeSupported); |
624 return result; | 640 return result; |
625 } | 641 } |
626 | 642 |
627 SupportsType MimeUtil::IsCodecSupported(const std::string& mime_type_lower_case, | 643 SupportsType MimeUtil::IsCodecSupported(const std::string& mime_type_lower_case, |
628 Codec codec, | 644 Codec codec, |
629 VideoCodecProfile video_profile, | 645 VideoCodecProfile video_profile, |
630 uint8_t video_level, | 646 uint8_t video_level, |
| 647 gfx::ColorSpace::TransferID eotf, |
631 bool is_encrypted) const { | 648 bool is_encrypted) const { |
632 DCHECK_EQ(base::ToLowerASCII(mime_type_lower_case), mime_type_lower_case); | 649 DCHECK_EQ(base::ToLowerASCII(mime_type_lower_case), mime_type_lower_case); |
633 DCHECK_NE(codec, INVALID_CODEC); | 650 DCHECK_NE(codec, INVALID_CODEC); |
634 | 651 |
635 VideoCodec video_codec = MimeUtilToVideoCodec(codec); | 652 VideoCodec video_codec = MimeUtilToVideoCodec(codec); |
636 if (video_codec != kUnknownVideoCodec && | 653 if (video_codec != kUnknownVideoCodec && |
637 // Theora and VP8 do not have profiles/levels. | 654 // Theora and VP8 do not have profiles/levels. |
638 video_codec != kCodecTheora && video_codec != kCodecVP8) { | 655 video_codec != kCodecTheora && video_codec != kCodecVP8) { |
639 DCHECK_NE(video_profile, VIDEO_CODEC_PROFILE_UNKNOWN); | 656 DCHECK_NE(video_profile, VIDEO_CODEC_PROFILE_UNKNOWN); |
640 DCHECK_GT(video_level, 0); | 657 DCHECK_GT(video_level, 0); |
(...skipping 29 matching lines...) Expand all Loading... |
670 } | 687 } |
671 } else if (codec == MimeUtil::VP9 && video_profile != VP9PROFILE_PROFILE0) { | 688 } else if (codec == MimeUtil::VP9 && video_profile != VP9PROFILE_PROFILE0) { |
672 // We don't know if the underlying platform supports these profiles. Need | 689 // We don't know if the underlying platform supports these profiles. Need |
673 // to add platform level querying to get supported profiles. | 690 // to add platform level querying to get supported profiles. |
674 // https://crbug.com/604566 | 691 // https://crbug.com/604566 |
675 ambiguous_platform_support = true; | 692 ambiguous_platform_support = true; |
676 } | 693 } |
677 | 694 |
678 if (GetMediaClient() && video_codec != kUnknownVideoCodec && | 695 if (GetMediaClient() && video_codec != kUnknownVideoCodec && |
679 !GetMediaClient()->IsSupportedVideoConfig(video_codec, video_profile, | 696 !GetMediaClient()->IsSupportedVideoConfig(video_codec, video_profile, |
680 video_level)) { | 697 video_level, eotf)) { |
681 return IsNotSupported; | 698 return IsNotSupported; |
682 } | 699 } |
683 | 700 |
684 #if defined(OS_ANDROID) | 701 #if defined(OS_ANDROID) |
685 // TODO(chcunningham): Delete this. Android platform support should be | 702 // TODO(chcunningham): Delete this. Android platform support should be |
686 // handled by (android specific) MediaClient. | 703 // handled by (android specific) MediaClient. |
687 if (!IsCodecSupportedOnAndroid(codec, mime_type_lower_case, is_encrypted, | 704 if (!IsCodecSupportedOnAndroid(codec, mime_type_lower_case, is_encrypted, |
688 platform_info_)) { | 705 platform_info_)) { |
689 return IsNotSupported; | 706 return IsNotSupported; |
690 } | 707 } |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
742 SupportsType MimeUtil::IsDefaultCodecSupported(const std::string& mime_type, | 759 SupportsType MimeUtil::IsDefaultCodecSupported(const std::string& mime_type, |
743 bool is_encrypted) const { | 760 bool is_encrypted) const { |
744 Codec default_codec = Codec::INVALID_CODEC; | 761 Codec default_codec = Codec::INVALID_CODEC; |
745 if (!GetDefaultCodec(mime_type, &default_codec)) | 762 if (!GetDefaultCodec(mime_type, &default_codec)) |
746 return IsNotSupported; | 763 return IsNotSupported; |
747 return IsSimpleCodecSupported(mime_type, default_codec, is_encrypted); | 764 return IsSimpleCodecSupported(mime_type, default_codec, is_encrypted); |
748 } | 765 } |
749 | 766 |
750 } // namespace internal | 767 } // namespace internal |
751 } // namespace media | 768 } // namespace media |
OLD | NEW |