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_split.h" |
10 #include "base/strings/string_util.h" | 10 #include "base/strings/string_util.h" |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
88 VideoCodecProfile* profile, | 88 VideoCodecProfile* profile, |
89 uint8_t* level_idc) { | 89 uint8_t* level_idc) { |
90 // Make sure we have avc1.xxxxxx or avc3.xxxxxx , where xxxxxx are hex digits | 90 // Make sure we have avc1.xxxxxx or avc3.xxxxxx , where xxxxxx are hex digits |
91 if (!base::StartsWith(codec_id, "avc1.", base::CompareCase::SENSITIVE) && | 91 if (!base::StartsWith(codec_id, "avc1.", base::CompareCase::SENSITIVE) && |
92 !base::StartsWith(codec_id, "avc3.", base::CompareCase::SENSITIVE)) { | 92 !base::StartsWith(codec_id, "avc3.", base::CompareCase::SENSITIVE)) { |
93 return false; | 93 return false; |
94 } | 94 } |
95 uint32_t elem = 0; | 95 uint32_t elem = 0; |
96 if (codec_id.size() != 11 || | 96 if (codec_id.size() != 11 || |
97 !base::HexStringToUInt(base::StringPiece(codec_id).substr(5), &elem)) { | 97 !base::HexStringToUInt(base::StringPiece(codec_id).substr(5), &elem)) { |
98 DVLOG(4) << __FUNCTION__ << ": invalid avc codec id (" << codec_id << ")"; | 98 DVLOG(4) << __func__ << ": invalid avc codec id (" << codec_id << ")"; |
99 return false; | 99 return false; |
100 } | 100 } |
101 | 101 |
102 uint8_t level_byte = elem & 0xFF; | 102 uint8_t level_byte = elem & 0xFF; |
103 uint8_t constraints_byte = (elem >> 8) & 0xFF; | 103 uint8_t constraints_byte = (elem >> 8) & 0xFF; |
104 uint8_t profile_idc = (elem >> 16) & 0xFF; | 104 uint8_t profile_idc = (elem >> 16) & 0xFF; |
105 | 105 |
106 // Check that the lower two bits of |constraints_byte| are zero (those are | 106 // Check that the lower two bits of |constraints_byte| are zero (those are |
107 // reserved and must be zero according to ISO IEC 14496-10). | 107 // reserved and must be zero according to ISO IEC 14496-10). |
108 if (constraints_byte & 3) { | 108 if (constraints_byte & 3) { |
109 DVLOG(4) << __FUNCTION__ << ": non-zero reserved bits in codec id " | 109 DVLOG(4) << __func__ << ": non-zero reserved bits in codec id " << codec_id; |
110 << codec_id; | |
111 return false; | 110 return false; |
112 } | 111 } |
113 | 112 |
114 VideoCodecProfile out_profile = VIDEO_CODEC_PROFILE_UNKNOWN; | 113 VideoCodecProfile out_profile = VIDEO_CODEC_PROFILE_UNKNOWN; |
115 // profile_idc values for each profile are taken from ISO IEC 14496-10 and | 114 // profile_idc values for each profile are taken from ISO IEC 14496-10 and |
116 // https://en.wikipedia.org/wiki/H.264/MPEG-4_AVC#Profiles | 115 // https://en.wikipedia.org/wiki/H.264/MPEG-4_AVC#Profiles |
117 switch (profile_idc) { | 116 switch (profile_idc) { |
118 case 66: | 117 case 66: |
119 out_profile = H264PROFILE_BASELINE; | 118 out_profile = H264PROFILE_BASELINE; |
120 break; | 119 break; |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
189 | 188 |
190 // HEVC codec id consists of: | 189 // HEVC codec id consists of: |
191 const int kMaxHevcCodecIdLength = | 190 const int kMaxHevcCodecIdLength = |
192 5 + // 'hev1.' or 'hvc1.' prefix (5 chars) | 191 5 + // 'hev1.' or 'hvc1.' prefix (5 chars) |
193 4 + // profile, e.g. '.A12' (max 4 chars) | 192 4 + // profile, e.g. '.A12' (max 4 chars) |
194 9 + // profile_compatibility, dot + 32-bit hex number (max 9 chars) | 193 9 + // profile_compatibility, dot + 32-bit hex number (max 9 chars) |
195 5 + // tier and level, e.g. '.H120' (max 5 chars) | 194 5 + // tier and level, e.g. '.H120' (max 5 chars) |
196 18; // up to 6 constraint bytes, bytes are dot-separated and hex-encoded. | 195 18; // up to 6 constraint bytes, bytes are dot-separated and hex-encoded. |
197 | 196 |
198 if (codec_id.size() > kMaxHevcCodecIdLength) { | 197 if (codec_id.size() > kMaxHevcCodecIdLength) { |
199 DVLOG(4) << __FUNCTION__ << ": Codec id is too long (" << codec_id << ")"; | 198 DVLOG(4) << __func__ << ": Codec id is too long (" << codec_id << ")"; |
200 return false; | 199 return false; |
201 } | 200 } |
202 | 201 |
203 std::vector<std::string> elem = base::SplitString( | 202 std::vector<std::string> elem = base::SplitString( |
204 codec_id, ".", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL); | 203 codec_id, ".", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL); |
205 DCHECK(elem[0] == "hev1" || elem[0] == "hvc1"); | 204 DCHECK(elem[0] == "hev1" || elem[0] == "hvc1"); |
206 | 205 |
207 if (elem.size() < 4) { | 206 if (elem.size() < 4) { |
208 DVLOG(4) << __FUNCTION__ << ": invalid HEVC codec id " << codec_id; | 207 DVLOG(4) << __func__ << ": invalid HEVC codec id " << codec_id; |
209 return false; | 208 return false; |
210 } | 209 } |
211 | 210 |
212 uint8_t general_profile_space = 0; | 211 uint8_t general_profile_space = 0; |
213 if (elem[1].size() > 0 && | 212 if (elem[1].size() > 0 && |
214 (elem[1][0] == 'A' || elem[1][0] == 'B' || elem[1][0] == 'C')) { | 213 (elem[1][0] == 'A' || elem[1][0] == 'B' || elem[1][0] == 'C')) { |
215 general_profile_space = 1 + (elem[1][0] - 'A'); | 214 general_profile_space = 1 + (elem[1][0] - 'A'); |
216 elem[1].erase(0, 1); | 215 elem[1].erase(0, 1); |
217 } | 216 } |
218 DCHECK(general_profile_space >= 0 && general_profile_space <= 3); | 217 DCHECK(general_profile_space >= 0 && general_profile_space <= 3); |
219 | 218 |
220 unsigned general_profile_idc = 0; | 219 unsigned general_profile_idc = 0; |
221 if (!base::StringToUint(elem[1], &general_profile_idc) || | 220 if (!base::StringToUint(elem[1], &general_profile_idc) || |
222 general_profile_idc > 0x1f) { | 221 general_profile_idc > 0x1f) { |
223 DVLOG(4) << __FUNCTION__ << ": invalid general_profile_idc=" << elem[1]; | 222 DVLOG(4) << __func__ << ": invalid general_profile_idc=" << elem[1]; |
224 return false; | 223 return false; |
225 } | 224 } |
226 | 225 |
227 uint32_t general_profile_compatibility_flags = 0; | 226 uint32_t general_profile_compatibility_flags = 0; |
228 if (!base::HexStringToUInt(elem[2], &general_profile_compatibility_flags)) { | 227 if (!base::HexStringToUInt(elem[2], &general_profile_compatibility_flags)) { |
229 DVLOG(4) << __FUNCTION__ | 228 DVLOG(4) << __func__ |
230 << ": invalid general_profile_compatibility_flags=" << elem[2]; | 229 << ": invalid general_profile_compatibility_flags=" << elem[2]; |
231 return false; | 230 return false; |
232 } | 231 } |
233 | 232 |
234 if (profile) { | 233 if (profile) { |
235 // TODO(servolk): Handle format range extension profiles as explained in | 234 // TODO(servolk): Handle format range extension profiles as explained in |
236 // HEVC standard (ISO/IEC ISO/IEC 23008-2) section A.3.5 | 235 // HEVC standard (ISO/IEC ISO/IEC 23008-2) section A.3.5 |
237 if (general_profile_idc == 3 || (general_profile_compatibility_flags & 4)) { | 236 if (general_profile_idc == 3 || (general_profile_compatibility_flags & 4)) { |
238 *profile = HEVCPROFILE_MAIN_STILL_PICTURE; | 237 *profile = HEVCPROFILE_MAIN_STILL_PICTURE; |
239 } | 238 } |
240 if (general_profile_idc == 2 || (general_profile_compatibility_flags & 2)) { | 239 if (general_profile_idc == 2 || (general_profile_compatibility_flags & 2)) { |
241 *profile = HEVCPROFILE_MAIN10; | 240 *profile = HEVCPROFILE_MAIN10; |
242 } | 241 } |
243 if (general_profile_idc == 1 || (general_profile_compatibility_flags & 1)) { | 242 if (general_profile_idc == 1 || (general_profile_compatibility_flags & 1)) { |
244 *profile = HEVCPROFILE_MAIN; | 243 *profile = HEVCPROFILE_MAIN; |
245 } | 244 } |
246 } | 245 } |
247 | 246 |
248 uint8_t general_tier_flag; | 247 uint8_t general_tier_flag; |
249 if (elem[3].size() > 0 && (elem[3][0] == 'L' || elem[3][0] == 'H')) { | 248 if (elem[3].size() > 0 && (elem[3][0] == 'L' || elem[3][0] == 'H')) { |
250 general_tier_flag = (elem[3][0] == 'L') ? 0 : 1; | 249 general_tier_flag = (elem[3][0] == 'L') ? 0 : 1; |
251 elem[3].erase(0, 1); | 250 elem[3].erase(0, 1); |
252 } else { | 251 } else { |
253 DVLOG(4) << __FUNCTION__ << ": invalid general_tier_flag=" << elem[3]; | 252 DVLOG(4) << __func__ << ": invalid general_tier_flag=" << elem[3]; |
254 return false; | 253 return false; |
255 } | 254 } |
256 DCHECK(general_tier_flag == 0 || general_tier_flag == 1); | 255 DCHECK(general_tier_flag == 0 || general_tier_flag == 1); |
257 | 256 |
258 unsigned general_level_idc = 0; | 257 unsigned general_level_idc = 0; |
259 if (!base::StringToUint(elem[3], &general_level_idc) || | 258 if (!base::StringToUint(elem[3], &general_level_idc) || |
260 general_level_idc > 0xff) { | 259 general_level_idc > 0xff) { |
261 DVLOG(4) << __FUNCTION__ << ": invalid general_level_idc=" << elem[3]; | 260 DVLOG(4) << __func__ << ": invalid general_level_idc=" << elem[3]; |
262 return false; | 261 return false; |
263 } | 262 } |
264 | 263 |
265 if (level_idc) | 264 if (level_idc) |
266 *level_idc = static_cast<uint8_t>(general_level_idc); | 265 *level_idc = static_cast<uint8_t>(general_level_idc); |
267 | 266 |
268 uint8_t constraint_flags[6]; | 267 uint8_t constraint_flags[6]; |
269 memset(constraint_flags, 0, sizeof(constraint_flags)); | 268 memset(constraint_flags, 0, sizeof(constraint_flags)); |
270 | 269 |
271 if (elem.size() > 10) { | 270 if (elem.size() > 10) { |
272 DVLOG(4) << __FUNCTION__ << ": unexpected number of trailing bytes in HEVC " | 271 DVLOG(4) << __func__ << ": unexpected number of trailing bytes in HEVC " |
273 << "codec id " << codec_id; | 272 << "codec id " << codec_id; |
274 return false; | 273 return false; |
275 } | 274 } |
276 for (size_t i = 4; i < elem.size(); ++i) { | 275 for (size_t i = 4; i < elem.size(); ++i) { |
277 unsigned constr_byte = 0; | 276 unsigned constr_byte = 0; |
278 if (!base::HexStringToUInt(elem[i], &constr_byte) || constr_byte > 0xFF) { | 277 if (!base::HexStringToUInt(elem[i], &constr_byte) || constr_byte > 0xFF) { |
279 DVLOG(4) << __FUNCTION__ << ": invalid constraint byte=" << elem[i]; | 278 DVLOG(4) << __func__ << ": invalid constraint byte=" << elem[i]; |
280 return false; | 279 return false; |
281 } | 280 } |
282 constraint_flags[i] = constr_byte; | 281 constraint_flags[i] = constr_byte; |
283 } | 282 } |
284 | 283 |
285 return true; | 284 return true; |
286 } | 285 } |
287 #endif | 286 #endif |
288 | 287 |
289 } // namespace media | 288 } // namespace media |
OLD | NEW |