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 uint8_t general_profile_space = 0; |
| 208 if (elem[1][0] == 'A' || elem[1][0] == 'B' || elem[1][0] == 'C') { |
| 209 general_profile_space = 1 + (elem[1][0] - 'A'); |
| 210 elem[1].erase(0, 1); |
| 211 } |
| 212 CHECK(general_profile_space >= 0 && general_profile_space <= 3); |
| 213 |
| 214 unsigned general_profile_idc = 0; |
| 215 if (!base::StringToUint(elem[1], &general_profile_idc) || |
| 216 general_profile_idc > 0x1f) { |
| 217 DVLOG(4) << __FUNCTION__ << ": invalid general_profile_idc=" << elem[1]; |
| 218 return false; |
| 219 } |
| 220 |
| 221 uint32_t general_profile_compatibility_flags = 0; |
| 222 if (!base::HexStringToUInt(elem[2], &general_profile_compatibility_flags)) { |
| 223 DVLOG(4) << __FUNCTION__ |
| 224 << ": invalid general_profile_compatibility_flags=" << elem[2]; |
| 225 return false; |
| 226 } |
| 227 |
| 228 if (profile) { |
| 229 // TODO(servolk): Handle format range extension profiles as explained in |
| 230 // HEVC standard (ISO/IEC ISO/IEC 23008-2) section A.3.5 |
| 231 if (general_profile_idc == 3 || (general_profile_compatibility_flags & 4)) { |
| 232 *profile = HEVCPROFILE_MAIN_STILL_PICTURE; |
| 233 } |
| 234 if (general_profile_idc == 2 || (general_profile_compatibility_flags & 2)) { |
| 235 *profile = HEVCPROFILE_MAIN10; |
| 236 } |
| 237 if (general_profile_idc == 1 || (general_profile_compatibility_flags & 1)) { |
| 238 *profile = HEVCPROFILE_MAIN; |
| 239 } |
| 240 } |
| 241 |
| 242 uint8_t general_tier_flag; |
| 243 if (elem[3][0] == 'L' || elem[3][0] == 'H') { |
| 244 general_tier_flag = (elem[3][0] == 'L') ? 0 : 1; |
| 245 elem[3].erase(0, 1); |
| 246 } else { |
| 247 DVLOG(4) << __FUNCTION__ << ": invalid general_tier_flag=" << elem[3]; |
| 248 return false; |
| 249 } |
| 250 CHECK(general_tier_flag == 0 || general_tier_flag == 1); |
| 251 |
| 252 unsigned general_level_idc = 0; |
| 253 if (!base::StringToUint(elem[3], &general_level_idc) || |
| 254 general_level_idc > 0xff) { |
| 255 DVLOG(4) << __FUNCTION__ << ": invalid general_level_idc=" << elem[3]; |
| 256 return false; |
| 257 } |
| 258 |
| 259 if (level_idc) |
| 260 *level_idc = static_cast<uint8_t>(general_level_idc); |
| 261 |
| 262 uint8_t constraint_flags[6]; |
| 263 memset(constraint_flags, 0, sizeof(constraint_flags)); |
| 264 // Remove everything up to the first constraint_flags byte |
| 265 elem.erase(elem.begin(), elem.begin() + 4); |
| 266 if (elem.size() > 6) { |
| 267 DVLOG(4) << __FUNCTION__ << ": unexpected number of trailing bytes in HEVC " |
| 268 << "codec id " << codec_id; |
| 269 return false; |
| 270 } |
| 271 for (size_t i = 0; i < elem.size(); ++i) { |
| 272 unsigned constr_byte = 0; |
| 273 if (!base::HexStringToUInt(elem[i], &constr_byte) || constr_byte > 0xFF) { |
| 274 DVLOG(4) << __FUNCTION__ << ": invalid constraint byte=" << elem[i]; |
| 275 return false; |
| 276 } |
| 277 constraint_flags[i] = constr_byte; |
| 278 } |
| 279 |
| 280 return true; |
| 281 } |
| 282 #endif |
| 283 |
172 } // namespace media | 284 } // namespace media |
OLD | NEW |