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

Unified 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 side-by-side diff with in-line comments
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 »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: media/base/video_codecs.cc
diff --git a/media/base/video_codecs.cc b/media/base/video_codecs.cc
index a2221a35d3dead73d0a14019d165c30116fa7ed3..ece3527bfc6650c1f9753589c50f3142c3dd996a 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,114 @@ 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");
+
+ if (elem.size() < 4) {
+ DVLOG(4) << __FUNCTION__ << ": invalid HEVC codec id " << codec_id;
+ return false;
+ }
+
+ uint8_t general_profile_space = 0;
+ if (elem[1].size() > 0 &&
+ (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);
+ }
+ 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
+
+ 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].size() > 0 && (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;
+ }
+ DCHECK(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));
+
+ if (elem.size() > 10) {
+ DVLOG(4) << __FUNCTION__ << ": unexpected number of trailing bytes in HEVC "
+ << "codec id " << codec_id;
+ return false;
+ }
+ for (size_t i = 4; 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
« 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