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_ANY: | 74 case VP9PROFILE_ANY: |
68 return "vp9"; | 75 return "vp9"; |
69 } | 76 } |
70 NOTREACHED(); | 77 NOTREACHED(); |
71 return ""; | 78 return ""; |
72 } | 79 } |
73 | 80 |
74 bool ParseAVCCodecId(const std::string& codec_id, | 81 bool ParseAVCCodecId(const std::string& codec_id, |
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
156 | 163 |
157 if (level_idc) | 164 if (level_idc) |
158 *level_idc = level_byte; | 165 *level_idc = level_byte; |
159 | 166 |
160 if (profile) | 167 if (profile) |
161 *profile = out_profile; | 168 *profile = out_profile; |
162 | 169 |
163 return true; | 170 return true; |
164 } | 171 } |
165 | 172 |
| 173 #if BUILDFLAG(ENABLE_HEVC_DEMUXING) |
| 174 // The specification for HEVC codec id strings can be found in ISO IEC 14496-15 |
| 175 // dated 2012 or newer in the Annex E.3 |
| 176 bool ParseHEVCCodecId(const std::string& codec_id, |
| 177 VideoCodecProfile* profile, |
| 178 uint8_t* level_idc) { |
| 179 if (!base::StartsWith(codec_id, "hev1.", base::CompareCase::SENSITIVE) && |
| 180 !base::StartsWith(codec_id, "hvc1.", base::CompareCase::SENSITIVE)) { |
| 181 return false; |
| 182 } |
| 183 |
| 184 // HEVC codec id consists of: |
| 185 const int kMaxHevcCodecIdLength = |
| 186 5 + // 'hev1.' or 'hvc1.' prefix (5 chars) |
| 187 4 + // profile, e.g. '.A12' (max 4 chars) |
| 188 9 + // profile_compatibility, dot + 32-bit hex number (max 9 chars) |
| 189 5 + // tier and level, e.g. '.H120' (max 5 chars) |
| 190 18; // up to 6 constraint bytes, bytes are dot-separated and hex-encoded. |
| 191 |
| 192 if (codec_id.size() > kMaxHevcCodecIdLength) { |
| 193 DVLOG(4) << __FUNCTION__ << ": Codec id is too long (" << codec_id << ")"; |
| 194 return false; |
| 195 } |
| 196 |
| 197 std::vector<std::string> elem = base::SplitString( |
| 198 codec_id, ".", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL); |
| 199 DCHECK(elem[0] == "hev1" || elem[0] == "hvc1"); |
| 200 |
| 201 uint8_t general_profile_space = 0; |
| 202 if (elem[1][0] == 'A' || elem[1][0] == 'B' || elem[1][0] == 'C') { |
| 203 general_profile_space = 1 + (elem[1][0] - 'A'); |
| 204 elem[1].erase(0, 1); |
| 205 } |
| 206 CHECK(general_profile_space >= 0 && general_profile_space <= 3); |
| 207 |
| 208 unsigned general_profile_idc = 0; |
| 209 if (!base::StringToUint(elem[1], &general_profile_idc) || |
| 210 general_profile_idc > 0x1f) { |
| 211 DVLOG(4) << __FUNCTION__ << ": invalid general_profile_idc=" << elem[1]; |
| 212 return false; |
| 213 } |
| 214 |
| 215 uint32_t general_profile_compatibility_flags = 0; |
| 216 if (!base::HexStringToUInt(elem[2], &general_profile_compatibility_flags)) { |
| 217 DVLOG(4) << __FUNCTION__ |
| 218 << ": invalid general_profile_compatibility_flags=" << elem[2]; |
| 219 return false; |
| 220 } |
| 221 |
| 222 if (profile) { |
| 223 // TODO(servolk): Handle format range extension profiles as explained in |
| 224 // HEVC standard (ISO/IEC ISO/IEC 23008-2) section A.3.5 |
| 225 if (general_profile_idc == 3 || (general_profile_compatibility_flags & 4)) { |
| 226 *profile = HEVCPROFILE_MAIN_STILL_PICTURE; |
| 227 } |
| 228 if (general_profile_idc == 2 || (general_profile_compatibility_flags & 2)) { |
| 229 *profile = HEVCPROFILE_MAIN10; |
| 230 } |
| 231 if (general_profile_idc == 1 || (general_profile_compatibility_flags & 1)) { |
| 232 *profile = HEVCPROFILE_MAIN; |
| 233 } |
| 234 } |
| 235 |
| 236 uint8_t general_tier_flag; |
| 237 if (elem[3][0] == 'L' || elem[3][0] == 'H') { |
| 238 general_tier_flag = (elem[3][0] == 'L') ? 0 : 1; |
| 239 elem[3].erase(0, 1); |
| 240 } else { |
| 241 DVLOG(4) << __FUNCTION__ << ": invalid general_tier_flag=" << elem[3]; |
| 242 return false; |
| 243 } |
| 244 CHECK(general_tier_flag == 0 || general_tier_flag == 1); |
| 245 |
| 246 unsigned general_level_idc = 0; |
| 247 if (!base::StringToUint(elem[3], &general_level_idc) || |
| 248 general_level_idc > 0xff) { |
| 249 DVLOG(4) << __FUNCTION__ << ": invalid general_level_idc=" << elem[3]; |
| 250 return false; |
| 251 } |
| 252 |
| 253 if (level_idc) |
| 254 *level_idc = static_cast<uint8_t>(general_level_idc); |
| 255 |
| 256 uint8_t constraint_flags[6]; |
| 257 memset(constraint_flags, 0, sizeof(constraint_flags)); |
| 258 // Remove everything up to the first constraint_flags byte |
| 259 elem.erase(elem.begin(), elem.begin() + 4); |
| 260 if (elem.size() > 6) { |
| 261 DVLOG(4) << __FUNCTION__ << ": unexpected number of trailing bytes in HEVC " |
| 262 << "codec id " << codec_id; |
| 263 return false; |
| 264 } |
| 265 for (size_t i = 0; i < elem.size(); ++i) { |
| 266 unsigned constr_byte = 0; |
| 267 if (!base::HexStringToUInt(elem[i], &constr_byte) || constr_byte > 0xFF) { |
| 268 DVLOG(4) << __FUNCTION__ << ": invalid constraint byte=" << elem[i]; |
| 269 return false; |
| 270 } |
| 271 constraint_flags[i] = constr_byte; |
| 272 } |
| 273 |
| 274 return true; |
| 275 } |
| 276 #endif |
| 277 |
166 } // namespace media | 278 } // namespace media |
OLD | NEW |