Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(79)

Side by Side Diff: media/base/mime_util_internal.cc

Issue 2495193004: Refactor VP9 codec string parsing (Closed)
Patch Set: Added a new test in chunk_demuxer_unittest Created 4 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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/command_line.h" 7 #include "base/command_line.h"
8 #include "base/strings/string_number_conversions.h" 8 #include "base/strings/string_number_conversions.h"
9 #include "base/strings/string_split.h" 9 #include "base/strings/string_split.h"
10 #include "base/strings/string_util.h" 10 #include "base/strings/string_util.h"
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after
133 result.push_back(IntToHex(level >> 4)); 133 result.push_back(IntToHex(level >> 4));
134 result.push_back(IntToHex(level & 0xf)); 134 result.push_back(IntToHex(level & 0xf));
135 return result; 135 return result;
136 } 136 }
137 137
138 // This is not a valid legacy avc1 codec id - return the original codec id. 138 // This is not a valid legacy avc1 codec id - return the original codec id.
139 return codec_id; 139 return codec_id;
140 } 140 }
141 #endif 141 #endif
142 142
143 static bool ParseVp9CodecID(const std::string& mime_type_lower_case,
144 const std::string& codec_id,
145 VideoCodecProfile* out_profile,
146 uint8_t* out_level) {
147 if (mime_type_lower_case == "video/mp4") {
148 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
149 switches::kEnableVp9InMp4)) {
150 return ParseNewStyleVp9CodecID(codec_id, out_profile, out_level);
151 }
152 } else if (mime_type_lower_case == "video/webm") {
153 // Only legacy codec strings are supported in WebM.
154 // TODO(kqyang): Should we support new codec string in WebM?
155 return ParseLegacyVp9CodecID(codec_id, out_profile, out_level);
156 }
157 return false;
158 }
159
143 static bool IsValidH264Level(uint8_t level_idc) { 160 static bool IsValidH264Level(uint8_t level_idc) {
144 // Valid levels taken from Table A-1 in ISO/IEC 14496-10. 161 // Valid levels taken from Table A-1 in ISO/IEC 14496-10.
145 // Level_idc represents the standard level represented as decimal number 162 // Level_idc represents the standard level represented as decimal number
146 // multiplied by ten, e.g. level_idc==32 corresponds to level==3.2 163 // multiplied by ten, e.g. level_idc==32 corresponds to level==3.2
147 return ((level_idc >= 10 && level_idc <= 13) || 164 return ((level_idc >= 10 && level_idc <= 13) ||
148 (level_idc >= 20 && level_idc <= 22) || 165 (level_idc >= 20 && level_idc <= 22) ||
149 (level_idc >= 30 && level_idc <= 32) || 166 (level_idc >= 30 && level_idc <= 32) ||
150 (level_idc >= 40 && level_idc <= 42) || 167 (level_idc >= 40 && level_idc <= 42) ||
151 (level_idc >= 50 && level_idc <= 51)); 168 (level_idc >= 50 && level_idc <= 51));
152 } 169 }
153 170
154 // Handle parsing of vp9 codec IDs.
155 static bool ParseVp9CodecID(const std::string& mime_type_lower_case,
156 const std::string& codec_id,
157 VideoCodecProfile* profile) {
158 if (mime_type_lower_case == "video/webm") {
159 if (codec_id == "vp9" || codec_id == "vp9.0") {
160 // Profile is not included in the codec string. Assuming profile 0 to be
161 // backward compatible.
162 *profile = VP9PROFILE_PROFILE0;
163 return true;
164 }
165 // TODO(kqyang): Should we support new codec string in WebM?
166 return false;
167 } else if (mime_type_lower_case == "audio/webm") {
168 return false;
169 }
170
171 if (!base::CommandLine::ForCurrentProcess()->HasSwitch(
172 switches::kEnableVp9InMp4)) {
173 return false;
174 }
175
176 std::vector<std::string> fields = base::SplitString(
177 codec_id, ".", base::KEEP_WHITESPACE, base::SPLIT_WANT_ALL);
178 if (fields.size() < 1)
179 return false;
180
181 if (fields[0] != "vp09")
182 return false;
183
184 if (fields.size() > 8)
185 return false;
186
187 std::vector<int> values;
188 for (size_t i = 1; i < fields.size(); ++i) {
189 // Missing value is not allowed.
190 if (fields[i] == "")
191 return false;
192 int value;
193 if (!base::StringToInt(fields[i], &value))
194 return false;
195 if (value < 0)
196 return false;
197 values.push_back(value);
198 }
199
200 // The spec specifies 8 fields (7 values excluding the first codec field).
201 // We do not allow missing fields.
202 if (values.size() < 7)
203 return false;
204
205 const int profile_idc = values[0];
206 switch (profile_idc) {
207 case 0:
208 *profile = VP9PROFILE_PROFILE0;
209 break;
210 case 1:
211 *profile = VP9PROFILE_PROFILE1;
212 break;
213 case 2:
214 *profile = VP9PROFILE_PROFILE2;
215 break;
216 case 3:
217 *profile = VP9PROFILE_PROFILE3;
218 break;
219 default:
220 return false;
221 }
222
223 const int bit_depth = values[2];
224 if (bit_depth != 8 && bit_depth != 10 && bit_depth != 12)
225 return false;
226
227 const int color_space = values[3];
228 if (color_space > 7)
229 return false;
230
231 const int chroma_subsampling = values[4];
232 if (chroma_subsampling > 3)
233 return false;
234
235 const int transfer_function = values[5];
236 if (transfer_function > 1)
237 return false;
238
239 const int video_full_range_flag = values[6];
240 if (video_full_range_flag > 1)
241 return false;
242
243 return true;
244 }
245
246 MimeUtil::MimeUtil() : allow_proprietary_codecs_(false) { 171 MimeUtil::MimeUtil() : allow_proprietary_codecs_(false) {
247 #if defined(OS_ANDROID) 172 #if defined(OS_ANDROID)
248 platform_info_.is_unified_media_pipeline_enabled = 173 platform_info_.is_unified_media_pipeline_enabled =
249 IsUnifiedMediaPipelineEnabled(); 174 IsUnifiedMediaPipelineEnabled();
250 // When the unified media pipeline is enabled, we need support for both GPU 175 // When the unified media pipeline is enabled, we need support for both GPU
251 // video decoders and MediaCodec; indicated by HasPlatformDecoderSupport(). 176 // video decoders and MediaCodec; indicated by HasPlatformDecoderSupport().
252 // When the Android pipeline is used, we only need access to MediaCodec. 177 // When the Android pipeline is used, we only need access to MediaCodec.
253 platform_info_.has_platform_decoders = ArePlatformDecodersAvailable(); 178 platform_info_.has_platform_decoders = ArePlatformDecodersAvailable();
254 platform_info_.has_platform_vp8_decoder = 179 platform_info_.has_platform_vp8_decoder =
255 MediaCodecUtil::IsVp8DecoderAvailable(); 180 MediaCodecUtil::IsVp8DecoderAvailable();
(...skipping 419 matching lines...) Expand 10 before | Expand all | Expand 10 after
675 *out_level = 0; 600 *out_level = 0;
676 601
677 StringToCodecMappings::const_iterator itr = 602 StringToCodecMappings::const_iterator itr =
678 string_to_codec_map_.find(codec_id); 603 string_to_codec_map_.find(codec_id);
679 if (itr != string_to_codec_map_.end()) { 604 if (itr != string_to_codec_map_.end()) {
680 *codec = itr->second.codec; 605 *codec = itr->second.codec;
681 *is_ambiguous = itr->second.is_ambiguous; 606 *is_ambiguous = itr->second.is_ambiguous;
682 return true; 607 return true;
683 } 608 }
684 609
685 // If |codec_id| is not in |string_to_codec_map_|, then we assume that it is 610 // If |codec_id| is not in |string_to_codec_map_|, then we assume that it is
686 // either H.264 or HEVC/H.265 codec ID because currently those are the only 611 // either VP9, H.264 or HEVC/H.265 codec ID because currently those are the
687 // ones that are not added to the |string_to_codec_map_| and require parsing. 612 // only ones that are not added to the |string_to_codec_map_| and require
613 // parsing.
614 if (ParseVp9CodecID(mime_type_lower_case, codec_id, out_profile, out_level)) {
615 *codec = MimeUtil::VP9;
616 switch (*out_profile) {
617 case VP9PROFILE_PROFILE0:
618 // Profile 0 should always be supported if VP9 is supported.
619 *is_ambiguous = false;
620 break;
621 default:
622 // We don't know if the underlying platform supports these profiles.
623 // Need to add platform level querying to get supported profiles
624 // (crbug/604566).
625 *is_ambiguous = true;
626 break;
627 }
628 return true;
629 }
630
688 if (ParseAVCCodecId(codec_id, out_profile, out_level)) { 631 if (ParseAVCCodecId(codec_id, out_profile, out_level)) {
689 *codec = MimeUtil::H264; 632 *codec = MimeUtil::H264;
690 switch (*out_profile) { 633 switch (*out_profile) {
691 // HIGH10PROFILE is supported through fallback to the ffmpeg decoder 634 // HIGH10PROFILE is supported through fallback to the ffmpeg decoder
692 // which is not available on Android, or if FFMPEG is not used. 635 // which is not available on Android, or if FFMPEG is not used.
693 #if !defined(MEDIA_DISABLE_FFMPEG) && !defined(OS_ANDROID) 636 #if !defined(MEDIA_DISABLE_FFMPEG) && !defined(OS_ANDROID)
694 case H264PROFILE_HIGH10PROFILE: 637 case H264PROFILE_HIGH10PROFILE:
695 if (is_encrypted) { 638 if (is_encrypted) {
696 // FFmpeg is not generally used for encrypted videos, so we do not 639 // FFmpeg is not generally used for encrypted videos, so we do not
697 // know whether 10-bit is supported. 640 // know whether 10-bit is supported.
698 *is_ambiguous = true; 641 *is_ambiguous = true;
699 break; 642 break;
700 } 643 }
701 // Fall through. 644 // Fall through.
702 #endif 645 #endif
703 646
704 case H264PROFILE_BASELINE: 647 case H264PROFILE_BASELINE:
705 case H264PROFILE_MAIN: 648 case H264PROFILE_MAIN:
706 case H264PROFILE_HIGH: 649 case H264PROFILE_HIGH:
707 *is_ambiguous = !IsValidH264Level(*out_level); 650 *is_ambiguous = !IsValidH264Level(*out_level);
708 break; 651 break;
709 default: 652 default:
710 *is_ambiguous = true; 653 *is_ambiguous = true;
711 } 654 }
712 return true; 655 return true;
713 } 656 }
714 657
715 if (ParseVp9CodecID(mime_type_lower_case, codec_id, out_profile)) {
716 *codec = MimeUtil::VP9;
717 *out_level = 1;
718 switch (*out_profile) {
719 case VP9PROFILE_PROFILE0:
720 // Profile 0 should always be supported if VP9 is supported.
721 *is_ambiguous = false;
722 break;
723 default:
724 // We don't know if the underlying platform supports these profiles.
725 // Need to add platform level querying to get supported profiles
726 // (crbug/604566).
727 *is_ambiguous = true;
728 }
729 return true;
730 }
731
732 #if BUILDFLAG(ENABLE_HEVC_DEMUXING) 658 #if BUILDFLAG(ENABLE_HEVC_DEMUXING)
733 if (ParseHEVCCodecId(codec_id, out_profile, out_level)) { 659 if (ParseHEVCCodecId(codec_id, out_profile, out_level)) {
734 *codec = MimeUtil::HEVC; 660 *codec = MimeUtil::HEVC;
735 *is_ambiguous = false; 661 *is_ambiguous = false;
736 return true; 662 return true;
737 } 663 }
738 #endif 664 #endif
739 665
740 DVLOG(4) << __func__ << ": Unrecognized codec id " << codec_id; 666 DVLOG(4) << __func__ << ": Unrecognized codec id " << codec_id;
741 return false; 667 return false;
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
807 const std::string& mime_type_lower_case, 733 const std::string& mime_type_lower_case,
808 bool is_encrypted) const { 734 bool is_encrypted) const {
809 Codec default_codec = Codec::INVALID_CODEC; 735 Codec default_codec = Codec::INVALID_CODEC;
810 if (!GetDefaultCodecLowerCase(mime_type_lower_case, &default_codec)) 736 if (!GetDefaultCodecLowerCase(mime_type_lower_case, &default_codec))
811 return false; 737 return false;
812 return IsCodecSupported(default_codec, mime_type_lower_case, is_encrypted); 738 return IsCodecSupported(default_codec, mime_type_lower_case, is_encrypted);
813 } 739 }
814 740
815 } // namespace internal 741 } // namespace internal
816 } // namespace media 742 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698