diff --git a/packager/app/test/testdata/dolby-vision-profile-5-with-encryption/output.mpd b/packager/app/test/testdata/dolby-vision-profile-5-with-encryption/output.mpd index b81c94aa08..9f02235c0b 100644 --- a/packager/app/test/testdata/dolby-vision-profile-5-with-encryption/output.mpd +++ b/packager/app/test/testdata/dolby-vision-profile-5-with-encryption/output.mpd @@ -3,6 +3,7 @@ + AAAANHBzc2gBAAAAEHfv7MCyTQKs4zweUuL7SwAAAAExMjM0NTY3ODkwMTIzNDU2AAAAAA== diff --git a/packager/app/test/testdata/dolby-vision-profile-8-with-encryption/output.mpd b/packager/app/test/testdata/dolby-vision-profile-8-with-encryption/output.mpd index 0950e11dcd..04c010c008 100644 --- a/packager/app/test/testdata/dolby-vision-profile-8-with-encryption/output.mpd +++ b/packager/app/test/testdata/dolby-vision-profile-8-with-encryption/output.mpd @@ -3,6 +3,7 @@ + AAAANHBzc2gBAAAAEHfv7MCyTQKs4zweUuL7SwAAAAExMjM0NTY3ODkwMTIzNDU2AAAAAA== @@ -15,6 +16,7 @@ + AAAANHBzc2gBAAAAEHfv7MCyTQKs4zweUuL7SwAAAAExMjM0NTY3ODkwMTIzNDU2AAAAAA== diff --git a/packager/app/test/testdata/hdr10-with-encryption/output.mpd b/packager/app/test/testdata/hdr10-with-encryption/output.mpd index 9fd7a8654a..56001f85c7 100644 --- a/packager/app/test/testdata/hdr10-with-encryption/output.mpd +++ b/packager/app/test/testdata/hdr10-with-encryption/output.mpd @@ -3,6 +3,7 @@ + AAAANHBzc2gBAAAAEHfv7MCyTQKs4zweUuL7SwAAAAExMjM0NTY3ODkwMTIzNDU2AAAAAA== diff --git a/packager/mpd/base/adaptation_set.cc b/packager/mpd/base/adaptation_set.cc index d7ee38246d..050b947194 100644 --- a/packager/mpd/base/adaptation_set.cc +++ b/packager/mpd/base/adaptation_set.cc @@ -291,6 +291,14 @@ std::optional AdaptationSet::GetXml() { } } + // https://dashif.org/docs/DASH-IF-IOP-v4.3.pdf - 4.2.5.1 + if (IsVideo() && transfer_characteristics_ > 0 && + !adaptation_set.AddSupplementalProperty( + "urn:mpeg:mpegB:cicp:TransferCharacteristics", + std::to_string(transfer_characteristics_))) { + return base::nullopt; + } + // Note: must be checked before checking segments_aligned_ (below). So that // segments_aligned_ is set before checking below. if (mpd_options_.mpd_type == MpdType::kStatic) { diff --git a/packager/mpd/base/adaptation_set.h b/packager/mpd/base/adaptation_set.h index 2decc2a8bd..1c25890142 100644 --- a/packager/mpd/base/adaptation_set.h +++ b/packager/mpd/base/adaptation_set.h @@ -180,6 +180,17 @@ class AdaptationSet { /// @param codec is the new codec to be set. void set_codec(const std::string& codec) { codec_ = codec; }; + /// @return transfer_characteristics. + const uint32_t transfer_characteristics() const { + return transfer_characteristics_; + } + + /// Set AdaptationSet's video transfer characteristics. + /// @param transfer_characteristics is the video transfer characteristics. + void set_transfer_characteristics(const uint32_t& transfer_characteristics) { + transfer_characteristics_ = transfer_characteristics; + }; + protected: /// @param language is the language of this AdaptationSet. Mainly relevant for /// audio. @@ -314,6 +325,9 @@ class AdaptationSet { // and HD videos in different AdaptationSets can share the same trick play // stream. std::vector trick_play_references_; + + // Transfer characteristics. + uint32_t transfer_characteristics_ = 0; }; } // namespace shaka diff --git a/packager/mpd/base/mpd_utils.cc b/packager/mpd/base/mpd_utils.cc index 3e8bdee256..18eae549d8 100644 --- a/packager/mpd/base/mpd_utils.cc +++ b/packager/mpd/base/mpd_utils.cc @@ -163,6 +163,17 @@ std::string GetAdaptationSetKey(const MediaInfo& media_info, if (!ignore_codec) { key.append(":"); key.append(GetBaseCodec(media_info)); + + if (GetBaseCodec(media_info).find("dvh") == 0) { + // Transfer characteristics for Dolby Vision (dvh1 or dvhe) must be PQ + // irrespective of value present in SPS VUI. + key.append(":"); + key.append(std::to_string(kTransferFunctionPQ)); + } else if (media_info.video_info().has_transfer_characteristics()) { + key.append(":"); + key.append( + std::to_string(media_info.video_info().transfer_characteristics())); + } } key.append(":"); key.append(GetLanguage(media_info)); diff --git a/packager/mpd/base/mpd_utils.h b/packager/mpd/base/mpd_utils.h index b48fbc06e7..245cf6f6b5 100644 --- a/packager/mpd/base/mpd_utils.h +++ b/packager/mpd/base/mpd_utils.h @@ -25,6 +25,7 @@ struct SegmentInfo; const char kEncryptedMp4Scheme[] = "urn:mpeg:dash:mp4protection:2011"; const char kPsshElementName[] = "cenc:pssh"; const char kMsproElementName[] = "mspr:pro"; +const uint32_t kTransferFunctionPQ = 16; bool HasVODOnlyFields(const MediaInfo& media_info); diff --git a/packager/mpd/base/period.cc b/packager/mpd/base/period.cc index 7c172a37ad..396a6ed906 100644 --- a/packager/mpd/base/period.cc +++ b/packager/mpd/base/period.cc @@ -269,6 +269,22 @@ bool Period::SetNewAdaptationSetAttributes( } } + // Set transfer characteristics. + // https://dashif.org/docs/DASH-IF-IOP-v4.3.pdf - 4.2.5.1 + // ISO/IEC 23001-8 MPEG systems technologies — Part 8: Coding-independent + // code points. https://en.wikipedia.org/wiki/Coding-independent_code_points + // - Common CCIP values. + // Dolby vision: + // https://professionalsupport.dolby.com/s/article/How-to-signal-Dolby-Vision-in-MPEG-DASH + // Transfer characteristics for Dolby Vision (dvh1 or dvhe) must be PQ + // irrespective of value present in SPS VUI. + if (new_adaptation_set->codec().find("dvh") == 0) { + new_adaptation_set->set_transfer_characteristics(kTransferFunctionPQ); + } else if (media_info.video_info().has_transfer_characteristics()) { + new_adaptation_set->set_transfer_characteristics( + media_info.video_info().transfer_characteristics()); + } + } else if (media_info.has_text_info()) { // IOP requires all AdaptationSets to have (sub)segmentAlignment set to // true, so carelessly set it to true.