Index: media/base/video_codecs.cc |
diff --git a/media/base/video_codecs.cc b/media/base/video_codecs.cc |
index eb7daa2c21be0f2127073ebab00f74b28c7ee2e9..e68e4337693b6fc816bb298430198ada750d0d6c 100644 |
--- a/media/base/video_codecs.cc |
+++ b/media/base/video_codecs.cc |
@@ -20,6 +20,8 @@ std::string GetCodecName(VideoCodec codec) { |
return "h264"; |
case kCodecHEVC: |
return "hevc"; |
+ case kCodecDolbyVision: |
+ return "dolbyvision"; |
case kCodecVC1: |
return "vc1"; |
case kCodecMPEG2: |
@@ -79,6 +81,14 @@ std::string GetProfileName(VideoCodecProfile profile) { |
return "vp9 profile2"; |
case VP9PROFILE_PROFILE3: |
return "vp9 profile3"; |
+ case DOLBYVISION_PROFILE0: |
+ return "dolby vision profile 0"; |
+ case DOLBYVISION_PROFILE4: |
+ return "dolby vision profile 4"; |
+ case DOLBYVISION_PROFILE5: |
+ return "dolby vision profile 5"; |
+ case DOLBYVISION_PROFILE7: |
+ return "dolby vision profile 7"; |
} |
NOTREACHED(); |
return ""; |
@@ -419,6 +429,104 @@ bool ParseHEVCCodecId(const std::string& codec_id, |
} |
#endif |
+#if BUILDFLAG(ENABLE_DOLBY_VISION_DEMUXING) |
+bool IsDolbyVisionAVCCodecId(const std::string& codec_id) { |
+ return base::StartsWith(codec_id, "dva1.", base::CompareCase::SENSITIVE) || |
+ base::StartsWith(codec_id, "dvav.", base::CompareCase::SENSITIVE); |
+} |
+ |
+bool IsDolbyVisionHEVCCodecId(const std::string& codec_id) { |
+ return base::StartsWith(codec_id, "dvh1.", base::CompareCase::SENSITIVE) || |
+ base::StartsWith(codec_id, "dvhe.", base::CompareCase::SENSITIVE); |
+} |
+ |
+// The specification for Dolby Vision codec id strings can be found in Dolby |
+// Vision streams within the MPEG-DASH format. |
+bool ParseDolbyVisionCodecId(const std::string& codec_id, |
+ VideoCodecProfile* profile, |
+ uint8_t* level_idc) { |
+ if (!IsDolbyVisionAVCCodecId(codec_id) && |
+ !IsDolbyVisionHEVCCodecId(codec_id)) { |
+ return false; |
+ } |
+ |
+ const int kMaxDvCodecIdLength = 5 // FOURCC string |
+ + 1 // delimiting period |
+ + 2 // profile id as 2 digit string |
+ + 1 // delimiting period |
+ + 2; // level id as 2 digit string. |
+ |
+ if (codec_id.size() > kMaxDvCodecIdLength) { |
+ DVLOG(4) << __func__ << ": 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] == "dvh1" || elem[0] == "dvhe" || elem[0] == "dva1" || |
+ elem[0] == "dvav"); |
+ |
+ if (elem.size() != 3) { |
+ DVLOG(4) << __func__ << ": invalid dolby vision codec id " << codec_id; |
+ return false; |
+ } |
+ |
+ // Profile string should be two digits. |
+ unsigned profile_id = 0; |
+ if (elem[1].size() != 2 || !base::StringToUint(elem[1], &profile_id) || |
+ profile_id > 7) { |
+ DVLOG(4) << __func__ << ": invalid format or profile_id=" << elem[1]; |
+ return false; |
+ } |
+ |
+ // Only profiles 0, 4, 5 and 7 are valid. Profile 0 is encoded based on AVC |
+ // while profile 4, 5 and 7 are based on HEVC. |
+ switch (profile_id) { |
+ case 0: |
+ if (!IsDolbyVisionAVCCodecId(codec_id)) { |
+ DVLOG(4) << __func__ |
+ << ": codec id is mismatched with profile_id=" << profile_id; |
+ return false; |
+ } |
+ *profile = DOLBYVISION_PROFILE0; |
+ break; |
+#if BUILDFLAG(ENABLE_HEVC_DEMUXING) |
+ case 4: |
+ case 5: |
+ case 7: |
+ if (!IsDolbyVisionHEVCCodecId(codec_id)) { |
+ DVLOG(4) << __func__ |
+ << ": codec id is mismatched with profile_id=" << profile_id; |
+ return false; |
+ } |
+ if (profile_id == 4) |
+ *profile = DOLBYVISION_PROFILE4; |
+ else if (profile_id == 5) |
+ *profile = DOLBYVISION_PROFILE5; |
+ else if (profile_id == 7) |
+ *profile = DOLBYVISION_PROFILE7; |
+ break; |
+#endif |
+ default: |
+ DVLOG(4) << __func__ |
+ << ": depecrated and not supported profile_id=" << profile_id; |
+ return false; |
+ } |
+ |
+ // Level string should be two digits. |
+ unsigned level_id = 0; |
+ if (elem[2].size() != 2 || !base::StringToUint(elem[2], &level_id) || |
+ level_id > 9 || level_id < 1) { |
+ DVLOG(4) << __func__ << ": invalid format level_id=" << elem[2]; |
+ return false; |
+ } |
+ |
+ *level_idc = level_id; |
+ |
+ return true; |
+} |
+#endif |
+ |
VideoCodec StringToVideoCodec(const std::string& codec_id) { |
std::vector<std::string> elem = base::SplitString( |
codec_id, ".", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL); |
@@ -444,6 +552,10 @@ VideoCodec StringToVideoCodec(const std::string& codec_id) { |
if (ParseHEVCCodecId(codec_id, &profile, &level)) |
return kCodecHEVC; |
#endif |
+#if BUILDFLAG(ENABLE_DOLBY_VISION_DEMUXING) |
+ if (ParseDolbyVisionCodecId(codec_id, &profile, &level)) |
+ return kCodecDolbyVision; |
+#endif |
return kUnknownVideoCodec; |
} |