Skip to content

Commit

Permalink
feat: support Dolby Vision profile 8.x (HEVC) and 10.x (AV1) in HLS a…
Browse files Browse the repository at this point in the history
…nd DASH (#1396)

Support Dolby Vision profile 8.1, 8.2, 8.4, 10.1, 10.4 signaling in HLS
and DASH.

Adds new option `--use_dovi_supplemental_codecs` (off by default) to use
SUPPLEMENTAL-CODECS in HLS and `scte214:supplementalCodecs` and
`scte214:supplementalProfiles` for DASH.

To maintain compatibility with existing players the current behavior of
using two entries in the manifest remains the default. This will be
changed in a future version where `use_dovi_supplemental_codecs` will
become on by default.

Adds Dolby Vision compatible brands, 'db1p', 'db2g', 'db4g', 'db4h',
'dby1' based on https://mp4ra.org/#/brands

---------

Co-authored-by: Xingzhao Yun <xyun@dolby.com>
  • Loading branch information
cosmin and XingzhaoYun committed May 11, 2024
1 parent f6f60e5 commit a99cfe0
Show file tree
Hide file tree
Showing 58 changed files with 584 additions and 50 deletions.
42 changes: 41 additions & 1 deletion packager/app/test/packager_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -486,7 +486,8 @@ def _GetFlags(self,
allow_codec_switching=False,
dash_force_segment_list=False,
force_cl_index=None,
start_segment_number=None):
start_segment_number=None,
use_dovi_supplemental_codecs=None):
flags = ['--single_threaded']

if not strip_parameter_set_nalus:
Expand Down Expand Up @@ -544,6 +545,9 @@ def _GetFlags(self,
if not dash_if_iop:
flags.append('--generate_dash_if_iop_compliant_mpd=false')

if use_dovi_supplemental_codecs:
flags.append('--use_dovi_supplemental_codecs')

if output_media_info:
flags.append('--output_media_info')
if output_dash:
Expand Down Expand Up @@ -1456,6 +1460,42 @@ def testDolbyVisionProfile8WithEncryption(self):
self.assertPackageSuccess(streams, flags)
self._CheckTestResults('dolby-vision-profile-8-with-encryption')

# TODO(cosmin): shared_library build does not support
# use_dovi_supplemental_codecs
@unittest.skipIf(
test_env.BUILD_TYPE == 'shared',
'libpackager shared_library does not support '
'--use_dovi_supplemental_codecs flag.'
)
def testDolbyVisionProfile8UsingSupplementalCodecs(self):
streams = [
self._GetStream('video', test_file='sparks_dovi_8.mp4')
]
flags = self._GetFlags(output_dash=True,
output_hls=True,
use_dovi_supplemental_codecs=True)

self.assertPackageSuccess(streams, flags)
self._CheckTestResults('dolby-vision-profile-8-supplemental-codecs')

# TODO(cosmin): shared_library build does not support
# use_dovi_supplemental_codecs
@unittest.skipIf(
test_env.BUILD_TYPE == 'shared',
'libpackager shared_library does not support '
'--use_dovi_supplemental_codecs flag.'
)
def testDolbyVisionProfile10UsingSupplementalCodecs(self):
streams = [
self._GetStream('video', test_file='sparks_dovi_10.mp4')
]
flags = self._GetFlags(output_dash=True,
output_hls=True,
use_dovi_supplemental_codecs=True)

self.assertPackageSuccess(streams, flags)
self._CheckTestResults('dolby-vision-profile-10-supplemental-codecs')

def testVp8Mp4WithEncryption(self):
streams = [
self._GetStream('video',
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#EXTM3U
## Generated with https://github.com/shaka-project/shaka-packager version <tag>-<hash>-<test>

#EXT-X-INDEPENDENT-SEGMENTS

#EXT-X-STREAM-INF:BANDWIDTH=550702,AVERAGE-BANDWIDTH=577484,CODECS="av01.0.04M.10.0.111.09.16.09.0",SUPPLEMENTAL-CODECS="dav1.10.01/db1p",RESOLUTION=640x360,FRAME-RATE=59.940,VIDEO-RANGE=PQ,CLOSED-CAPTIONS=NONE
stream_0.m3u8
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--Generated with https://github.com/shaka-project/shaka-packager version <tag>-<hash>-<test>-->
<MPD xmlns="urn:mpeg:dash:schema:mpd:2011" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:mpeg:dash:schema:mpd:2011 DASH-MPD.xsd" xmlns:scte214="urn:scte:dash:scte214-extensions" profiles="urn:mpeg:dash:profile:isoff-on-demand:2011" minBufferTime="PT2S" type="static" mediaPresentationDuration="PT6.022683S">
<Period id="0">
<AdaptationSet id="0" contentType="video" width="640" height="360" frameRate="60000/1001" subsegmentAlignment="true" par="16:9">
<SupplementalProperty schemeIdUri="urn:mpeg:mpegB:cicp:MatrixCoefficients" value="9"/>
<SupplementalProperty schemeIdUri="urn:mpeg:mpegB:cicp:ColourPrimaries" value="9"/>
<SupplementalProperty schemeIdUri="urn:mpeg:mpegB:cicp:TransferCharacteristics" value="16"/>
<Representation id="0" bandwidth="550702" codecs="av01.0.04M.10.0.111.09.16.09.0" mimeType="video/mp4" scte214:supplementalCodecs="dav1.10.01" scte214:supplementalProfiles="db1p" sar="1:1">
<BaseURL>sparks_dovi_10-video.mp4</BaseURL>
<SegmentBase indexRange="871-926" timescale="60000">
<Initialization range="0-870"/>
</SegmentBase>
</Representation>
</AdaptationSet>
</Period>
</MPD>
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#EXTM3U
#EXT-X-VERSION:6
## Generated with https://github.com/shaka-project/shaka-packager version <tag>-<hash>-<test>
#EXT-X-TARGETDURATION:6
#EXT-X-PLAYLIST-TYPE:VOD
#EXT-X-MAP:URI="sparks_dovi_10-video.mp4",BYTERANGE="871@0"
#EXTINF:5.355,
#EXT-X-BYTERANGE:368650@927
sparks_dovi_10-video.mp4
#EXTINF:0.667,
#EXT-X-BYTERANGE:66100
sparks_dovi_10-video.mp4
#EXT-X-ENDLIST
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
<MPD xmlns="urn:mpeg:dash:schema:mpd:2011" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:mpeg:dash:schema:mpd:2011 DASH-MPD.xsd" xmlns:cenc="urn:mpeg:cenc:2013" profiles="urn:mpeg:dash:profile:isoff-on-demand:2011" minBufferTime="PT2S" type="static" mediaPresentationDuration="PT6.022683S">
<Period id="0">
<AdaptationSet id="0" contentType="video" width="640" height="360" frameRate="60000/1001" subsegmentAlignment="true" par="16:9">
<SupplementalProperty schemeIdUri="urn:mpeg:mpegB:cicp:MatrixCoefficients" value="2"/>
<SupplementalProperty schemeIdUri="urn:mpeg:mpegB:cicp:ColourPrimaries" value="2"/>
<SupplementalProperty schemeIdUri="urn:mpeg:mpegB:cicp:TransferCharacteristics" value="16"/>
<ContentProtection value="cenc" schemeIdUri="urn:mpeg:dash:mp4protection:2011" cenc:default_KID="31323334-3536-3738-3930-313233343536"/>
<ContentProtection schemeIdUri="urn:uuid:1077efec-c0b2-4d02-ace3-3c1e52e2fb4b">
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#EXTM3U
## Generated with https://github.com/shaka-project/shaka-packager version <tag>-<hash>-<test>

#EXT-X-INDEPENDENT-SEGMENTS

#EXT-X-STREAM-INF:BANDWIDTH=807837,AVERAGE-BANDWIDTH=748074,CODECS="hvc1.2.4.L90.90",SUPPLEMENTAL-CODECS="dvh1.08.01/db2g",RESOLUTION=640x360,FRAME-RATE=59.940,VIDEO-RANGE=PQ,CLOSED-CAPTIONS=NONE
stream_0.m3u8
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--Generated with https://github.com/shaka-project/shaka-packager version <tag>-<hash>-<test>-->
<MPD xmlns="urn:mpeg:dash:schema:mpd:2011" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:mpeg:dash:schema:mpd:2011 DASH-MPD.xsd" xmlns:scte214="urn:scte:dash:scte214-extensions" profiles="urn:mpeg:dash:profile:isoff-on-demand:2011" minBufferTime="PT2S" type="static" mediaPresentationDuration="PT6.022683S">
<Period id="0">
<AdaptationSet id="0" contentType="video" width="640" height="360" frameRate="60000/1001" subsegmentAlignment="true" par="16:9">
<SupplementalProperty schemeIdUri="urn:mpeg:mpegB:cicp:MatrixCoefficients" value="9"/>
<SupplementalProperty schemeIdUri="urn:mpeg:mpegB:cicp:ColourPrimaries" value="9"/>
<SupplementalProperty schemeIdUri="urn:mpeg:mpegB:cicp:TransferCharacteristics" value="16"/>
<Representation id="0" bandwidth="807837" codecs="hvc1.2.4.L90.90" mimeType="video/mp4" scte214:supplementalCodecs="dvh1.08.01" scte214:supplementalProfiles="db2g" sar="1:1">
<BaseURL>sparks_dovi_8-video.mp4</BaseURL>
<SegmentBase indexRange="992-1071" timescale="60000">
<Initialization range="0-991"/>
</SegmentBase>
</Representation>
</AdaptationSet>
</Period>
</MPD>
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#EXTM3U
#EXT-X-VERSION:6
## Generated with https://github.com/shaka-project/shaka-packager version <tag>-<hash>-<test>
#EXT-X-TARGETDURATION:3
#EXT-X-PLAYLIST-TYPE:VOD
#EXT-X-MAP:URI="sparks_dovi_8-video.mp4",BYTERANGE="992@0"
#EXTINF:2.002,
#EXT-X-BYTERANGE:172013@1072
sparks_dovi_8-video.mp4
#EXTINF:2.002,
#EXT-X-BYTERANGE:186781
sparks_dovi_8-video.mp4
#EXTINF:2.002,
#EXT-X-BYTERANGE:202161
sparks_dovi_8-video.mp4
#EXTINF:0.017,
#EXT-X-BYTERANGE:2221
sparks_dovi_8-video.mp4
#EXT-X-ENDLIST
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
<MPD xmlns="urn:mpeg:dash:schema:mpd:2011" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:mpeg:dash:schema:mpd:2011 DASH-MPD.xsd" xmlns:cenc="urn:mpeg:cenc:2013" profiles="urn:mpeg:dash:profile:isoff-on-demand:2011" minBufferTime="PT2S" type="static" mediaPresentationDuration="PT6.022683S">
<Period id="0">
<AdaptationSet id="0" contentType="video" width="640" height="360" frameRate="60000/1001" subsegmentAlignment="true" par="16:9">
<SupplementalProperty schemeIdUri="urn:mpeg:mpegB:cicp:MatrixCoefficients" value="9"/>
<SupplementalProperty schemeIdUri="urn:mpeg:mpegB:cicp:ColourPrimaries" value="9"/>
<SupplementalProperty schemeIdUri="urn:mpeg:mpegB:cicp:TransferCharacteristics" value="16"/>
<ContentProtection value="cenc" schemeIdUri="urn:mpeg:dash:mp4protection:2011" cenc:default_KID="31323334-3536-3738-3930-313233343536"/>
<ContentProtection schemeIdUri="urn:uuid:1077efec-c0b2-4d02-ace3-3c1e52e2fb4b">
Expand All @@ -16,6 +18,8 @@
</Representation>
</AdaptationSet>
<AdaptationSet id="1" contentType="video" width="640" height="360" frameRate="60000/1001" subsegmentAlignment="true" par="16:9">
<SupplementalProperty schemeIdUri="urn:mpeg:mpegB:cicp:MatrixCoefficients" value="9"/>
<SupplementalProperty schemeIdUri="urn:mpeg:mpegB:cicp:ColourPrimaries" value="9"/>
<SupplementalProperty schemeIdUri="urn:mpeg:mpegB:cicp:TransferCharacteristics" value="16"/>
<ContentProtection value="cenc" schemeIdUri="urn:mpeg:dash:mp4protection:2011" cenc:default_KID="31323334-3536-3738-3930-313233343536"/>
<ContentProtection schemeIdUri="urn:uuid:1077efec-c0b2-4d02-ace3-3c1e52e2fb4b">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ video_info {
decoder_config: "\001d\000\036\377\341\000\031gd\000\036\254\331@\240/\371p\021\000\000\003\003\351\000\000\352`\017\026-\226\001\000\006h\353\343\313\"\300"
pixel_width: 1
pixel_height: 1
supplemental_codec: ""
compatible_brand: 0
}
init_range {
begin: 0
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ video_info {
decoder_config: "\001d\000\036\377\341\000\031gd\000\036\254\331@\240/\371p\021\000\000\003\003\351\000\000\352`\017\026-\226\001\000\006h\353\343\313\"\300"
pixel_width: 1
pixel_height: 1
supplemental_codec: ""
compatible_brand: 0
}
init_range {
begin: 0
Expand Down
2 changes: 2 additions & 0 deletions packager/app/test/testdata/hdr10-with-encryption/output.mpd
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
<MPD xmlns="urn:mpeg:dash:schema:mpd:2011" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:mpeg:dash:schema:mpd:2011 DASH-MPD.xsd" xmlns:cenc="urn:mpeg:cenc:2013" profiles="urn:mpeg:dash:profile:isoff-on-demand:2011" minBufferTime="PT2S" type="static" mediaPresentationDuration="PT2.8028S">
<Period id="0">
<AdaptationSet id="0" contentType="video" width="640" height="360" frameRate="30000/1001" subsegmentAlignment="true" par="16:9">
<SupplementalProperty schemeIdUri="urn:mpeg:mpegB:cicp:MatrixCoefficients" value="9"/>
<SupplementalProperty schemeIdUri="urn:mpeg:mpegB:cicp:ColourPrimaries" value="9"/>
<SupplementalProperty schemeIdUri="urn:mpeg:mpegB:cicp:TransferCharacteristics" value="16"/>
<ContentProtection value="cenc" schemeIdUri="urn:mpeg:dash:mp4protection:2011" cenc:default_KID="31323334-3536-3738-3930-313233343536"/>
<ContentProtection schemeIdUri="urn:uuid:1077efec-c0b2-4d02-ace3-3c1e52e2fb4b">
Expand Down
9 changes: 9 additions & 0 deletions packager/hls/base/master_playlist.cc
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,15 @@ void BuildStreamInfTag(const MediaPlaylist& playlist,
variant.text_codecs.end());
tag.AddQuotedString("CODECS", absl::StrJoin(all_codecs, ","));

if (playlist.supplemental_codec() != "" &&
playlist.compatible_brand() != media::FOURCC_NULL) {
std::vector<std::string> supplemental_codecs;
supplemental_codecs.push_back(playlist.supplemental_codec());
supplemental_codecs.push_back(FourCCToString(playlist.compatible_brand()));
tag.AddQuotedString("SUPPLEMENTAL-CODECS",
absl::StrJoin(supplemental_codecs, "/"));
}

uint32_t width;
uint32_t height;
if (playlist.GetDisplayResolution(&width, &height)) {
Expand Down
22 changes: 21 additions & 1 deletion packager/hls/base/media_playlist.cc
Original file line number Diff line number Diff line change
Expand Up @@ -393,6 +393,13 @@ bool MediaPlaylist::SetMediaInfo(const MediaInfo& media_info) {
if (media_info.has_video_info()) {
stream_type_ = MediaPlaylistStreamType::kVideo;
codec_ = AdjustVideoCodec(media_info.video_info().codec());
if (media_info.video_info().has_supplemental_codec() &&
media_info.video_info().has_compatible_brand()) {
supplemental_codec_ =
AdjustVideoCodec(media_info.video_info().supplemental_codec());
compatible_brand_ = static_cast<media::FourCC>(
media_info.video_info().compatible_brand());
}
} else if (media_info.has_audio_info()) {
stream_type_ = MediaPlaylistStreamType::kAudio;
codec_ = media_info.audio_info().codec();
Expand Down Expand Up @@ -576,10 +583,23 @@ std::string MediaPlaylist::GetVideoRange() const {
// https://tools.ietf.org/html/draft-pantos-hls-rfc8216bis-02#section-4.4.4.2
switch (media_info_.video_info().transfer_characteristics()) {
case 1:
case 6:
case 13:
case 14:
// Dolby Vision profile 8.4 may have a transfer_characteristics 14, the
// actual value refers to preferred_transfer_characteristic value in SEI
// message, using compatible brand as a workaround
if (!supplemental_codec_.empty() &&
compatible_brand_ == media::FOURCC_db4g)
return "HLG";
else
return "SDR";
case 15:
return "SDR";
case 16:
case 18:
return "PQ";
case 18:
return "HLG";
default:
// Leave it empty if we do not have the transfer characteristics
// information.
Expand Down
5 changes: 5 additions & 0 deletions packager/hls/base/media_playlist.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#include <packager/macros/classes.h>
#include <packager/mpd/base/bandwidth_estimator.h>
#include <packager/mpd/base/media_info.pb.h>
#include "packager/media/base/fourccs.h"

namespace shaka {

Expand Down Expand Up @@ -80,6 +81,8 @@ class MediaPlaylist {
const std::string& group_id() const { return group_id_; }
MediaPlaylistStreamType stream_type() const { return stream_type_; }
const std::string& codec() const { return codec_; }
const std::string& supplemental_codec() const { return supplemental_codec_; }
const media::FourCC& compatible_brand() const { return compatible_brand_; }

/// For testing only.
void SetStreamTypeForTesting(MediaPlaylistStreamType stream_type);
Expand Down Expand Up @@ -265,6 +268,8 @@ class MediaPlaylist {
// Whether to use byte range for SegmentInfoEntry.
bool use_byte_range_ = false;
std::string codec_;
std::string supplemental_codec_;
media::FourCC compatible_brand_;
std::string language_;
std::vector<std::string> characteristics_;
bool forced_subtitle_ = false;
Expand Down
2 changes: 1 addition & 1 deletion packager/hls/base/media_playlist_unittest.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1227,7 +1227,7 @@ INSTANTIATE_TEST_CASE_P(VideoRanges,
Values(VideoRangeTestData{"hvc1.2.4.L63.90", 0, ""},
VideoRangeTestData{"hvc1.2.4.L63.90", 1, "SDR"},
VideoRangeTestData{"hvc1.2.4.L63.90", 16, "PQ"},
VideoRangeTestData{"hvc1.2.4.L63.90", 18, "PQ"},
VideoRangeTestData{"hvc1.2.4.L63.90", 18, "HLG"},
VideoRangeTestData{"dvh1.05.08", 0, "PQ"}));

} // namespace hls
Expand Down
5 changes: 5 additions & 0 deletions packager/media/base/fourccs.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,11 @@ enum FourCC : uint32_t {
FOURCC_dac3 = 0x64616333,
FOURCC_dac4 = 0x64616334,
FOURCC_dash = 0x64617368,
FOURCC_dav1 = 0x64617631,
FOURCC_db1p = 0x64623170,
FOURCC_db2g = 0x64623267,
FOURCC_db4g = 0x64623467,
FOURCC_db4h = 0x64623468,
FOURCC_dby1 = 0x64627931,
FOURCC_ddts = 0x64647473,
FOURCC_dec3 = 0x64656333,
Expand Down
8 changes: 6 additions & 2 deletions packager/media/base/media_handler_test_base.cc
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,10 @@ const uint32_t kWidth = 10u;
const uint32_t kHeight = 20u;
const uint32_t kPixelWidth = 2u;
const uint32_t kPixelHeight = 3u;
const uint8_t kColorPrimaries = 0;
const uint8_t kMatrixCoefficients = 0;
const uint8_t kTransferCharacteristics = 0;

const int16_t kTrickPlayFactor = 0;
const uint8_t kNaluLengthSize = 1u;
const bool kEncrypted = true;
Expand Down Expand Up @@ -207,8 +210,9 @@ std::unique_ptr<StreamInfo> MediaHandlerTestBase::GetVideoStreamInfo(
return std::unique_ptr<VideoStreamInfo>(new VideoStreamInfo(
kTrackId, time_scale, kDuration, codec, H26xStreamFormat::kUnSpecified,
kCodecString, kCodecConfig, sizeof(kCodecConfig), width, height,
kPixelWidth, kPixelHeight, kTransferCharacteristics, kTrickPlayFactor,
kNaluLengthSize, kLanguage, !kEncrypted));
kPixelWidth, kPixelHeight, kColorPrimaries, kMatrixCoefficients,
kTransferCharacteristics, kTrickPlayFactor, kNaluLengthSize, kLanguage,
!kEncrypted));
}

std::unique_ptr<StreamInfo> MediaHandlerTestBase::GetAudioStreamInfo(
Expand Down
4 changes: 4 additions & 0 deletions packager/media/base/video_stream_info.cc
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@ VideoStreamInfo::VideoStreamInfo(int track_id,
uint32_t height,
uint32_t pixel_width,
uint32_t pixel_height,
uint8_t color_primaries,
uint8_t matrix_coefficients,
uint8_t transfer_characteristics,
uint32_t trick_play_factor,
uint8_t nalu_length_size,
Expand All @@ -71,6 +73,8 @@ VideoStreamInfo::VideoStreamInfo(int track_id,
pixel_width_(pixel_width),
pixel_height_(pixel_height),
transfer_characteristics_(transfer_characteristics),
color_primaries_(color_primaries),
matrix_coefficients_(matrix_coefficients),
trick_play_factor_(trick_play_factor),
nalu_length_size_(nalu_length_size) {}

Expand Down
Loading

0 comments on commit a99cfe0

Please sign in to comment.