OLD | NEW |
---|---|
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 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/video_codecs.h" | 5 #include "media/base/video_codecs.h" |
6 | 6 |
7 #include "base/logging.h" | 7 #include "base/logging.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_util.h" | 10 #include "base/strings/string_util.h" |
10 | 11 |
11 namespace media { | 12 namespace media { |
12 | 13 |
13 // The names come from src/third_party/ffmpeg/libavcodec/codec_desc.c | 14 // The names come from src/third_party/ffmpeg/libavcodec/codec_desc.c |
14 std::string GetCodecName(VideoCodec codec) { | 15 std::string GetCodecName(VideoCodec codec) { |
15 switch (codec) { | 16 switch (codec) { |
16 case kUnknownVideoCodec: | 17 case kUnknownVideoCodec: |
17 return "unknown"; | 18 return "unknown"; |
18 case kCodecH264: | 19 case kCodecH264: |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
55 case H264PROFILE_HIGH444PREDICTIVEPROFILE: | 56 case H264PROFILE_HIGH444PREDICTIVEPROFILE: |
56 return "h264 high 4:4:4 predictive"; | 57 return "h264 high 4:4:4 predictive"; |
57 case H264PROFILE_SCALABLEBASELINE: | 58 case H264PROFILE_SCALABLEBASELINE: |
58 return "h264 scalable baseline"; | 59 return "h264 scalable baseline"; |
59 case H264PROFILE_SCALABLEHIGH: | 60 case H264PROFILE_SCALABLEHIGH: |
60 return "h264 scalable high"; | 61 return "h264 scalable high"; |
61 case H264PROFILE_STEREOHIGH: | 62 case H264PROFILE_STEREOHIGH: |
62 return "h264 stereo high"; | 63 return "h264 stereo high"; |
63 case H264PROFILE_MULTIVIEWHIGH: | 64 case H264PROFILE_MULTIVIEWHIGH: |
64 return "h264 multiview high"; | 65 return "h264 multiview high"; |
66 case HEVCPROFILE_MAIN: | |
67 return "hevc main"; | |
68 case HEVCPROFILE_MAIN10: | |
69 return "hevc main 10"; | |
70 case HEVCPROFILE_MAIN_STILL_PICTURE: | |
71 return "hevc main still-picture"; | |
65 case VP8PROFILE_ANY: | 72 case VP8PROFILE_ANY: |
66 return "vp8"; | 73 return "vp8"; |
67 case VP9PROFILE_PROFILE0: | 74 case VP9PROFILE_PROFILE0: |
68 return "vp9 profile0"; | 75 return "vp9 profile0"; |
69 case VP9PROFILE_PROFILE1: | 76 case VP9PROFILE_PROFILE1: |
70 return "vp9 profile1"; | 77 return "vp9 profile1"; |
71 case VP9PROFILE_PROFILE2: | 78 case VP9PROFILE_PROFILE2: |
72 return "vp9 profile2"; | 79 return "vp9 profile2"; |
73 case VP9PROFILE_PROFILE3: | 80 case VP9PROFILE_PROFILE3: |
74 return "vp9 profile3"; | 81 return "vp9 profile3"; |
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
162 | 169 |
163 if (level_idc) | 170 if (level_idc) |
164 *level_idc = level_byte; | 171 *level_idc = level_byte; |
165 | 172 |
166 if (profile) | 173 if (profile) |
167 *profile = out_profile; | 174 *profile = out_profile; |
168 | 175 |
169 return true; | 176 return true; |
170 } | 177 } |
171 | 178 |
179 #if BUILDFLAG(ENABLE_HEVC_DEMUXING) | |
180 // The specification for HEVC codec id strings can be found in ISO IEC 14496-15 | |
181 // dated 2012 or newer in the Annex E.3 | |
182 bool ParseHEVCCodecId(const std::string& codec_id, | |
183 VideoCodecProfile* profile, | |
184 uint8_t* level_idc) { | |
185 if (!base::StartsWith(codec_id, "hev1.", base::CompareCase::SENSITIVE) && | |
186 !base::StartsWith(codec_id, "hvc1.", base::CompareCase::SENSITIVE)) { | |
187 return false; | |
188 } | |
189 | |
190 // HEVC codec id consists of: | |
191 const int kMaxHevcCodecIdLength = | |
192 5 + // 'hev1.' or 'hvc1.' prefix (5 chars) | |
193 4 + // profile, e.g. '.A12' (max 4 chars) | |
194 9 + // profile_compatibility, dot + 32-bit hex number (max 9 chars) | |
195 5 + // tier and level, e.g. '.H120' (max 5 chars) | |
196 18; // up to 6 constraint bytes, bytes are dot-separated and hex-encoded. | |
197 | |
198 if (codec_id.size() > kMaxHevcCodecIdLength) { | |
199 DVLOG(4) << __FUNCTION__ << ": Codec id is too long (" << codec_id << ")"; | |
200 return false; | |
201 } | |
202 | |
203 std::vector<std::string> elem = base::SplitString( | |
204 codec_id, ".", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL); | |
205 DCHECK(elem[0] == "hev1" || elem[0] == "hvc1"); | |
206 | |
207 if (elem.size() < 4) { | |
208 DVLOG(4) << __FUNCTION__ << ": invalid HEVC codec id " << codec_id; | |
209 return false; | |
210 } | |
211 | |
212 uint8_t general_profile_space = 0; | |
213 if (elem[1].size() > 0 && | |
214 (elem[1][0] == 'A' || elem[1][0] == 'B' || elem[1][0] == 'C')) { | |
215 general_profile_space = 1 + (elem[1][0] - 'A'); | |
216 elem[1].erase(0, 1); | |
217 } | |
218 DCHECK(general_profile_space >= 0 && general_profile_space <= 3); | |
ddorwin
2016/04/20 23:32:41
Should we be doing anything with general_profile_s
servolk
2016/04/20 23:57:48
No, general_profile_space is expected to be 0 for
ddorwin
2016/04/21 00:00:31
Then why do we allow 1, 2, and 3?
To the original
servolk
2016/04/21 00:13:27
Well, let me clarify. What I quoted above is from
| |
219 | |
220 unsigned general_profile_idc = 0; | |
221 if (!base::StringToUint(elem[1], &general_profile_idc) || | |
222 general_profile_idc > 0x1f) { | |
223 DVLOG(4) << __FUNCTION__ << ": invalid general_profile_idc=" << elem[1]; | |
224 return false; | |
225 } | |
226 | |
227 uint32_t general_profile_compatibility_flags = 0; | |
228 if (!base::HexStringToUInt(elem[2], &general_profile_compatibility_flags)) { | |
229 DVLOG(4) << __FUNCTION__ | |
230 << ": invalid general_profile_compatibility_flags=" << elem[2]; | |
231 return false; | |
232 } | |
233 | |
234 if (profile) { | |
235 // TODO(servolk): Handle format range extension profiles as explained in | |
236 // HEVC standard (ISO/IEC ISO/IEC 23008-2) section A.3.5 | |
237 if (general_profile_idc == 3 || (general_profile_compatibility_flags & 4)) { | |
238 *profile = HEVCPROFILE_MAIN_STILL_PICTURE; | |
239 } | |
240 if (general_profile_idc == 2 || (general_profile_compatibility_flags & 2)) { | |
241 *profile = HEVCPROFILE_MAIN10; | |
242 } | |
243 if (general_profile_idc == 1 || (general_profile_compatibility_flags & 1)) { | |
244 *profile = HEVCPROFILE_MAIN; | |
245 } | |
246 } | |
247 | |
248 uint8_t general_tier_flag; | |
249 if (elem[3].size() > 0 && (elem[3][0] == 'L' || elem[3][0] == 'H')) { | |
250 general_tier_flag = (elem[3][0] == 'L') ? 0 : 1; | |
251 elem[3].erase(0, 1); | |
252 } else { | |
253 DVLOG(4) << __FUNCTION__ << ": invalid general_tier_flag=" << elem[3]; | |
254 return false; | |
255 } | |
256 DCHECK(general_tier_flag == 0 || general_tier_flag == 1); | |
257 | |
258 unsigned general_level_idc = 0; | |
259 if (!base::StringToUint(elem[3], &general_level_idc) || | |
260 general_level_idc > 0xff) { | |
261 DVLOG(4) << __FUNCTION__ << ": invalid general_level_idc=" << elem[3]; | |
262 return false; | |
263 } | |
264 | |
265 if (level_idc) | |
266 *level_idc = static_cast<uint8_t>(general_level_idc); | |
267 | |
268 uint8_t constraint_flags[6]; | |
269 memset(constraint_flags, 0, sizeof(constraint_flags)); | |
270 | |
271 if (elem.size() > 10) { | |
272 DVLOG(4) << __FUNCTION__ << ": unexpected number of trailing bytes in HEVC " | |
273 << "codec id " << codec_id; | |
274 return false; | |
275 } | |
276 for (size_t i = 4; i < elem.size(); ++i) { | |
277 unsigned constr_byte = 0; | |
278 if (!base::HexStringToUInt(elem[i], &constr_byte) || constr_byte > 0xFF) { | |
279 DVLOG(4) << __FUNCTION__ << ": invalid constraint byte=" << elem[i]; | |
280 return false; | |
281 } | |
282 constraint_flags[i] = constr_byte; | |
283 } | |
284 | |
285 return true; | |
286 } | |
287 #endif | |
288 | |
172 } // namespace media | 289 } // namespace media |
OLD | NEW |