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

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

Issue 1677133003: Implemented parsing of HEVC codec ids (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@parse-codec-id
Patch Set: Fixed handling of empty elements + added test cases with empty elements Created 4 years, 8 months 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
« no previous file with comments | « media/base/video_codecs.h ('k') | media/base/video_decoder_config.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
OLDNEW
« no previous file with comments | « media/base/video_codecs.h ('k') | media/base/video_decoder_config.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698