| Index: media/base/video_codecs.cc
|
| diff --git a/media/base/video_codecs.cc b/media/base/video_codecs.cc
|
| index a2221a35d3dead73d0a14019d165c30116fa7ed3..204b2352c36f3b364afc1abff65816f7bfbb0604 100644
|
| --- a/media/base/video_codecs.cc
|
| +++ b/media/base/video_codecs.cc
|
| @@ -6,6 +6,7 @@
|
|
|
| #include "base/logging.h"
|
| #include "base/strings/string_number_conversions.h"
|
| +#include "base/strings/string_split.h"
|
| #include "base/strings/string_util.h"
|
|
|
| namespace media {
|
| @@ -62,6 +63,12 @@ std::string GetProfileName(VideoCodecProfile profile) {
|
| return "h264 stereo high";
|
| case H264PROFILE_MULTIVIEWHIGH:
|
| return "h264 multiview high";
|
| + case HEVCPROFILE_MAIN:
|
| + return "hevc main";
|
| + case HEVCPROFILE_MAIN10:
|
| + return "hevc main 10";
|
| + case HEVCPROFILE_MAIN_STILL_PICTURE:
|
| + return "hevc main still-picture";
|
| case VP8PROFILE_ANY:
|
| return "vp8";
|
| case VP9PROFILE_PROFILE0:
|
| @@ -169,4 +176,109 @@ bool ParseAVCCodecId(const std::string& codec_id,
|
| return true;
|
| }
|
|
|
| +#if BUILDFLAG(ENABLE_HEVC_DEMUXING)
|
| +// The specification for HEVC codec id strings can be found in ISO IEC 14496-15
|
| +// dated 2012 or newer in the Annex E.3
|
| +bool ParseHEVCCodecId(const std::string& codec_id,
|
| + VideoCodecProfile* profile,
|
| + uint8_t* level_idc) {
|
| + if (!base::StartsWith(codec_id, "hev1.", base::CompareCase::SENSITIVE) &&
|
| + !base::StartsWith(codec_id, "hvc1.", base::CompareCase::SENSITIVE)) {
|
| + return false;
|
| + }
|
| +
|
| + // HEVC codec id consists of:
|
| + const int kMaxHevcCodecIdLength =
|
| + 5 + // 'hev1.' or 'hvc1.' prefix (5 chars)
|
| + 4 + // profile, e.g. '.A12' (max 4 chars)
|
| + 9 + // profile_compatibility, dot + 32-bit hex number (max 9 chars)
|
| + 5 + // tier and level, e.g. '.H120' (max 5 chars)
|
| + 18; // up to 6 constraint bytes, bytes are dot-separated and hex-encoded.
|
| +
|
| + if (codec_id.size() > kMaxHevcCodecIdLength) {
|
| + DVLOG(4) << __FUNCTION__ << ": Codec id is too long (" << codec_id << ")";
|
| + return false;
|
| + }
|
| +
|
| + std::vector<std::string> elem = base::SplitString(
|
| + codec_id, ".", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
|
| + DCHECK(elem[0] == "hev1" || elem[0] == "hvc1");
|
| +
|
| + uint8_t general_profile_space = 0;
|
| + if (elem[1][0] == 'A' || elem[1][0] == 'B' || elem[1][0] == 'C') {
|
| + general_profile_space = 1 + (elem[1][0] - 'A');
|
| + elem[1].erase(0, 1);
|
| + }
|
| + CHECK(general_profile_space >= 0 && general_profile_space <= 3);
|
| +
|
| + unsigned general_profile_idc = 0;
|
| + if (!base::StringToUint(elem[1], &general_profile_idc) ||
|
| + general_profile_idc > 0x1f) {
|
| + DVLOG(4) << __FUNCTION__ << ": invalid general_profile_idc=" << elem[1];
|
| + return false;
|
| + }
|
| +
|
| + uint32_t general_profile_compatibility_flags = 0;
|
| + if (!base::HexStringToUInt(elem[2], &general_profile_compatibility_flags)) {
|
| + DVLOG(4) << __FUNCTION__
|
| + << ": invalid general_profile_compatibility_flags=" << elem[2];
|
| + return false;
|
| + }
|
| +
|
| + if (profile) {
|
| + // TODO(servolk): Handle format range extension profiles as explained in
|
| + // HEVC standard (ISO/IEC ISO/IEC 23008-2) section A.3.5
|
| + if (general_profile_idc == 3 || (general_profile_compatibility_flags & 4)) {
|
| + *profile = HEVCPROFILE_MAIN_STILL_PICTURE;
|
| + }
|
| + if (general_profile_idc == 2 || (general_profile_compatibility_flags & 2)) {
|
| + *profile = HEVCPROFILE_MAIN10;
|
| + }
|
| + if (general_profile_idc == 1 || (general_profile_compatibility_flags & 1)) {
|
| + *profile = HEVCPROFILE_MAIN;
|
| + }
|
| + }
|
| +
|
| + uint8_t general_tier_flag;
|
| + if (elem[3][0] == 'L' || elem[3][0] == 'H') {
|
| + general_tier_flag = (elem[3][0] == 'L') ? 0 : 1;
|
| + elem[3].erase(0, 1);
|
| + } else {
|
| + DVLOG(4) << __FUNCTION__ << ": invalid general_tier_flag=" << elem[3];
|
| + return false;
|
| + }
|
| + CHECK(general_tier_flag == 0 || general_tier_flag == 1);
|
| +
|
| + unsigned general_level_idc = 0;
|
| + if (!base::StringToUint(elem[3], &general_level_idc) ||
|
| + general_level_idc > 0xff) {
|
| + DVLOG(4) << __FUNCTION__ << ": invalid general_level_idc=" << elem[3];
|
| + return false;
|
| + }
|
| +
|
| + if (level_idc)
|
| + *level_idc = static_cast<uint8_t>(general_level_idc);
|
| +
|
| + uint8_t constraint_flags[6];
|
| + memset(constraint_flags, 0, sizeof(constraint_flags));
|
| + // Remove everything up to the first constraint_flags byte
|
| + elem.erase(elem.begin(), elem.begin() + 4);
|
| + if (elem.size() > 6) {
|
| + DVLOG(4) << __FUNCTION__ << ": unexpected number of trailing bytes in HEVC "
|
| + << "codec id " << codec_id;
|
| + return false;
|
| + }
|
| + for (size_t i = 0; i < elem.size(); ++i) {
|
| + unsigned constr_byte = 0;
|
| + if (!base::HexStringToUInt(elem[i], &constr_byte) || constr_byte > 0xFF) {
|
| + DVLOG(4) << __FUNCTION__ << ": invalid constraint byte=" << elem[i];
|
| + return false;
|
| + }
|
| + constraint_flags[i] = constr_byte;
|
| + }
|
| +
|
| + return true;
|
| +}
|
| +#endif
|
| +
|
| } // namespace media
|
|
|