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:
47 NOTREACHED_NORETURN();
50 // Reported as part of some UMA names. NEVER change existing strings!
51 std::string GetCodecNameForUMA(VideoCodec codec) {
53 case VideoCodec::kUnknown:
55 case VideoCodec::kH264:
57 case VideoCodec::kHEVC:
59 case VideoCodec::kDolbyVision:
61 case VideoCodec::kVC1:
63 case VideoCodec::kMPEG2:
65 case VideoCodec::kMPEG4:
67 case VideoCodec::kTheora:
69 case VideoCodec::kVP8:
71 case VideoCodec::kVP9:
73 case VideoCodec::kAV1:
76 NOTREACHED_NORETURN();
79 std::string GetProfileName(VideoCodecProfile profile) {
81 case VIDEO_CODEC_PROFILE_UNKNOWN:
83 case H264PROFILE_BASELINE:
84 return "h264 baseline";
85 case H264PROFILE_MAIN:
87 case H264PROFILE_EXTENDED:
88 return "h264 extended";
89 case H264PROFILE_HIGH:
91 case H264PROFILE_HIGH10PROFILE:
92 return "h264 high 10";
93 case H264PROFILE_HIGH422PROFILE:
94 return "h264 high 4:2:2";
95 case H264PROFILE_HIGH444PREDICTIVEPROFILE:
96 return "h264 high 4:4:4 predictive";
97 case H264PROFILE_SCALABLEBASELINE:
98 return "h264 scalable baseline";
99 case H264PROFILE_SCALABLEHIGH:
100 return "h264 scalable high";
101 case H264PROFILE_STEREOHIGH:
102 return "h264 stereo high";
103 case H264PROFILE_MULTIVIEWHIGH:
104 return "h264 multiview high";
105 case HEVCPROFILE_MAIN:
107 case HEVCPROFILE_MAIN10:
108 return "hevc main 10";
109 case HEVCPROFILE_MAIN_STILL_PICTURE:
110 return "hevc main still-picture";
111 case HEVCPROFILE_REXT:
112 return "hevc range extensions";
113 case HEVCPROFILE_HIGH_THROUGHPUT:
114 return "hevc high throughput";
115 case HEVCPROFILE_MULTIVIEW_MAIN:
116 return "hevc multiview main";
117 case HEVCPROFILE_SCALABLE_MAIN:
118 return "hevc scalable main";
119 case HEVCPROFILE_3D_MAIN:
120 return "hevc 3d main";
121 case HEVCPROFILE_SCREEN_EXTENDED:
122 return "hevc screen extended";
123 case HEVCPROFILE_SCALABLE_REXT:
124 return "hevc scalable range extensions";
125 case HEVCPROFILE_HIGH_THROUGHPUT_SCREEN_EXTENDED:
126 return "hevc high throughput screen extended";
129 case VP9PROFILE_PROFILE0:
130 return "vp9 profile0";
131 case VP9PROFILE_PROFILE1:
132 return "vp9 profile1";
133 case VP9PROFILE_PROFILE2:
134 return "vp9 profile2";
135 case VP9PROFILE_PROFILE3:
136 return "vp9 profile3";
137 case DOLBYVISION_PROFILE0:
138 return "dolby vision profile 0";
139 case DOLBYVISION_PROFILE4:
140 return "dolby vision profile 4";
141 case DOLBYVISION_PROFILE5:
142 return "dolby vision profile 5";
143 case DOLBYVISION_PROFILE7:
144 return "dolby vision profile 7";
145 case DOLBYVISION_PROFILE8:
146 return "dolby vision profile 8";
147 case DOLBYVISION_PROFILE9:
148 return "dolby vision profile 9";
149 case THEORAPROFILE_ANY:
151 case AV1PROFILE_PROFILE_MAIN:
152 return "av1 profile main";
153 case AV1PROFILE_PROFILE_HIGH:
154 return "av1 profile high";
155 case AV1PROFILE_PROFILE_PRO:
156 return "av1 profile pro";
157 case VVCPROFILE_MAIN10:
158 return "vvc profile main10";
159 case VVCPROFILE_MAIN12:
160 return "vvc profile main12";
161 case VVCPROFILE_MAIN12_INTRA:
162 return "vvc profile main12 intra";
163 case VVCPROIFLE_MULTILAYER_MAIN10:
164 return "vvc profile multilayer main10";
165 case VVCPROFILE_MAIN10_444:
166 return "vvc profile main10 444";
167 case VVCPROFILE_MAIN12_444:
168 return "vvc profile main12 444";
169 case VVCPROFILE_MAIN16_444:
170 return "vvc profile main16 444";
171 case VVCPROFILE_MAIN12_444_INTRA:
172 return "vvc profile main12 444 intra";
173 case VVCPROFILE_MAIN16_444_INTRA:
174 return "vvc profile main16 444 intra";
175 case VVCPROFILE_MULTILAYER_MAIN10_444:
176 return "vvc profile multilayer main10 444";
177 case VVCPROFILE_MAIN10_STILL_PICTURE:
178 return "vvc profile main10 still picture";
179 case VVCPROFILE_MAIN12_STILL_PICTURE:
180 return "vvc profile main12 still picture";
181 case VVCPROFILE_MAIN10_444_STILL_PICTURE:
182 return "vvc profile main10 444 still picture";
183 case VVCPROFILE_MAIN12_444_STILL_PICTURE:
184 return "vvc profile main12 444 still picture";
185 case VVCPROFILE_MAIN16_444_STILL_PICTURE:
186 return "vvc profile main16 444 still picture";
188 NOTREACHED_NORETURN();
191 std::string BuildH264MimeSuffix(media::VideoCodecProfile profile,
193 std::string profile_str;
195 case media::VideoCodecProfile::H264PROFILE_BASELINE:
198 case media::VideoCodecProfile::H264PROFILE_MAIN:
201 case media::VideoCodecProfile::H264PROFILE_SCALABLEBASELINE:
204 case media::VideoCodecProfile::H264PROFILE_SCALABLEHIGH:
207 case media::VideoCodecProfile::H264PROFILE_EXTENDED:
210 case media::VideoCodecProfile::H264PROFILE_HIGH:
213 case media::VideoCodecProfile::H264PROFILE_HIGH10PROFILE:
216 case media::VideoCodecProfile::H264PROFILE_MULTIVIEWHIGH:
219 case media::VideoCodecProfile::H264PROFILE_HIGH422PROFILE:
222 case media::VideoCodecProfile::H264PROFILE_STEREOHIGH:
225 case media::VideoCodecProfile::H264PROFILE_HIGH444PREDICTIVEPROFILE:
232 return base::StringPrintf(".%s%04x", profile_str.c_str(), level);
235 bool ParseNewStyleVp9CodecID(base::StringPiece codec_id,
236 VideoCodecProfile* profile,
238 VideoColorSpace* color_space) {
239 // Initialize optional fields to their defaults.
240 *color_space = VideoColorSpace::REC709();
242 std::vector<std::string> fields = base::SplitString(
243 codec_id, ".", base::KEEP_WHITESPACE, base::SPLIT_WANT_ALL);
245 // First four fields are mandatory. No more than 9 fields are expected.
246 if (fields.size() < 4 || fields.size() > 9) {
247 DVLOG(3) << __func__ << " Invalid number of fields (" << fields.size()
252 if (fields[0] != "vp09") {
253 DVLOG(3) << __func__ << " Invalid 4CC (" << fields[0] << ")";
257 std::vector<int> values;
258 for (size_t i = 1; i < fields.size(); ++i) {
259 // Missing value is not allowed.
260 if (fields[i] == "") {
261 DVLOG(3) << __func__ << " Invalid missing field (position:" << i << ")";
265 if (!base::StringToInt(fields[i], &value) || value < 0) {
266 DVLOG(3) << __func__ << " Invalid field value (" << value << ")";
269 values.push_back(value);
272 const int profile_idc = values[0];
273 switch (profile_idc) {
275 *profile = VP9PROFILE_PROFILE0;
278 *profile = VP9PROFILE_PROFILE1;
281 *profile = VP9PROFILE_PROFILE2;
284 *profile = VP9PROFILE_PROFILE3;
287 DVLOG(3) << __func__ << " Invalid profile (" << profile_idc << ")";
291 *level_idc = values[1];
292 switch (*level_idc) {
309 DVLOG(3) << __func__ << " Invalid level (" << *level_idc << ")";
313 const int bit_depth = values[2];
314 if (bit_depth != 8 && bit_depth != 10 && bit_depth != 12) {
315 DVLOG(3) << __func__ << " Invalid bit-depth (" << bit_depth << ")";
319 if (values.size() < 4)
321 const int chroma_subsampling = values[3];
322 if (chroma_subsampling > 3) {
323 DVLOG(3) << __func__ << " Invalid chroma subsampling ("
324 << chroma_subsampling << ")";
328 if (values.size() < 5)
330 color_space->primaries = VideoColorSpace::GetPrimaryID(values[4]);
331 if (color_space->primaries == VideoColorSpace::PrimaryID::INVALID) {
332 DVLOG(3) << __func__ << " Invalid color primaries (" << values[4] << ")";
336 if (values.size() < 6)
338 color_space->transfer = VideoColorSpace::GetTransferID(values[5]);
339 if (color_space->transfer == VideoColorSpace::TransferID::INVALID) {
340 DVLOG(3) << __func__ << " Invalid transfer function (" << values[5] << ")";
344 if (values.size() < 7)
346 color_space->matrix = VideoColorSpace::GetMatrixID(values[6]);
347 if (color_space->matrix == VideoColorSpace::MatrixID::INVALID) {
348 DVLOG(3) << __func__ << " Invalid matrix coefficients (" << values[6]
352 if (color_space->matrix == VideoColorSpace::MatrixID::RGB &&
353 chroma_subsampling != 3) {
354 DVLOG(3) << __func__ << " Invalid combination of chroma_subsampling ("
355 << ") and matrix coefficients (" << values[6] << ")";
358 if (values.size() < 8)
360 const int video_full_range_flag = values[7];
361 if (video_full_range_flag > 1) {
362 DVLOG(3) << __func__ << " Invalid full range flag ("
363 << video_full_range_flag << ")";
366 color_space->range = video_full_range_flag == 1
367 ? gfx::ColorSpace::RangeID::FULL
368 : gfx::ColorSpace::RangeID::LIMITED;
373 bool ParseLegacyVp9CodecID(base::StringPiece codec_id,
374 VideoCodecProfile* profile,
375 uint8_t* level_idc) {
376 if (codec_id == "vp9" || codec_id == "vp9.0") {
377 // Profile is not included in the codec string. Consumers of parsed codec
378 // should handle by rejecting ambiguous string or resolving to a default
380 *profile = VIDEO_CODEC_PROFILE_UNKNOWN;
381 // Use 0 to indicate unknown level.
388 #if BUILDFLAG(ENABLE_AV1_DECODER)
389 bool ParseAv1CodecId(base::StringPiece codec_id,
390 VideoCodecProfile* profile,
392 VideoColorSpace* color_space) {
393 // The codecs parameter string for the AOM AV1 codec is as follows:
394 // See https://aomediacodec.github.io/av1-isobmff/#codecsparam.
396 // <sample entry4CC>.<profile>.<level><tier>.<bitDepth>.<monochrome>.
397 // <chromaSubsampling>.<colorPrimaries>.<transferCharacteristics>.
398 // <matrixCoefficients>.<videoFullRangeFlag>
400 std::vector<std::string> fields = base::SplitString(
401 codec_id, ".", base::KEEP_WHITESPACE, base::SPLIT_WANT_ALL);
403 // The parameters sample entry 4CC, profile, level, tier, and bitDepth are all
404 // mandatory fields. If any of these fields are empty, or not within their
405 // allowed range, the processing device SHOULD treat it as an error.
406 if (fields.size() < 4 || fields.size() > 10) {
407 DVLOG(3) << __func__ << " Invalid number of fields (" << fields.size()
412 // All the other fields (including their leading '.') are optional, mutually
413 // inclusive (all or none) fields. If not specified then the values listed in
414 // the table below are assumed.
417 // chromaSubsampling 112 (4:2:0 colocated with luma (0,0))
418 // colorPrimaries 1 (ITU-R BT.709)
419 // transferCharacteristics 1 (ITU-R BT.709)
420 // matrixCoefficients 1 (ITU-R BT.709)
421 // videoFullRangeFlag 0 (studio swing representation)
422 *color_space = VideoColorSpace::REC709();
424 if (fields[0] != "av01") {
425 DVLOG(3) << __func__ << " Invalid AV1 4CC (" << fields[0] << ")";
429 // The level parameter value SHALL equal the first level value indicated by
430 // seq_level_idx in the Sequence Header. The tier parameter value SHALL be
431 // equal to M when the first seq_tier value in the Sequence Header is equal to
432 // 0, and H when it is equal to 1.
433 if (fields[2].size() != 3 || (fields[2][2] != 'M' && fields[2][2] != 'H')) {
434 DVLOG(3) << __func__ << " Invalid level+tier (" << fields[2] << ")";
438 // Since tier has been validated, strip the trailing tier indicator to allow
439 // int conversion below.
442 // Fill with dummy values to ensure parallel indices with fields.
443 std::vector<int> values(fields.size(), 0);
444 for (size_t i = 1; i < fields.size(); ++i) {
445 if (fields[i].empty()) {
446 DVLOG(3) << __func__ << " Invalid empty field (position:" << i << ")";
450 if (!base::StringToInt(fields[i], &values[i]) || values[i] < 0) {
451 DVLOG(3) << __func__ << " Invalid field value (" << values[i] << ")";
456 // The profile parameter value, represented by a single digit decimal, SHALL
457 // equal the value of seq_profile in the Sequence Header.
458 const int profile_idc = fields[1].size() == 1 ? values[1] : -1;
459 switch (profile_idc) {
461 *profile = AV1PROFILE_PROFILE_MAIN;
464 *profile = AV1PROFILE_PROFILE_HIGH;
467 *profile = AV1PROFILE_PROFILE_PRO;
470 DVLOG(3) << __func__ << " Invalid profile (" << fields[1] << ")";
474 // The level parameter value SHALL equal the first level value indicated by
475 // seq_level_idx in the Sequence Header. Note: We validate that this field has
476 // the required leading zeros above.
477 *level_idc = values[2];
478 if (*level_idc > 31) {
479 DVLOG(3) << __func__ << " Invalid level (" << *level_idc << ")";
483 // The bitDepth parameter value SHALL equal the value of BitDepth variable as
484 // defined in [AV1] derived from the Sequence Header. Leading zeros required.
485 const int bit_depth = values[3];
486 if (fields[3].size() != 2 ||
487 (bit_depth != 8 && bit_depth != 10 && bit_depth != 12)) {
488 DVLOG(3) << __func__ << " Invalid bit-depth (" << fields[3] << ")";
492 if (values.size() <= 4)
495 // The monochrome parameter value, represented by a single digit decimal,
496 // SHALL equal the value of mono_chrome in the Sequence Header.
497 const int monochrome = values[4];
498 if (fields[4].size() != 1 || monochrome > 1) {
499 DVLOG(3) << __func__ << " Invalid monochrome (" << fields[4] << ")";
503 if (values.size() <= 5)
506 // The chromaSubsampling parameter value, represented by a three-digit
507 // decimal, SHALL have its first digit equal to subsampling_x and its second
508 // digit equal to subsampling_y. If both subsampling_x and subsampling_y are
509 // set to 1, then the third digit SHALL be equal to chroma_sample_position,
510 // otherwise it SHALL be set to 0.
511 if (fields[5].size() != 3) {
512 DVLOG(3) << __func__ << " Invalid chroma subsampling (" << fields[5] << ")";
516 const char subsampling_x = fields[5][0];
517 const char subsampling_y = fields[5][1];
518 const char chroma_sample_position = fields[5][2];
519 if ((subsampling_x < '0' || subsampling_x > '1') ||
520 (subsampling_y < '0' || subsampling_y > '1') ||
521 (chroma_sample_position < '0' || chroma_sample_position > '3')) {
522 DVLOG(3) << __func__ << " Invalid chroma subsampling (" << fields[5] << ")";
526 if (((subsampling_x == '0' || subsampling_y == '0') &&
527 chroma_sample_position != '0')) {
528 DVLOG(3) << __func__ << " Invalid chroma subsampling (" << fields[5] << ")";
532 if (values.size() <= 6)
535 // The colorPrimaries, transferCharacteristics, matrixCoefficients and
536 // videoFullRangeFlag parameter values SHALL equal the value of matching
537 // fields in the Sequence Header, if color_description_present_flag is set to
538 // 1, otherwise they SHOULD not be set, defaulting to the values below. The
539 // videoFullRangeFlag is represented by a single digit.
540 color_space->primaries = VideoColorSpace::GetPrimaryID(values[6]);
541 if (fields[6].size() != 2 ||
542 color_space->primaries == VideoColorSpace::PrimaryID::INVALID) {
543 DVLOG(3) << __func__ << " Invalid color primaries (" << fields[6] << ")";
547 if (values.size() <= 7)
550 color_space->transfer = VideoColorSpace::GetTransferID(values[7]);
551 if (fields[7].size() != 2 ||
552 color_space->transfer == VideoColorSpace::TransferID::INVALID) {
553 DVLOG(3) << __func__ << " Invalid transfer function (" << fields[7] << ")";
557 if (values.size() <= 8)
560 color_space->matrix = VideoColorSpace::GetMatrixID(values[8]);
561 if (fields[8].size() != 2 ||
562 color_space->matrix == VideoColorSpace::MatrixID::INVALID) {
563 // TODO(dalecurtis): AV1 allows a few matrices we don't support yet.
564 // https://crbug.com/854290
565 if (values[8] == 12 || values[8] == 13 || values[8] == 14) {
566 DVLOG(3) << __func__ << " Unsupported matrix coefficients (" << fields[8]
569 DVLOG(3) << __func__ << " Invalid matrix coefficients (" << fields[8]
575 if (values.size() <= 9)
578 const int video_full_range_flag = values[9];
579 if (fields[9].size() != 1 || video_full_range_flag > 1) {
580 DVLOG(3) << __func__ << " Invalid full range flag (" << fields[9] << ")";
583 color_space->range = video_full_range_flag == 1
584 ? gfx::ColorSpace::RangeID::FULL
585 : gfx::ColorSpace::RangeID::LIMITED;
589 #endif // BUILDFLAG(ENABLE_AV1_DECODER)
591 bool ParseAVCCodecId(base::StringPiece codec_id,
592 VideoCodecProfile* profile,
593 uint8_t* level_idc) {
594 // Make sure we have avc1.xxxxxx or avc3.xxxxxx , where xxxxxx are hex digits
595 if (!base::StartsWith(codec_id, "avc1.", base::CompareCase::SENSITIVE) &&
596 !base::StartsWith(codec_id, "avc3.", base::CompareCase::SENSITIVE)) {
600 if (codec_id.size() != 11 ||
601 !base::HexStringToUInt(base::StringPiece(codec_id).substr(5), &elem)) {
602 DVLOG(4) << __func__ << ": invalid avc codec id (" << codec_id << ")";
606 uint8_t level_byte = elem & 0xFF;
607 uint8_t constraints_byte = (elem >> 8) & 0xFF;
608 uint8_t profile_idc = (elem >> 16) & 0xFF;
610 // Check that the lower two bits of |constraints_byte| are zero (those are
611 // reserved and must be zero according to ISO IEC 14496-10).
612 if (constraints_byte & 3) {
613 DVLOG(4) << __func__ << ": non-zero reserved bits in codec id " << codec_id;
617 VideoCodecProfile out_profile = VIDEO_CODEC_PROFILE_UNKNOWN;
618 // profile_idc values for each profile are taken from ISO IEC 14496-10 and
619 // https://en.wikipedia.org/wiki/H.264/MPEG-4_AVC#Profiles
620 switch (profile_idc) {
622 out_profile = H264PROFILE_BASELINE;
625 out_profile = H264PROFILE_MAIN;
628 out_profile = H264PROFILE_SCALABLEBASELINE;
631 out_profile = H264PROFILE_SCALABLEHIGH;
634 out_profile = H264PROFILE_EXTENDED;
637 out_profile = H264PROFILE_HIGH;
640 out_profile = H264PROFILE_HIGH10PROFILE;
643 out_profile = H264PROFILE_MULTIVIEWHIGH;
646 out_profile = H264PROFILE_HIGH422PROFILE;
649 out_profile = H264PROFILE_STEREOHIGH;
652 out_profile = H264PROFILE_HIGH444PREDICTIVEPROFILE;
655 DVLOG(1) << "Warning: unrecognized AVC/H.264 profile " << profile_idc;
659 // TODO(servolk): Take into account also constraint set flags 3 through 5.
660 uint8_t constraint_set0_flag = (constraints_byte >> 7) & 1;
661 uint8_t constraint_set1_flag = (constraints_byte >> 6) & 1;
662 uint8_t constraint_set2_flag = (constraints_byte >> 5) & 1;
663 if (constraint_set2_flag && out_profile > H264PROFILE_EXTENDED) {
664 out_profile = H264PROFILE_EXTENDED;
666 if (constraint_set1_flag && out_profile > H264PROFILE_MAIN) {
667 out_profile = H264PROFILE_MAIN;
669 if (constraint_set0_flag && out_profile > H264PROFILE_BASELINE) {
670 out_profile = H264PROFILE_BASELINE;
674 *level_idc = level_byte;
677 *profile = out_profile;
682 #if BUILDFLAG(ENABLE_MSE_MPEG2TS_STREAM_PARSER) || BUILDFLAG(IS_TIZEN_TV)
683 std::string TranslateLegacyAvc1CodecIds(base::StringPiece codec_id) {
684 // Special handling for old, pre-RFC 6381 format avc1 strings, which are still
685 // being used by some HLS apps to preserve backward compatibility with older
686 // iOS devices. The old format was avc1.<profile>.<level>
687 // Where <profile> is H.264 profile_idc encoded as a decimal number, i.e.
688 // 66 is baseline profile (0x42)
689 // 77 is main profile (0x4d)
690 // 100 is high profile (0x64)
691 // And <level> is H.264 level multiplied by 10, also encoded as decimal number
692 // E.g. <level> 31 corresponds to H.264 level 3.1
693 // See, for example, http://qtdevseed.apple.com/qadrift/testcases/tc-0133.php
694 uint32_t level_start = 0;
696 if (base::StartsWith(codec_id, "avc1.66.", base::CompareCase::SENSITIVE)) {
698 result = "avc1.4200";
699 } else if (base::StartsWith(codec_id, "avc1.77.",
700 base::CompareCase::SENSITIVE)) {
702 result = "avc1.4D00";
703 } else if (base::StartsWith(codec_id, "avc1.100.",
704 base::CompareCase::SENSITIVE)) {
706 result = "avc1.6400";
710 if (level_start > 0 &&
711 base::StringToUint(codec_id.substr(level_start), &level) && level < 256) {
712 // This is a valid legacy avc1 codec id - return the codec id translated
713 // into RFC 6381 format.
714 base::AppendHexEncodedByte(static_cast<uint8_t>(level), result);
718 // This is not a valid legacy avc1 codec id - return the original codec id.
719 return std::string(codec_id);
723 #if BUILDFLAG(ENABLE_PLATFORM_HEVC)
724 // The specification for HEVC codec id strings can be found in ISO IEC 14496-15
725 // dated 2012 or newer in the Annex E.3
726 bool ParseHEVCCodecId(base::StringPiece codec_id,
727 VideoCodecProfile* profile,
728 uint8_t* level_idc) {
729 if (!base::StartsWith(codec_id, "hev1.", base::CompareCase::SENSITIVE) &&
730 !base::StartsWith(codec_id, "hvc1.", base::CompareCase::SENSITIVE)) {
734 // HEVC codec id consists of:
735 const int kMaxHevcCodecIdLength =
736 5 + // 'hev1.' or 'hvc1.' prefix (5 chars)
737 4 + // profile, e.g. '.A12' (max 4 chars)
738 9 + // profile_compatibility, dot + 32-bit hex number (max 9 chars)
739 5 + // tier and level, e.g. '.H120' (max 5 chars)
740 18; // up to 6 constraint bytes, bytes are dot-separated and hex-encoded.
742 if (codec_id.size() > kMaxHevcCodecIdLength) {
743 DVLOG(4) << __func__ << ": Codec id is too long (" << codec_id << ")";
747 std::vector<std::string> elem = base::SplitString(
748 codec_id, ".", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
749 DCHECK(elem[0] == "hev1" || elem[0] == "hvc1");
751 if (elem.size() < 4) {
752 DVLOG(4) << __func__ << ": invalid HEVC codec id " << codec_id;
756 uint8_t general_profile_space = 0;
757 if (elem[1].size() > 0 &&
758 (elem[1][0] == 'A' || elem[1][0] == 'B' || elem[1][0] == 'C')) {
759 general_profile_space = 1 + (elem[1][0] - 'A');
762 DCHECK(general_profile_space >= 0 && general_profile_space <= 3);
764 unsigned general_profile_idc = 0;
765 if (!base::StringToUint(elem[1], &general_profile_idc) ||
766 general_profile_idc > 0x1f) {
767 DVLOG(4) << __func__ << ": invalid general_profile_idc=" << elem[1];
771 uint32_t general_profile_compatibility_flags = 0;
772 if (!base::HexStringToUInt(elem[2], &general_profile_compatibility_flags)) {
774 << ": invalid general_profile_compatibility_flags=" << elem[2];
778 VideoCodecProfile out_profile = VIDEO_CODEC_PROFILE_UNKNOWN;
780 if (general_profile_idc == 11 ||
781 (general_profile_compatibility_flags & 2048)) {
782 out_profile = HEVCPROFILE_HIGH_THROUGHPUT_SCREEN_EXTENDED;
785 if (general_profile_idc == 10 ||
786 (general_profile_compatibility_flags & 1024)) {
787 out_profile = HEVCPROFILE_SCALABLE_REXT;
790 if (general_profile_idc == 9 || (general_profile_compatibility_flags & 512)) {
791 out_profile = HEVCPROFILE_SCREEN_EXTENDED;
794 if (general_profile_idc == 8 || (general_profile_compatibility_flags & 256)) {
795 out_profile = HEVCPROFILE_3D_MAIN;
798 if (general_profile_idc == 7 || (general_profile_compatibility_flags & 128)) {
799 out_profile = HEVCPROFILE_SCALABLE_MAIN;
802 if (general_profile_idc == 6 || (general_profile_compatibility_flags & 64)) {
803 out_profile = HEVCPROFILE_MULTIVIEW_MAIN;
806 if (general_profile_idc == 5 || (general_profile_compatibility_flags & 32)) {
807 out_profile = HEVCPROFILE_HIGH_THROUGHPUT;
810 if (general_profile_idc == 4 || (general_profile_compatibility_flags & 16)) {
811 out_profile = HEVCPROFILE_REXT;
814 // NOTICE: Do not change the order of below sections
815 if (general_profile_idc == 2 || (general_profile_compatibility_flags & 4)) {
816 out_profile = HEVCPROFILE_MAIN10;
819 // When general_profile_compatibility_flag[1] is equal to 1,
820 // general_profile_compatibility_flag[2] should be equal to 1 as well.
821 if (general_profile_idc == 1 || (general_profile_compatibility_flags & 2)) {
822 out_profile = HEVCPROFILE_MAIN;
825 // When general_profile_compatibility_flag[3] is equal to 1,
826 // general_profile_compatibility_flag[1] and
827 // general_profile_compatibility_flag[2] should be equal to 1 as well.
828 if (general_profile_idc == 3 || (general_profile_compatibility_flags & 8)) {
829 out_profile = HEVCPROFILE_MAIN_STILL_PICTURE;
832 if (out_profile == VIDEO_CODEC_PROFILE_UNKNOWN) {
833 DVLOG(1) << "Warning: unrecognized HEVC/H.265 general_profile_idc: "
834 << general_profile_idc << ", general_profile_compatibility_flags: "
835 << general_profile_compatibility_flags;
840 *profile = out_profile;
842 uint8_t general_tier_flag;
843 if (elem[3].size() > 0 && (elem[3][0] == 'L' || elem[3][0] == 'H')) {
844 general_tier_flag = (elem[3][0] == 'L') ? 0 : 1;
847 DVLOG(4) << __func__ << ": invalid general_tier_flag=" << elem[3];
850 DCHECK(general_tier_flag == 0 || general_tier_flag == 1);
852 unsigned general_level_idc = 0;
853 if (!base::StringToUint(elem[3], &general_level_idc) ||
854 general_level_idc > 0xff) {
855 DVLOG(4) << __func__ << ": invalid general_level_idc=" << elem[3];
860 *level_idc = static_cast<uint8_t>(general_level_idc);
862 uint8_t constraint_flags[6];
863 memset(constraint_flags, 0, sizeof(constraint_flags));
865 if (elem.size() > 10) {
866 DVLOG(4) << __func__ << ": unexpected number of trailing bytes in HEVC "
867 << "codec id " << codec_id;
870 for (size_t i = 4; i < elem.size(); ++i) {
871 unsigned constr_byte = 0;
872 if (!base::HexStringToUInt(elem[i], &constr_byte) || constr_byte > 0xFF) {
873 DVLOG(4) << __func__ << ": invalid constraint byte=" << elem[i];
876 constraint_flags[i - 4] = constr_byte;
883 #if BUILDFLAG(ENABLE_PLATFORM_VVC)
884 // The specification for VVC codec id strings can be found in ISO/IEC 14496-15
886 // In detail it would be:
887 // <sample entry FourCC> ("vvi1: if config is inband, or "vvc1" otherwise.)
888 // .<general_profile_idc> (base10)
889 // .<general_tier_flag> ("L" or "H")
890 // <op_level_idc> (base10. <= general_level_idc in SPS)
891 // .C<ptl_frame_only_constraint_flag><ptl_multi_layer_enabled_flag> (optional)
892 // <general_constraint_info) (base32 with "=" might be omitted.)
893 // .S<general_sub_profile_idc1> (Optional, base32 with "=" might be omitted.)
894 // <+general_sub_profile_
895 // .O<ols_idx>+<max_tid> (Optional, base10 OlsIdx & MaxTid)
896 bool ParseVVCCodecId(base::StringPiece codec_id,
897 VideoCodecProfile* profile,
898 uint8_t* level_idc) {
899 if (!base::StartsWith(codec_id, "vvc1.", base::CompareCase::SENSITIVE) &&
900 !base::StartsWith(codec_id, "vvi1.", base::CompareCase::SENSITIVE)) {
904 std::vector<std::string> elem = base::SplitString(
905 codec_id, ".", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
906 DCHECK(elem[0] == "vvc1" || elem[0] == "vvi1");
908 if (elem.size() < 3 || elem.size() > 6) {
909 DVLOG(4) << __func__ << ": invalid VVC codec id " << codec_id;
913 for (auto& item : elem) {
914 if (item.size() < 1 ||
915 ((item[0] == 'C' || item[0] == 'S' || item[0] == 'O') &&
917 DVLOG(4) << __func__ << ": subelement of VVC codec id invalid.";
920 if (item[0] == 'O' && item.back() == '+') {
921 DVLOG(4) << __func__ << ": invalid OlxIdx and MaxTid string.";
926 unsigned general_profile_idc = 0;
927 if (!base::StringToUint(elem[1], &general_profile_idc) ||
928 general_profile_idc > 0x63) {
929 DVLOG(4) << __func__ << ": invalid general_profile_idc=" << elem[1];
933 VideoCodecProfile out_profile = VIDEO_CODEC_PROFILE_UNKNOWN;
934 switch (general_profile_idc) {
935 case 99: // Spec A.3.5
936 out_profile = VVCPROFILE_MAIN16_444_STILL_PICTURE;
938 case 98: // Spec A.3.5
939 out_profile = VVCPROFILE_MAIN12_444_STILL_PICTURE;
941 case 97: // Spec A.3.2
942 out_profile = VVCPROFILE_MAIN10_444_STILL_PICTURE;
944 case 66: // Spec A.3.5
945 out_profile = VVCPROFILE_MAIN12_STILL_PICTURE;
947 case 65: // Spec A.3.1
948 out_profile = VVCPROFILE_MAIN10_STILL_PICTURE;
950 case 49: // Spec A.3.4
951 out_profile = VVCPROFILE_MULTILAYER_MAIN10_444;
953 case 43: // Spec A.3.5
954 out_profile = VVCPROFILE_MAIN16_444_INTRA;
956 case 42: // Spec A.3.5
957 out_profile = VVCPROFILE_MAIN12_444_INTRA;
959 case 35: // Spec A.3.5
960 out_profile = VVCPROFILE_MAIN16_444;
962 case 34: // Spec A.3.5
963 out_profile = VVCPROFILE_MAIN12_444;
965 case 33: // Spec A.3.2
966 out_profile = VVCPROFILE_MAIN10_444;
968 case 17: // Spec A.3.3
969 out_profile = VVCPROIFLE_MULTILAYER_MAIN10;
971 case 10: // Spec A.3.5
972 out_profile = VVCPROFILE_MAIN12_INTRA;
974 case 2: // Spec A.3.5
975 out_profile = VVCPROFILE_MAIN12;
977 case 1: // Spec A.3.1
978 out_profile = VVCPROFILE_MAIN10;
984 if (out_profile == VIDEO_CODEC_PROFILE_UNKNOWN) {
985 DVLOG(1) << "Warning: unrecognized VVC/H.266 general_profile_idc: "
986 << general_profile_idc;
991 *profile = out_profile;
994 uint8_t general_tier_flag;
995 if (elem[2][0] == 'L' || elem[2][0] == 'H') {
996 general_tier_flag = (elem[2][0] == 'L') ? 0 : 1;
999 DVLOG(4) << __func__ << ": invalid general_tier_flag=" << elem[2];
1002 DCHECK(general_tier_flag == 0 || general_tier_flag == 1);
1004 unsigned general_level_idc = 0;
1005 if (!base::StringToUint(elem[2], &general_level_idc) ||
1006 general_level_idc > 0xff) {
1007 DVLOG(4) << __func__ << ": invalid general_level_idc=" << elem[2];
1012 *level_idc = static_cast<uint8_t>(general_level_idc);
1015 // C-string, if existing, should proceed S-string and O-string.
1016 // Similarly, S-string should proceed O-string.
1017 bool trailing_valid = true;
1018 if (elem.size() == 4) {
1019 if (elem[3][0] != 'C' && elem[3][0] != 'S' && elem[3][0] != 'O') {
1020 trailing_valid = false;
1022 } else if (elem.size() == 5) {
1023 if (!((elem[3][0] == 'C' && elem[4][0] == 'S') ||
1024 (elem[3][0] == 'C' && elem[4][0] == 'O') ||
1025 (elem[3][0] == 'S' && elem[4][0] == 'O'))) {
1026 trailing_valid = false;
1028 } else if (elem.size() == 6) {
1029 if (elem[3][0] != 'C' || elem[4][0] != 'S' || elem[5][0] != 'O') {
1030 trailing_valid = false;
1034 if (!trailing_valid) {
1035 DVLOG(4) << __func__ << ": invalid traing codec string.";
1043 #if BUILDFLAG(ENABLE_PLATFORM_DOLBY_VISION)
1044 bool IsDolbyVisionAVCCodecId(base::StringPiece codec_id) {
1045 return base::StartsWith(codec_id, "dva1.", base::CompareCase::SENSITIVE) ||
1046 base::StartsWith(codec_id, "dvav.", base::CompareCase::SENSITIVE);
1049 bool IsDolbyVisionHEVCCodecId(base::StringPiece codec_id) {
1050 return base::StartsWith(codec_id, "dvh1.", base::CompareCase::SENSITIVE) ||
1051 base::StartsWith(codec_id, "dvhe.", base::CompareCase::SENSITIVE);
1054 // The specification for Dolby Vision codec id strings can be found in Dolby
1055 // Vision streams within the MPEG-DASH format:
1056 // https://professional.dolby.com/siteassets/content-creation/dolby-vision-for-content-creators/dolbyvisioninmpegdashspecification_v2_0_public_20190107.pdf
1057 bool ParseDolbyVisionCodecId(base::StringPiece codec_id,
1058 VideoCodecProfile* profile,
1059 uint8_t* level_idc) {
1060 if (!IsDolbyVisionAVCCodecId(codec_id) &&
1061 !IsDolbyVisionHEVCCodecId(codec_id)) {
1065 const int kMaxDvCodecIdLength = 5 // FOURCC string
1066 + 1 // delimiting period
1067 + 2 // profile id as 2 digit string
1068 + 1 // delimiting period
1069 + 2; // level id as 2 digit string.
1071 if (codec_id.size() > kMaxDvCodecIdLength) {
1072 DVLOG(4) << __func__ << ": Codec id is too long (" << codec_id << ")";
1076 std::vector<std::string> elem = base::SplitString(
1077 codec_id, ".", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
1078 DCHECK(elem[0] == "dvh1" || elem[0] == "dvhe" || elem[0] == "dva1" ||
1081 if (elem.size() != 3) {
1082 DVLOG(4) << __func__ << ": invalid dolby vision codec id " << codec_id;
1086 // Profile string should be two digits.
1087 unsigned profile_id = 0;
1088 if (elem[1].size() != 2 || !base::StringToUint(elem[1], &profile_id) ||
1090 DVLOG(4) << __func__ << ": invalid format or profile_id=" << elem[1];
1094 // Only profiles 0, 4, 5, 7, 8 and 9 are valid. Profile 0 and 9 are encoded
1095 // based on AVC while profile 4, 5, 7 and 8 are based on HEVC.
1096 switch (profile_id) {
1099 if (!IsDolbyVisionAVCCodecId(codec_id)) {
1100 DVLOG(4) << __func__
1101 << ": codec id is mismatched with profile_id=" << profile_id;
1104 if (profile_id == 0)
1105 *profile = DOLBYVISION_PROFILE0;
1106 else if (profile_id == 9)
1107 *profile = DOLBYVISION_PROFILE9;
1109 #if BUILDFLAG(ENABLE_PLATFORM_HEVC)
1114 if (!IsDolbyVisionHEVCCodecId(codec_id)) {
1115 DVLOG(4) << __func__
1116 << ": codec id is mismatched with profile_id=" << profile_id;
1119 if (profile_id == 4)
1120 *profile = DOLBYVISION_PROFILE4;
1121 else if (profile_id == 5)
1122 *profile = DOLBYVISION_PROFILE5;
1123 else if (profile_id == 7)
1124 *profile = DOLBYVISION_PROFILE7;
1125 else if (profile_id == 8)
1126 *profile = DOLBYVISION_PROFILE8;
1130 DVLOG(4) << __func__
1131 << ": depecrated and not supported profile_id=" << profile_id;
1135 // Level string should be two digits.
1136 unsigned level_id = 0;
1137 if (elem[2].size() != 2 || !base::StringToUint(elem[2], &level_id) ||
1138 level_id > 13 || level_id < 1) {
1139 DVLOG(4) << __func__ << ": invalid format level_id=" << elem[2];
1143 *level_idc = level_id;
1149 VideoCodec StringToVideoCodec(base::StringPiece codec_id) {
1150 VideoCodec codec = VideoCodec::kUnknown;
1151 VideoCodecProfile profile = VIDEO_CODEC_PROFILE_UNKNOWN;
1153 VideoColorSpace color_space;
1154 ParseCodec(codec_id, codec, profile, level, color_space);
1158 void ParseCodec(base::StringPiece codec_id,
1160 VideoCodecProfile& profile,
1162 VideoColorSpace& color_space) {
1163 std::vector<std::string> elem = base::SplitString(
1164 codec_id, ".", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
1166 codec = VideoCodec::kUnknown;
1170 if (codec_id == "vp8" || codec_id == "vp8.0") {
1171 codec = VideoCodec::kVP8;
1174 if (ParseNewStyleVp9CodecID(codec_id, &profile, &level, &color_space) ||
1175 ParseLegacyVp9CodecID(codec_id, &profile, &level)) {
1176 codec = VideoCodec::kVP9;
1180 #if BUILDFLAG(ENABLE_AV1_DECODER)
1181 if (ParseAv1CodecId(codec_id, &profile, &level, &color_space)) {
1182 codec = VideoCodec::kAV1;
1187 if (codec_id == "theora") {
1188 codec = VideoCodec::kTheora;
1191 if (ParseAVCCodecId(codec_id, &profile, &level)) {
1192 codec = VideoCodec::kH264;
1195 #if BUILDFLAG(ENABLE_MSE_MPEG2TS_STREAM_PARSER) || BUILDFLAG(IS_TIZEN_TV)
1196 if (ParseAVCCodecId(TranslateLegacyAvc1CodecIds(codec_id), &profile,
1198 codec = VideoCodec::kH264;
1202 #if BUILDFLAG(ENABLE_PLATFORM_HEVC)
1203 if (ParseHEVCCodecId(codec_id, &profile, &level)) {
1204 codec = VideoCodec::kHEVC;
1208 #if BUILDFLAG(ENABLE_PLATFORM_DOLBY_VISION)
1209 if (ParseDolbyVisionCodecId(codec_id, &profile, &level)) {
1210 codec = VideoCodec::kDolbyVision;
1214 codec = VideoCodec::kUnknown;
1217 VideoCodec VideoCodecProfileToVideoCodec(VideoCodecProfile profile) {
1219 case VIDEO_CODEC_PROFILE_UNKNOWN:
1220 return VideoCodec::kUnknown;
1221 case H264PROFILE_BASELINE:
1222 case H264PROFILE_MAIN:
1223 case H264PROFILE_EXTENDED:
1224 case H264PROFILE_HIGH:
1225 case H264PROFILE_HIGH10PROFILE:
1226 case H264PROFILE_HIGH422PROFILE:
1227 case H264PROFILE_HIGH444PREDICTIVEPROFILE:
1228 case H264PROFILE_SCALABLEBASELINE:
1229 case H264PROFILE_SCALABLEHIGH:
1230 case H264PROFILE_STEREOHIGH:
1231 case H264PROFILE_MULTIVIEWHIGH:
1232 return VideoCodec::kH264;
1233 case HEVCPROFILE_MAIN:
1234 case HEVCPROFILE_MAIN10:
1235 case HEVCPROFILE_MAIN_STILL_PICTURE:
1236 case HEVCPROFILE_REXT:
1237 case HEVCPROFILE_HIGH_THROUGHPUT:
1238 case HEVCPROFILE_MULTIVIEW_MAIN:
1239 case HEVCPROFILE_SCALABLE_MAIN:
1240 case HEVCPROFILE_3D_MAIN:
1241 case HEVCPROFILE_SCREEN_EXTENDED:
1242 case HEVCPROFILE_SCALABLE_REXT:
1243 case HEVCPROFILE_HIGH_THROUGHPUT_SCREEN_EXTENDED:
1244 return VideoCodec::kHEVC;
1245 case VP8PROFILE_ANY:
1246 return VideoCodec::kVP8;
1247 case VP9PROFILE_PROFILE0:
1248 case VP9PROFILE_PROFILE1:
1249 case VP9PROFILE_PROFILE2:
1250 case VP9PROFILE_PROFILE3:
1251 return VideoCodec::kVP9;
1252 case DOLBYVISION_PROFILE0:
1253 case DOLBYVISION_PROFILE4:
1254 case DOLBYVISION_PROFILE5:
1255 case DOLBYVISION_PROFILE7:
1256 case DOLBYVISION_PROFILE8:
1257 case DOLBYVISION_PROFILE9:
1258 return VideoCodec::kDolbyVision;
1259 case THEORAPROFILE_ANY:
1260 return VideoCodec::kTheora;
1261 case AV1PROFILE_PROFILE_MAIN:
1262 case AV1PROFILE_PROFILE_HIGH:
1263 case AV1PROFILE_PROFILE_PRO:
1264 return VideoCodec::kAV1;
1265 // TODO(crbugs.com/1417910): Update to VideoCodec::kVVC when
1266 // the production VVC decoder is enabled and corresponding
1267 // enum is allowed to be added.
1268 case VVCPROFILE_MAIN10:
1269 case VVCPROFILE_MAIN12:
1270 case VVCPROFILE_MAIN12_INTRA:
1271 case VVCPROIFLE_MULTILAYER_MAIN10:
1272 case VVCPROFILE_MAIN10_444:
1273 case VVCPROFILE_MAIN12_444:
1274 case VVCPROFILE_MAIN16_444:
1275 case VVCPROFILE_MAIN12_444_INTRA:
1276 case VVCPROFILE_MAIN16_444_INTRA:
1277 case VVCPROFILE_MULTILAYER_MAIN10_444:
1278 case VVCPROFILE_MAIN10_STILL_PICTURE:
1279 case VVCPROFILE_MAIN12_STILL_PICTURE:
1280 case VVCPROFILE_MAIN10_444_STILL_PICTURE:
1281 case VVCPROFILE_MAIN12_444_STILL_PICTURE:
1282 case VVCPROFILE_MAIN16_444_STILL_PICTURE:
1283 return VideoCodec::kUnknown;
1287 std::ostream& operator<<(std::ostream& os, const VideoCodec& codec) {
1288 return os << GetCodecName(codec);
1291 } // namespace media