1 // Copyright 2015 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "media/base/video_codecs.h"
7 #include "base/logging.h"
8 #include "base/notreached.h"
9 #include "base/strings/string_number_conversions.h"
10 #include "base/strings/string_piece.h"
11 #include "base/strings/string_split.h"
12 #include "base/strings/string_util.h"
13 #include "base/strings/stringprintf.h"
14 #include "media/base/video_color_space.h"
15 #include "ui/gfx/color_space.h"
19 // The names come from src/third_party/ffmpeg/libavcodec/codec_desc.c
20 // TODO(crbug.com/1357080): The returned strings are used by ChunkDemuxer in
21 // the code logic as well in tests. Merge with GetCodecNameForUMA() if possible.
22 std::string GetCodecName(VideoCodec codec) {
24 case VideoCodec::kUnknown:
26 case VideoCodec::kH264:
28 case VideoCodec::kHEVC:
30 case VideoCodec::kDolbyVision:
32 case VideoCodec::kVC1:
34 case VideoCodec::kMPEG2:
36 case VideoCodec::kMPEG4:
38 case VideoCodec::kTheora:
40 case VideoCodec::kVP8:
42 case VideoCodec::kVP9:
44 case VideoCodec::kAV1:
46 #if defined(TIZEN_MULTIMEDIA_MJPEG_SUPPORT)
47 case VideoCodec::kMJPEG:
51 NOTREACHED_NORETURN();
54 // Reported as part of some UMA names. NEVER change existing strings!
55 std::string GetCodecNameForUMA(VideoCodec codec) {
57 case VideoCodec::kUnknown:
59 case VideoCodec::kH264:
61 case VideoCodec::kHEVC:
63 case VideoCodec::kDolbyVision:
65 case VideoCodec::kVC1:
67 case VideoCodec::kMPEG2:
69 case VideoCodec::kMPEG4:
71 case VideoCodec::kTheora:
73 case VideoCodec::kVP8:
75 case VideoCodec::kVP9:
77 case VideoCodec::kAV1:
80 NOTREACHED_NORETURN();
83 std::string GetProfileName(VideoCodecProfile profile) {
85 case VIDEO_CODEC_PROFILE_UNKNOWN:
87 case H264PROFILE_BASELINE:
88 return "h264 baseline";
89 case H264PROFILE_MAIN:
91 case H264PROFILE_EXTENDED:
92 return "h264 extended";
93 case H264PROFILE_HIGH:
95 case H264PROFILE_HIGH10PROFILE:
96 return "h264 high 10";
97 case H264PROFILE_HIGH422PROFILE:
98 return "h264 high 4:2:2";
99 case H264PROFILE_HIGH444PREDICTIVEPROFILE:
100 return "h264 high 4:4:4 predictive";
101 case H264PROFILE_SCALABLEBASELINE:
102 return "h264 scalable baseline";
103 case H264PROFILE_SCALABLEHIGH:
104 return "h264 scalable high";
105 case H264PROFILE_STEREOHIGH:
106 return "h264 stereo high";
107 case H264PROFILE_MULTIVIEWHIGH:
108 return "h264 multiview high";
109 case HEVCPROFILE_MAIN:
111 case HEVCPROFILE_MAIN10:
112 return "hevc main 10";
113 case HEVCPROFILE_MAIN_STILL_PICTURE:
114 return "hevc main still-picture";
115 case HEVCPROFILE_REXT:
116 return "hevc range extensions";
117 case HEVCPROFILE_HIGH_THROUGHPUT:
118 return "hevc high throughput";
119 case HEVCPROFILE_MULTIVIEW_MAIN:
120 return "hevc multiview main";
121 case HEVCPROFILE_SCALABLE_MAIN:
122 return "hevc scalable main";
123 case HEVCPROFILE_3D_MAIN:
124 return "hevc 3d main";
125 case HEVCPROFILE_SCREEN_EXTENDED:
126 return "hevc screen extended";
127 case HEVCPROFILE_SCALABLE_REXT:
128 return "hevc scalable range extensions";
129 case HEVCPROFILE_HIGH_THROUGHPUT_SCREEN_EXTENDED:
130 return "hevc high throughput screen extended";
133 case VP9PROFILE_PROFILE0:
134 return "vp9 profile0";
135 case VP9PROFILE_PROFILE1:
136 return "vp9 profile1";
137 case VP9PROFILE_PROFILE2:
138 return "vp9 profile2";
139 case VP9PROFILE_PROFILE3:
140 return "vp9 profile3";
141 case DOLBYVISION_PROFILE0:
142 return "dolby vision profile 0";
143 case DOLBYVISION_PROFILE4:
144 return "dolby vision profile 4";
145 case DOLBYVISION_PROFILE5:
146 return "dolby vision profile 5";
147 case DOLBYVISION_PROFILE7:
148 return "dolby vision profile 7";
149 case DOLBYVISION_PROFILE8:
150 return "dolby vision profile 8";
151 case DOLBYVISION_PROFILE9:
152 return "dolby vision profile 9";
153 case THEORAPROFILE_ANY:
155 case AV1PROFILE_PROFILE_MAIN:
156 return "av1 profile main";
157 case AV1PROFILE_PROFILE_HIGH:
158 return "av1 profile high";
159 case AV1PROFILE_PROFILE_PRO:
160 return "av1 profile pro";
161 case VVCPROFILE_MAIN10:
162 return "vvc profile main10";
163 case VVCPROFILE_MAIN12:
164 return "vvc profile main12";
165 case VVCPROFILE_MAIN12_INTRA:
166 return "vvc profile main12 intra";
167 case VVCPROIFLE_MULTILAYER_MAIN10:
168 return "vvc profile multilayer main10";
169 case VVCPROFILE_MAIN10_444:
170 return "vvc profile main10 444";
171 case VVCPROFILE_MAIN12_444:
172 return "vvc profile main12 444";
173 case VVCPROFILE_MAIN16_444:
174 return "vvc profile main16 444";
175 case VVCPROFILE_MAIN12_444_INTRA:
176 return "vvc profile main12 444 intra";
177 case VVCPROFILE_MAIN16_444_INTRA:
178 return "vvc profile main16 444 intra";
179 case VVCPROFILE_MULTILAYER_MAIN10_444:
180 return "vvc profile multilayer main10 444";
181 case VVCPROFILE_MAIN10_STILL_PICTURE:
182 return "vvc profile main10 still picture";
183 case VVCPROFILE_MAIN12_STILL_PICTURE:
184 return "vvc profile main12 still picture";
185 case VVCPROFILE_MAIN10_444_STILL_PICTURE:
186 return "vvc profile main10 444 still picture";
187 case VVCPROFILE_MAIN12_444_STILL_PICTURE:
188 return "vvc profile main12 444 still picture";
189 case VVCPROFILE_MAIN16_444_STILL_PICTURE:
190 return "vvc profile main16 444 still picture";
192 NOTREACHED_NORETURN();
195 std::string BuildH264MimeSuffix(media::VideoCodecProfile profile,
197 std::string profile_str;
199 case media::VideoCodecProfile::H264PROFILE_BASELINE:
202 case media::VideoCodecProfile::H264PROFILE_MAIN:
205 case media::VideoCodecProfile::H264PROFILE_SCALABLEBASELINE:
208 case media::VideoCodecProfile::H264PROFILE_SCALABLEHIGH:
211 case media::VideoCodecProfile::H264PROFILE_EXTENDED:
214 case media::VideoCodecProfile::H264PROFILE_HIGH:
217 case media::VideoCodecProfile::H264PROFILE_HIGH10PROFILE:
220 case media::VideoCodecProfile::H264PROFILE_MULTIVIEWHIGH:
223 case media::VideoCodecProfile::H264PROFILE_HIGH422PROFILE:
226 case media::VideoCodecProfile::H264PROFILE_STEREOHIGH:
229 case media::VideoCodecProfile::H264PROFILE_HIGH444PREDICTIVEPROFILE:
236 return base::StringPrintf(".%s%04x", profile_str.c_str(), level);
239 bool ParseNewStyleVp9CodecID(base::StringPiece codec_id,
240 VideoCodecProfile* profile,
242 VideoColorSpace* color_space) {
243 // Initialize optional fields to their defaults.
244 *color_space = VideoColorSpace::REC709();
246 std::vector<std::string> fields = base::SplitString(
247 codec_id, ".", base::KEEP_WHITESPACE, base::SPLIT_WANT_ALL);
249 // First four fields are mandatory. No more than 9 fields are expected.
250 if (fields.size() < 4 || fields.size() > 9) {
251 DVLOG(3) << __func__ << " Invalid number of fields (" << fields.size()
256 if (fields[0] != "vp09") {
257 DVLOG(3) << __func__ << " Invalid 4CC (" << fields[0] << ")";
261 std::vector<int> values;
262 for (size_t i = 1; i < fields.size(); ++i) {
263 // Missing value is not allowed.
264 if (fields[i] == "") {
265 DVLOG(3) << __func__ << " Invalid missing field (position:" << i << ")";
269 if (!base::StringToInt(fields[i], &value) || value < 0) {
270 DVLOG(3) << __func__ << " Invalid field value (" << value << ")";
273 values.push_back(value);
276 const int profile_idc = values[0];
277 switch (profile_idc) {
279 *profile = VP9PROFILE_PROFILE0;
282 *profile = VP9PROFILE_PROFILE1;
285 *profile = VP9PROFILE_PROFILE2;
288 *profile = VP9PROFILE_PROFILE3;
291 DVLOG(3) << __func__ << " Invalid profile (" << profile_idc << ")";
295 *level_idc = values[1];
296 switch (*level_idc) {
313 DVLOG(3) << __func__ << " Invalid level (" << *level_idc << ")";
317 const int bit_depth = values[2];
318 if (bit_depth != 8 && bit_depth != 10 && bit_depth != 12) {
319 DVLOG(3) << __func__ << " Invalid bit-depth (" << bit_depth << ")";
323 if (values.size() < 4)
325 const int chroma_subsampling = values[3];
326 if (chroma_subsampling > 3) {
327 DVLOG(3) << __func__ << " Invalid chroma subsampling ("
328 << chroma_subsampling << ")";
332 if (values.size() < 5)
334 color_space->primaries = VideoColorSpace::GetPrimaryID(values[4]);
335 if (color_space->primaries == VideoColorSpace::PrimaryID::INVALID) {
336 DVLOG(3) << __func__ << " Invalid color primaries (" << values[4] << ")";
340 if (values.size() < 6)
342 color_space->transfer = VideoColorSpace::GetTransferID(values[5]);
343 if (color_space->transfer == VideoColorSpace::TransferID::INVALID) {
344 DVLOG(3) << __func__ << " Invalid transfer function (" << values[5] << ")";
348 if (values.size() < 7)
350 color_space->matrix = VideoColorSpace::GetMatrixID(values[6]);
351 if (color_space->matrix == VideoColorSpace::MatrixID::INVALID) {
352 DVLOG(3) << __func__ << " Invalid matrix coefficients (" << values[6]
356 if (color_space->matrix == VideoColorSpace::MatrixID::RGB &&
357 chroma_subsampling != 3) {
358 DVLOG(3) << __func__ << " Invalid combination of chroma_subsampling ("
359 << ") and matrix coefficients (" << values[6] << ")";
362 if (values.size() < 8)
364 const int video_full_range_flag = values[7];
365 if (video_full_range_flag > 1) {
366 DVLOG(3) << __func__ << " Invalid full range flag ("
367 << video_full_range_flag << ")";
370 color_space->range = video_full_range_flag == 1
371 ? gfx::ColorSpace::RangeID::FULL
372 : gfx::ColorSpace::RangeID::LIMITED;
377 bool ParseLegacyVp9CodecID(base::StringPiece codec_id,
378 VideoCodecProfile* profile,
379 uint8_t* level_idc) {
380 if (codec_id == "vp9" || codec_id == "vp9.0") {
381 // Profile is not included in the codec string. Consumers of parsed codec
382 // should handle by rejecting ambiguous string or resolving to a default
384 *profile = VIDEO_CODEC_PROFILE_UNKNOWN;
385 // Use 0 to indicate unknown level.
392 #if BUILDFLAG(ENABLE_AV1_DECODER)
393 bool ParseAv1CodecId(base::StringPiece codec_id,
394 VideoCodecProfile* profile,
396 VideoColorSpace* color_space) {
397 // The codecs parameter string for the AOM AV1 codec is as follows:
398 // See https://aomediacodec.github.io/av1-isobmff/#codecsparam.
400 // <sample entry4CC>.<profile>.<level><tier>.<bitDepth>.<monochrome>.
401 // <chromaSubsampling>.<colorPrimaries>.<transferCharacteristics>.
402 // <matrixCoefficients>.<videoFullRangeFlag>
404 std::vector<std::string> fields = base::SplitString(
405 codec_id, ".", base::KEEP_WHITESPACE, base::SPLIT_WANT_ALL);
407 // The parameters sample entry 4CC, profile, level, tier, and bitDepth are all
408 // mandatory fields. If any of these fields are empty, or not within their
409 // allowed range, the processing device SHOULD treat it as an error.
410 if (fields.size() < 4 || fields.size() > 10) {
411 DVLOG(3) << __func__ << " Invalid number of fields (" << fields.size()
416 // All the other fields (including their leading '.') are optional, mutually
417 // inclusive (all or none) fields. If not specified then the values listed in
418 // the table below are assumed.
421 // chromaSubsampling 112 (4:2:0 colocated with luma (0,0))
422 // colorPrimaries 1 (ITU-R BT.709)
423 // transferCharacteristics 1 (ITU-R BT.709)
424 // matrixCoefficients 1 (ITU-R BT.709)
425 // videoFullRangeFlag 0 (studio swing representation)
426 *color_space = VideoColorSpace::REC709();
428 if (fields[0] != "av01") {
429 DVLOG(3) << __func__ << " Invalid AV1 4CC (" << fields[0] << ")";
433 // The level parameter value SHALL equal the first level value indicated by
434 // seq_level_idx in the Sequence Header. The tier parameter value SHALL be
435 // equal to M when the first seq_tier value in the Sequence Header is equal to
436 // 0, and H when it is equal to 1.
437 if (fields[2].size() != 3 || (fields[2][2] != 'M' && fields[2][2] != 'H')) {
438 DVLOG(3) << __func__ << " Invalid level+tier (" << fields[2] << ")";
442 // Since tier has been validated, strip the trailing tier indicator to allow
443 // int conversion below.
446 // Fill with dummy values to ensure parallel indices with fields.
447 std::vector<int> values(fields.size(), 0);
448 for (size_t i = 1; i < fields.size(); ++i) {
449 if (fields[i].empty()) {
450 DVLOG(3) << __func__ << " Invalid empty field (position:" << i << ")";
454 if (!base::StringToInt(fields[i], &values[i]) || values[i] < 0) {
455 DVLOG(3) << __func__ << " Invalid field value (" << values[i] << ")";
460 // The profile parameter value, represented by a single digit decimal, SHALL
461 // equal the value of seq_profile in the Sequence Header.
462 const int profile_idc = fields[1].size() == 1 ? values[1] : -1;
463 switch (profile_idc) {
465 *profile = AV1PROFILE_PROFILE_MAIN;
468 *profile = AV1PROFILE_PROFILE_HIGH;
471 *profile = AV1PROFILE_PROFILE_PRO;
474 DVLOG(3) << __func__ << " Invalid profile (" << fields[1] << ")";
478 // The level parameter value SHALL equal the first level value indicated by
479 // seq_level_idx in the Sequence Header. Note: We validate that this field has
480 // the required leading zeros above.
481 *level_idc = values[2];
482 if (*level_idc > 31) {
483 DVLOG(3) << __func__ << " Invalid level (" << *level_idc << ")";
487 // The bitDepth parameter value SHALL equal the value of BitDepth variable as
488 // defined in [AV1] derived from the Sequence Header. Leading zeros required.
489 const int bit_depth = values[3];
490 if (fields[3].size() != 2 ||
491 (bit_depth != 8 && bit_depth != 10 && bit_depth != 12)) {
492 DVLOG(3) << __func__ << " Invalid bit-depth (" << fields[3] << ")";
496 if (values.size() <= 4)
499 // The monochrome parameter value, represented by a single digit decimal,
500 // SHALL equal the value of mono_chrome in the Sequence Header.
501 const int monochrome = values[4];
502 if (fields[4].size() != 1 || monochrome > 1) {
503 DVLOG(3) << __func__ << " Invalid monochrome (" << fields[4] << ")";
507 if (values.size() <= 5)
510 // The chromaSubsampling parameter value, represented by a three-digit
511 // decimal, SHALL have its first digit equal to subsampling_x and its second
512 // digit equal to subsampling_y. If both subsampling_x and subsampling_y are
513 // set to 1, then the third digit SHALL be equal to chroma_sample_position,
514 // otherwise it SHALL be set to 0.
515 if (fields[5].size() != 3) {
516 DVLOG(3) << __func__ << " Invalid chroma subsampling (" << fields[5] << ")";
520 const char subsampling_x = fields[5][0];
521 const char subsampling_y = fields[5][1];
522 const char chroma_sample_position = fields[5][2];
523 if ((subsampling_x < '0' || subsampling_x > '1') ||
524 (subsampling_y < '0' || subsampling_y > '1') ||
525 (chroma_sample_position < '0' || chroma_sample_position > '3')) {
526 DVLOG(3) << __func__ << " Invalid chroma subsampling (" << fields[5] << ")";
530 if (((subsampling_x == '0' || subsampling_y == '0') &&
531 chroma_sample_position != '0')) {
532 DVLOG(3) << __func__ << " Invalid chroma subsampling (" << fields[5] << ")";
536 if (values.size() <= 6)
539 // The colorPrimaries, transferCharacteristics, matrixCoefficients and
540 // videoFullRangeFlag parameter values SHALL equal the value of matching
541 // fields in the Sequence Header, if color_description_present_flag is set to
542 // 1, otherwise they SHOULD not be set, defaulting to the values below. The
543 // videoFullRangeFlag is represented by a single digit.
544 color_space->primaries = VideoColorSpace::GetPrimaryID(values[6]);
545 if (fields[6].size() != 2 ||
546 color_space->primaries == VideoColorSpace::PrimaryID::INVALID) {
547 DVLOG(3) << __func__ << " Invalid color primaries (" << fields[6] << ")";
551 if (values.size() <= 7)
554 color_space->transfer = VideoColorSpace::GetTransferID(values[7]);
555 if (fields[7].size() != 2 ||
556 color_space->transfer == VideoColorSpace::TransferID::INVALID) {
557 DVLOG(3) << __func__ << " Invalid transfer function (" << fields[7] << ")";
561 if (values.size() <= 8)
564 color_space->matrix = VideoColorSpace::GetMatrixID(values[8]);
565 if (fields[8].size() != 2 ||
566 color_space->matrix == VideoColorSpace::MatrixID::INVALID) {
567 // TODO(dalecurtis): AV1 allows a few matrices we don't support yet.
568 // https://crbug.com/854290
569 if (values[8] == 12 || values[8] == 13 || values[8] == 14) {
570 DVLOG(3) << __func__ << " Unsupported matrix coefficients (" << fields[8]
573 DVLOG(3) << __func__ << " Invalid matrix coefficients (" << fields[8]
579 if (values.size() <= 9)
582 const int video_full_range_flag = values[9];
583 if (fields[9].size() != 1 || video_full_range_flag > 1) {
584 DVLOG(3) << __func__ << " Invalid full range flag (" << fields[9] << ")";
587 color_space->range = video_full_range_flag == 1
588 ? gfx::ColorSpace::RangeID::FULL
589 : gfx::ColorSpace::RangeID::LIMITED;
593 #endif // BUILDFLAG(ENABLE_AV1_DECODER)
595 bool ParseAVCCodecId(base::StringPiece codec_id,
596 VideoCodecProfile* profile,
597 uint8_t* level_idc) {
598 // Make sure we have avc1.xxxxxx or avc3.xxxxxx , where xxxxxx are hex digits
599 if (!base::StartsWith(codec_id, "avc1.", base::CompareCase::SENSITIVE) &&
600 !base::StartsWith(codec_id, "avc3.", base::CompareCase::SENSITIVE)) {
604 if (codec_id.size() != 11 ||
605 !base::HexStringToUInt(base::StringPiece(codec_id).substr(5), &elem)) {
606 DVLOG(4) << __func__ << ": invalid avc codec id (" << codec_id << ")";
610 uint8_t level_byte = elem & 0xFF;
611 uint8_t constraints_byte = (elem >> 8) & 0xFF;
612 uint8_t profile_idc = (elem >> 16) & 0xFF;
614 // Check that the lower two bits of |constraints_byte| are zero (those are
615 // reserved and must be zero according to ISO IEC 14496-10).
616 if (constraints_byte & 3) {
617 DVLOG(4) << __func__ << ": non-zero reserved bits in codec id " << codec_id;
621 VideoCodecProfile out_profile = VIDEO_CODEC_PROFILE_UNKNOWN;
622 // profile_idc values for each profile are taken from ISO IEC 14496-10 and
623 // https://en.wikipedia.org/wiki/H.264/MPEG-4_AVC#Profiles
624 switch (profile_idc) {
626 out_profile = H264PROFILE_BASELINE;
629 out_profile = H264PROFILE_MAIN;
632 out_profile = H264PROFILE_SCALABLEBASELINE;
635 out_profile = H264PROFILE_SCALABLEHIGH;
638 out_profile = H264PROFILE_EXTENDED;
641 out_profile = H264PROFILE_HIGH;
644 out_profile = H264PROFILE_HIGH10PROFILE;
647 out_profile = H264PROFILE_MULTIVIEWHIGH;
650 out_profile = H264PROFILE_HIGH422PROFILE;
653 out_profile = H264PROFILE_STEREOHIGH;
656 out_profile = H264PROFILE_HIGH444PREDICTIVEPROFILE;
659 DVLOG(1) << "Warning: unrecognized AVC/H.264 profile " << profile_idc;
663 // TODO(servolk): Take into account also constraint set flags 3 through 5.
664 uint8_t constraint_set0_flag = (constraints_byte >> 7) & 1;
665 uint8_t constraint_set1_flag = (constraints_byte >> 6) & 1;
666 uint8_t constraint_set2_flag = (constraints_byte >> 5) & 1;
667 if (constraint_set2_flag && out_profile > H264PROFILE_EXTENDED) {
668 out_profile = H264PROFILE_EXTENDED;
670 if (constraint_set1_flag && out_profile > H264PROFILE_MAIN) {
671 out_profile = H264PROFILE_MAIN;
673 if (constraint_set0_flag && out_profile > H264PROFILE_BASELINE) {
674 out_profile = H264PROFILE_BASELINE;
678 *level_idc = level_byte;
681 *profile = out_profile;
686 #if BUILDFLAG(ENABLE_MSE_MPEG2TS_STREAM_PARSER) || BUILDFLAG(IS_TIZEN_TV)
687 std::string TranslateLegacyAvc1CodecIds(base::StringPiece codec_id) {
688 // Special handling for old, pre-RFC 6381 format avc1 strings, which are still
689 // being used by some HLS apps to preserve backward compatibility with older
690 // iOS devices. The old format was avc1.<profile>.<level>
691 // Where <profile> is H.264 profile_idc encoded as a decimal number, i.e.
692 // 66 is baseline profile (0x42)
693 // 77 is main profile (0x4d)
694 // 100 is high profile (0x64)
695 // And <level> is H.264 level multiplied by 10, also encoded as decimal number
696 // E.g. <level> 31 corresponds to H.264 level 3.1
697 // See, for example, http://qtdevseed.apple.com/qadrift/testcases/tc-0133.php
698 uint32_t level_start = 0;
700 if (base::StartsWith(codec_id, "avc1.66.", base::CompareCase::SENSITIVE)) {
702 result = "avc1.4200";
703 } else if (base::StartsWith(codec_id, "avc1.77.",
704 base::CompareCase::SENSITIVE)) {
706 result = "avc1.4D00";
707 } else if (base::StartsWith(codec_id, "avc1.100.",
708 base::CompareCase::SENSITIVE)) {
710 result = "avc1.6400";
714 if (level_start > 0 &&
715 base::StringToUint(codec_id.substr(level_start), &level) && level < 256) {
716 // This is a valid legacy avc1 codec id - return the codec id translated
717 // into RFC 6381 format.
718 base::AppendHexEncodedByte(static_cast<uint8_t>(level), result);
722 // This is not a valid legacy avc1 codec id - return the original codec id.
723 return std::string(codec_id);
727 #if BUILDFLAG(ENABLE_PLATFORM_HEVC)
728 // The specification for HEVC codec id strings can be found in ISO IEC 14496-15
729 // dated 2012 or newer in the Annex E.3
730 bool ParseHEVCCodecId(base::StringPiece codec_id,
731 VideoCodecProfile* profile,
732 uint8_t* level_idc) {
733 if (!base::StartsWith(codec_id, "hev1.", base::CompareCase::SENSITIVE) &&
734 !base::StartsWith(codec_id, "hvc1.", base::CompareCase::SENSITIVE)) {
738 // HEVC codec id consists of:
739 const int kMaxHevcCodecIdLength =
740 5 + // 'hev1.' or 'hvc1.' prefix (5 chars)
741 4 + // profile, e.g. '.A12' (max 4 chars)
742 9 + // profile_compatibility, dot + 32-bit hex number (max 9 chars)
743 5 + // tier and level, e.g. '.H120' (max 5 chars)
744 18; // up to 6 constraint bytes, bytes are dot-separated and hex-encoded.
746 if (codec_id.size() > kMaxHevcCodecIdLength) {
747 DVLOG(4) << __func__ << ": Codec id is too long (" << codec_id << ")";
751 std::vector<std::string> elem = base::SplitString(
752 codec_id, ".", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
753 DCHECK(elem[0] == "hev1" || elem[0] == "hvc1");
755 if (elem.size() < 4) {
756 DVLOG(4) << __func__ << ": invalid HEVC codec id " << codec_id;
760 uint8_t general_profile_space = 0;
761 if (elem[1].size() > 0 &&
762 (elem[1][0] == 'A' || elem[1][0] == 'B' || elem[1][0] == 'C')) {
763 general_profile_space = 1 + (elem[1][0] - 'A');
766 DCHECK(general_profile_space >= 0 && general_profile_space <= 3);
768 unsigned general_profile_idc = 0;
769 if (!base::StringToUint(elem[1], &general_profile_idc) ||
770 general_profile_idc > 0x1f) {
771 DVLOG(4) << __func__ << ": invalid general_profile_idc=" << elem[1];
775 uint32_t general_profile_compatibility_flags = 0;
776 if (!base::HexStringToUInt(elem[2], &general_profile_compatibility_flags)) {
778 << ": invalid general_profile_compatibility_flags=" << elem[2];
782 VideoCodecProfile out_profile = VIDEO_CODEC_PROFILE_UNKNOWN;
784 if (general_profile_idc == 11 ||
785 (general_profile_compatibility_flags & 2048)) {
786 out_profile = HEVCPROFILE_HIGH_THROUGHPUT_SCREEN_EXTENDED;
789 if (general_profile_idc == 10 ||
790 (general_profile_compatibility_flags & 1024)) {
791 out_profile = HEVCPROFILE_SCALABLE_REXT;
794 if (general_profile_idc == 9 || (general_profile_compatibility_flags & 512)) {
795 out_profile = HEVCPROFILE_SCREEN_EXTENDED;
798 if (general_profile_idc == 8 || (general_profile_compatibility_flags & 256)) {
799 out_profile = HEVCPROFILE_3D_MAIN;
802 if (general_profile_idc == 7 || (general_profile_compatibility_flags & 128)) {
803 out_profile = HEVCPROFILE_SCALABLE_MAIN;
806 if (general_profile_idc == 6 || (general_profile_compatibility_flags & 64)) {
807 out_profile = HEVCPROFILE_MULTIVIEW_MAIN;
810 if (general_profile_idc == 5 || (general_profile_compatibility_flags & 32)) {
811 out_profile = HEVCPROFILE_HIGH_THROUGHPUT;
814 if (general_profile_idc == 4 || (general_profile_compatibility_flags & 16)) {
815 out_profile = HEVCPROFILE_REXT;
818 // NOTICE: Do not change the order of below sections
819 if (general_profile_idc == 2 || (general_profile_compatibility_flags & 4)) {
820 out_profile = HEVCPROFILE_MAIN10;
823 // When general_profile_compatibility_flag[1] is equal to 1,
824 // general_profile_compatibility_flag[2] should be equal to 1 as well.
825 if (general_profile_idc == 1 || (general_profile_compatibility_flags & 2)) {
826 out_profile = HEVCPROFILE_MAIN;
829 // When general_profile_compatibility_flag[3] is equal to 1,
830 // general_profile_compatibility_flag[1] and
831 // general_profile_compatibility_flag[2] should be equal to 1 as well.
832 if (general_profile_idc == 3 || (general_profile_compatibility_flags & 8)) {
833 out_profile = HEVCPROFILE_MAIN_STILL_PICTURE;
836 if (out_profile == VIDEO_CODEC_PROFILE_UNKNOWN) {
837 DVLOG(1) << "Warning: unrecognized HEVC/H.265 general_profile_idc: "
838 << general_profile_idc << ", general_profile_compatibility_flags: "
839 << general_profile_compatibility_flags;
844 *profile = out_profile;
846 uint8_t general_tier_flag;
847 if (elem[3].size() > 0 && (elem[3][0] == 'L' || elem[3][0] == 'H')) {
848 general_tier_flag = (elem[3][0] == 'L') ? 0 : 1;
851 DVLOG(4) << __func__ << ": invalid general_tier_flag=" << elem[3];
854 DCHECK(general_tier_flag == 0 || general_tier_flag == 1);
856 unsigned general_level_idc = 0;
857 if (!base::StringToUint(elem[3], &general_level_idc) ||
858 general_level_idc > 0xff) {
859 DVLOG(4) << __func__ << ": invalid general_level_idc=" << elem[3];
864 *level_idc = static_cast<uint8_t>(general_level_idc);
866 uint8_t constraint_flags[6];
867 memset(constraint_flags, 0, sizeof(constraint_flags));
869 if (elem.size() > 10) {
870 DVLOG(4) << __func__ << ": unexpected number of trailing bytes in HEVC "
871 << "codec id " << codec_id;
874 for (size_t i = 4; i < elem.size(); ++i) {
875 unsigned constr_byte = 0;
876 if (!base::HexStringToUInt(elem[i], &constr_byte) || constr_byte > 0xFF) {
877 DVLOG(4) << __func__ << ": invalid constraint byte=" << elem[i];
880 constraint_flags[i - 4] = constr_byte;
887 #if BUILDFLAG(ENABLE_PLATFORM_VVC)
888 // The specification for VVC codec id strings can be found in ISO/IEC 14496-15
890 // In detail it would be:
891 // <sample entry FourCC> ("vvi1: if config is inband, or "vvc1" otherwise.)
892 // .<general_profile_idc> (base10)
893 // .<general_tier_flag> ("L" or "H")
894 // <op_level_idc> (base10. <= general_level_idc in SPS)
895 // .C<ptl_frame_only_constraint_flag><ptl_multi_layer_enabled_flag> (optional)
896 // <general_constraint_info) (base32 with "=" might be omitted.)
897 // .S<general_sub_profile_idc1> (Optional, base32 with "=" might be omitted.)
898 // <+general_sub_profile_
899 // .O<ols_idx>+<max_tid> (Optional, base10 OlsIdx & MaxTid)
900 bool ParseVVCCodecId(base::StringPiece codec_id,
901 VideoCodecProfile* profile,
902 uint8_t* level_idc) {
903 if (!base::StartsWith(codec_id, "vvc1.", base::CompareCase::SENSITIVE) &&
904 !base::StartsWith(codec_id, "vvi1.", base::CompareCase::SENSITIVE)) {
908 std::vector<std::string> elem = base::SplitString(
909 codec_id, ".", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
910 DCHECK(elem[0] == "vvc1" || elem[0] == "vvi1");
912 if (elem.size() < 3 || elem.size() > 6) {
913 DVLOG(4) << __func__ << ": invalid VVC codec id " << codec_id;
917 for (auto& item : elem) {
918 if (item.size() < 1 ||
919 ((item[0] == 'C' || item[0] == 'S' || item[0] == 'O') &&
921 DVLOG(4) << __func__ << ": subelement of VVC codec id invalid.";
924 if (item[0] == 'O' && item.back() == '+') {
925 DVLOG(4) << __func__ << ": invalid OlxIdx and MaxTid string.";
930 unsigned general_profile_idc = 0;
931 if (!base::StringToUint(elem[1], &general_profile_idc) ||
932 general_profile_idc > 0x63) {
933 DVLOG(4) << __func__ << ": invalid general_profile_idc=" << elem[1];
937 VideoCodecProfile out_profile = VIDEO_CODEC_PROFILE_UNKNOWN;
938 switch (general_profile_idc) {
939 case 99: // Spec A.3.5
940 out_profile = VVCPROFILE_MAIN16_444_STILL_PICTURE;
942 case 98: // Spec A.3.5
943 out_profile = VVCPROFILE_MAIN12_444_STILL_PICTURE;
945 case 97: // Spec A.3.2
946 out_profile = VVCPROFILE_MAIN10_444_STILL_PICTURE;
948 case 66: // Spec A.3.5
949 out_profile = VVCPROFILE_MAIN12_STILL_PICTURE;
951 case 65: // Spec A.3.1
952 out_profile = VVCPROFILE_MAIN10_STILL_PICTURE;
954 case 49: // Spec A.3.4
955 out_profile = VVCPROFILE_MULTILAYER_MAIN10_444;
957 case 43: // Spec A.3.5
958 out_profile = VVCPROFILE_MAIN16_444_INTRA;
960 case 42: // Spec A.3.5
961 out_profile = VVCPROFILE_MAIN12_444_INTRA;
963 case 35: // Spec A.3.5
964 out_profile = VVCPROFILE_MAIN16_444;
966 case 34: // Spec A.3.5
967 out_profile = VVCPROFILE_MAIN12_444;
969 case 33: // Spec A.3.2
970 out_profile = VVCPROFILE_MAIN10_444;
972 case 17: // Spec A.3.3
973 out_profile = VVCPROIFLE_MULTILAYER_MAIN10;
975 case 10: // Spec A.3.5
976 out_profile = VVCPROFILE_MAIN12_INTRA;
978 case 2: // Spec A.3.5
979 out_profile = VVCPROFILE_MAIN12;
981 case 1: // Spec A.3.1
982 out_profile = VVCPROFILE_MAIN10;
988 if (out_profile == VIDEO_CODEC_PROFILE_UNKNOWN) {
989 DVLOG(1) << "Warning: unrecognized VVC/H.266 general_profile_idc: "
990 << general_profile_idc;
995 *profile = out_profile;
998 uint8_t general_tier_flag;
999 if (elem[2][0] == 'L' || elem[2][0] == 'H') {
1000 general_tier_flag = (elem[2][0] == 'L') ? 0 : 1;
1001 elem[2].erase(0, 1);
1003 DVLOG(4) << __func__ << ": invalid general_tier_flag=" << elem[2];
1006 DCHECK(general_tier_flag == 0 || general_tier_flag == 1);
1008 unsigned general_level_idc = 0;
1009 if (!base::StringToUint(elem[2], &general_level_idc) ||
1010 general_level_idc > 0xff) {
1011 DVLOG(4) << __func__ << ": invalid general_level_idc=" << elem[2];
1016 *level_idc = static_cast<uint8_t>(general_level_idc);
1019 // C-string, if existing, should proceed S-string and O-string.
1020 // Similarly, S-string should proceed O-string.
1021 bool trailing_valid = true;
1022 if (elem.size() == 4) {
1023 if (elem[3][0] != 'C' && elem[3][0] != 'S' && elem[3][0] != 'O') {
1024 trailing_valid = false;
1026 } else if (elem.size() == 5) {
1027 if (!((elem[3][0] == 'C' && elem[4][0] == 'S') ||
1028 (elem[3][0] == 'C' && elem[4][0] == 'O') ||
1029 (elem[3][0] == 'S' && elem[4][0] == 'O'))) {
1030 trailing_valid = false;
1032 } else if (elem.size() == 6) {
1033 if (elem[3][0] != 'C' || elem[4][0] != 'S' || elem[5][0] != 'O') {
1034 trailing_valid = false;
1038 if (!trailing_valid) {
1039 DVLOG(4) << __func__ << ": invalid traing codec string.";
1047 #if BUILDFLAG(ENABLE_PLATFORM_DOLBY_VISION)
1048 bool IsDolbyVisionAVCCodecId(base::StringPiece codec_id) {
1049 return base::StartsWith(codec_id, "dva1.", base::CompareCase::SENSITIVE) ||
1050 base::StartsWith(codec_id, "dvav.", base::CompareCase::SENSITIVE);
1053 bool IsDolbyVisionHEVCCodecId(base::StringPiece codec_id) {
1054 return base::StartsWith(codec_id, "dvh1.", base::CompareCase::SENSITIVE) ||
1055 base::StartsWith(codec_id, "dvhe.", base::CompareCase::SENSITIVE);
1058 // The specification for Dolby Vision codec id strings can be found in Dolby
1059 // Vision streams within the MPEG-DASH format:
1060 // https://professional.dolby.com/siteassets/content-creation/dolby-vision-for-content-creators/dolbyvisioninmpegdashspecification_v2_0_public_20190107.pdf
1061 bool ParseDolbyVisionCodecId(base::StringPiece codec_id,
1062 VideoCodecProfile* profile,
1063 uint8_t* level_idc) {
1064 if (!IsDolbyVisionAVCCodecId(codec_id) &&
1065 !IsDolbyVisionHEVCCodecId(codec_id)) {
1069 const int kMaxDvCodecIdLength = 5 // FOURCC string
1070 + 1 // delimiting period
1071 + 2 // profile id as 2 digit string
1072 + 1 // delimiting period
1073 + 2; // level id as 2 digit string.
1075 if (codec_id.size() > kMaxDvCodecIdLength) {
1076 DVLOG(4) << __func__ << ": Codec id is too long (" << codec_id << ")";
1080 std::vector<std::string> elem = base::SplitString(
1081 codec_id, ".", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
1082 DCHECK(elem[0] == "dvh1" || elem[0] == "dvhe" || elem[0] == "dva1" ||
1085 if (elem.size() != 3) {
1086 DVLOG(4) << __func__ << ": invalid dolby vision codec id " << codec_id;
1090 // Profile string should be two digits.
1091 unsigned profile_id = 0;
1092 if (elem[1].size() != 2 || !base::StringToUint(elem[1], &profile_id) ||
1094 DVLOG(4) << __func__ << ": invalid format or profile_id=" << elem[1];
1098 // Only profiles 0, 4, 5, 7, 8 and 9 are valid. Profile 0 and 9 are encoded
1099 // based on AVC while profile 4, 5, 7 and 8 are based on HEVC.
1100 switch (profile_id) {
1103 if (!IsDolbyVisionAVCCodecId(codec_id)) {
1104 DVLOG(4) << __func__
1105 << ": codec id is mismatched with profile_id=" << profile_id;
1108 if (profile_id == 0)
1109 *profile = DOLBYVISION_PROFILE0;
1110 else if (profile_id == 9)
1111 *profile = DOLBYVISION_PROFILE9;
1113 #if BUILDFLAG(ENABLE_PLATFORM_HEVC)
1118 if (!IsDolbyVisionHEVCCodecId(codec_id)) {
1119 DVLOG(4) << __func__
1120 << ": codec id is mismatched with profile_id=" << profile_id;
1123 if (profile_id == 4)
1124 *profile = DOLBYVISION_PROFILE4;
1125 else if (profile_id == 5)
1126 *profile = DOLBYVISION_PROFILE5;
1127 else if (profile_id == 7)
1128 *profile = DOLBYVISION_PROFILE7;
1129 else if (profile_id == 8)
1130 *profile = DOLBYVISION_PROFILE8;
1134 DVLOG(4) << __func__
1135 << ": depecrated and not supported profile_id=" << profile_id;
1139 // Level string should be two digits.
1140 unsigned level_id = 0;
1141 if (elem[2].size() != 2 || !base::StringToUint(elem[2], &level_id) ||
1142 level_id > 13 || level_id < 1) {
1143 DVLOG(4) << __func__ << ": invalid format level_id=" << elem[2];
1147 *level_idc = level_id;
1153 VideoCodec StringToVideoCodec(base::StringPiece codec_id) {
1154 VideoCodec codec = VideoCodec::kUnknown;
1155 VideoCodecProfile profile = VIDEO_CODEC_PROFILE_UNKNOWN;
1157 VideoColorSpace color_space;
1158 ParseCodec(codec_id, codec, profile, level, color_space);
1162 void ParseCodec(base::StringPiece codec_id,
1164 VideoCodecProfile& profile,
1166 VideoColorSpace& color_space) {
1167 std::vector<std::string> elem = base::SplitString(
1168 codec_id, ".", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
1170 codec = VideoCodec::kUnknown;
1174 if (codec_id == "vp8" || codec_id == "vp8.0") {
1175 codec = VideoCodec::kVP8;
1178 if (ParseNewStyleVp9CodecID(codec_id, &profile, &level, &color_space) ||
1179 ParseLegacyVp9CodecID(codec_id, &profile, &level)) {
1180 codec = VideoCodec::kVP9;
1184 #if BUILDFLAG(ENABLE_AV1_DECODER)
1185 if (ParseAv1CodecId(codec_id, &profile, &level, &color_space)) {
1186 codec = VideoCodec::kAV1;
1191 if (codec_id == "theora") {
1192 codec = VideoCodec::kTheora;
1195 if (ParseAVCCodecId(codec_id, &profile, &level)) {
1196 codec = VideoCodec::kH264;
1199 #if BUILDFLAG(ENABLE_MSE_MPEG2TS_STREAM_PARSER) || BUILDFLAG(IS_TIZEN_TV)
1200 if (ParseAVCCodecId(TranslateLegacyAvc1CodecIds(codec_id), &profile,
1202 codec = VideoCodec::kH264;
1206 #if BUILDFLAG(ENABLE_PLATFORM_HEVC)
1207 if (ParseHEVCCodecId(codec_id, &profile, &level)) {
1208 codec = VideoCodec::kHEVC;
1212 #if BUILDFLAG(ENABLE_PLATFORM_DOLBY_VISION)
1213 if (ParseDolbyVisionCodecId(codec_id, &profile, &level)) {
1214 codec = VideoCodec::kDolbyVision;
1218 codec = VideoCodec::kUnknown;
1221 VideoCodec VideoCodecProfileToVideoCodec(VideoCodecProfile profile) {
1223 case VIDEO_CODEC_PROFILE_UNKNOWN:
1224 return VideoCodec::kUnknown;
1225 case H264PROFILE_BASELINE:
1226 case H264PROFILE_MAIN:
1227 case H264PROFILE_EXTENDED:
1228 case H264PROFILE_HIGH:
1229 case H264PROFILE_HIGH10PROFILE:
1230 case H264PROFILE_HIGH422PROFILE:
1231 case H264PROFILE_HIGH444PREDICTIVEPROFILE:
1232 case H264PROFILE_SCALABLEBASELINE:
1233 case H264PROFILE_SCALABLEHIGH:
1234 case H264PROFILE_STEREOHIGH:
1235 case H264PROFILE_MULTIVIEWHIGH:
1236 return VideoCodec::kH264;
1237 case HEVCPROFILE_MAIN:
1238 case HEVCPROFILE_MAIN10:
1239 case HEVCPROFILE_MAIN_STILL_PICTURE:
1240 case HEVCPROFILE_REXT:
1241 case HEVCPROFILE_HIGH_THROUGHPUT:
1242 case HEVCPROFILE_MULTIVIEW_MAIN:
1243 case HEVCPROFILE_SCALABLE_MAIN:
1244 case HEVCPROFILE_3D_MAIN:
1245 case HEVCPROFILE_SCREEN_EXTENDED:
1246 case HEVCPROFILE_SCALABLE_REXT:
1247 case HEVCPROFILE_HIGH_THROUGHPUT_SCREEN_EXTENDED:
1248 return VideoCodec::kHEVC;
1249 case VP8PROFILE_ANY:
1250 return VideoCodec::kVP8;
1251 case VP9PROFILE_PROFILE0:
1252 case VP9PROFILE_PROFILE1:
1253 case VP9PROFILE_PROFILE2:
1254 case VP9PROFILE_PROFILE3:
1255 return VideoCodec::kVP9;
1256 case DOLBYVISION_PROFILE0:
1257 case DOLBYVISION_PROFILE4:
1258 case DOLBYVISION_PROFILE5:
1259 case DOLBYVISION_PROFILE7:
1260 case DOLBYVISION_PROFILE8:
1261 case DOLBYVISION_PROFILE9:
1262 return VideoCodec::kDolbyVision;
1263 case THEORAPROFILE_ANY:
1264 return VideoCodec::kTheora;
1265 case AV1PROFILE_PROFILE_MAIN:
1266 case AV1PROFILE_PROFILE_HIGH:
1267 case AV1PROFILE_PROFILE_PRO:
1268 return VideoCodec::kAV1;
1269 // TODO(crbugs.com/1417910): Update to VideoCodec::kVVC when
1270 // the production VVC decoder is enabled and corresponding
1271 // enum is allowed to be added.
1272 case VVCPROFILE_MAIN10:
1273 case VVCPROFILE_MAIN12:
1274 case VVCPROFILE_MAIN12_INTRA:
1275 case VVCPROIFLE_MULTILAYER_MAIN10:
1276 case VVCPROFILE_MAIN10_444:
1277 case VVCPROFILE_MAIN12_444:
1278 case VVCPROFILE_MAIN16_444:
1279 case VVCPROFILE_MAIN12_444_INTRA:
1280 case VVCPROFILE_MAIN16_444_INTRA:
1281 case VVCPROFILE_MULTILAYER_MAIN10_444:
1282 case VVCPROFILE_MAIN10_STILL_PICTURE:
1283 case VVCPROFILE_MAIN12_STILL_PICTURE:
1284 case VVCPROFILE_MAIN10_444_STILL_PICTURE:
1285 case VVCPROFILE_MAIN12_444_STILL_PICTURE:
1286 case VVCPROFILE_MAIN16_444_STILL_PICTURE:
1287 return VideoCodec::kUnknown;
1291 std::ostream& operator<<(std::ostream& os, const VideoCodec& codec) {
1292 return os << GetCodecName(codec);
1295 } // namespace media