Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Dolby Vision for DASH signaling support. #820

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 52 additions & 9 deletions Source/Python/utils/mp4-dash.py
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,8 @@

DASH_DEFAULT_ROLE_NAMESPACE = 'urn:mpeg:dash:role:2011'

SCTE_NAMESPACE = 'urn:scte:dash:scte214-extensions'

DASH_MEDIA_SEGMENT_URL_PATTERN_SMOOTH = "/QualityLevels($Bandwidth$)/Fragments(%s=$Time$)"
DASH_MEDIA_SEGMENT_URL_PATTERN_HIPPO = '%s/Bitrate($Bandwidth$)/Fragment($Time$)'

Expand All @@ -139,6 +141,10 @@
DOLBY_DIGITAL_AUDIO_CHANNEL_CONFIGURATION_SCHEME_ID_URI = 'tag:dolby.com,2014:dash:audio_channel_configuration:2011'
DOLBY_AC4_AUDIO_CHANNEL_CONFIGURATION_SCHEME_ID_URI = 'tag:dolby.com,2015:dash:audio_channel_configuration:2015'

MPEG_DASH_MATRIX_COEFFICIENTS_SCHEME_ID_URI = 'urn:mpeg:mpegB:cicp:MatrixCoefficients'
MPEG_DASH_COLOUR_PRIMARIES_SCHEME_ID_URI = 'urn:mpeg:mpegB:cicp:ColourPrimaries'
MPEG_DASH_TRANSFER_CHARACTERISTICS_SCHEME_ID_URI = 'urn:mpeg:mpegB:cicp:TransferCharacteristics'

ISOFF_MAIN_PROFILE = 'urn:mpeg:dash:profile:isoff-main:2011'
ISOFF_LIVE_PROFILE = 'urn:mpeg:dash:profile:isoff-live:2011'
ISOFF_ON_DEMAND_PROFILE = 'urn:mpeg:dash:profile:isoff-on-demand:2011'
Expand Down Expand Up @@ -478,15 +484,50 @@ def OutputDash(options, set_attributes, audio_sets, video_sets, subtitles_sets,
AddSegmentTemplate(options, adaptation_set, init_segment_url, media_segment_url_template_prefix, video_tracks[0], 'video')

for video_track in video_tracks:
representation = xml.SubElement(adaptation_set,
'Representation',
id=video_track.representation_id,
codecs=video_track.codec,
width=str(video_track.width),
height=str(video_track.height),
scanType=video_track.scan_type,
frameRate=video_track.frame_rate_ratio,
bandwidth=str(video_track.bandwidth))
if hasattr(video_track, 'supplemental_codec') and hasattr(video_track, 'supplemental_profile'):
#adding MatrixCoefficients
if hasattr(video_track, 'matrix_coefficients'):
xml.SubElement(adaptation_set,
'EssentialProperty',
schemeIdUri=MPEG_DASH_MATRIX_COEFFICIENTS_SCHEME_ID_URI,
value=video_track.matrix_coefficients)

#adding ColourPrimaries
if hasattr(video_track, 'colour_primaries'):
xml.SubElement(adaptation_set,
'EssentialProperty',
schemeIdUri=MPEG_DASH_COLOUR_PRIMARIES_SCHEME_ID_URI,
value=video_track.colour_primaries)

#adding TransferCharacteristics
if hasattr(video_track, 'transfer_characteristics'):
xml.SubElement(adaptation_set,
'EssentialProperty',
schemeIdUri=MPEG_DASH_TRANSFER_CHARACTERISTICS_SCHEME_ID_URI,
value=video_track.transfer_characteristics)

representation = xml.SubElement(adaptation_set,
'Representation',
id=video_track.representation_id,
codecs=video_track.codec.split(',')[0],
width=str(video_track.width),
height=str(video_track.height),
scanType=video_track.scan_type,
frameRate=video_track.frame_rate_ratio,
bandwidth=str(video_track.bandwidth))
xml.register_namespace('scte214', SCTE_NAMESPACE)
representation.set('{'+SCTE_NAMESPACE+'}supplementalCodecs', video_track.supplemental_codec)
representation.set('{'+SCTE_NAMESPACE+'}supplementalProfiles', video_track.supplemental_profile)
else:
representation = xml.SubElement(adaptation_set,
'Representation',
id=video_track.representation_id,
codecs=video_track.codec,
width=str(video_track.width),
height=str(video_track.height),
scanType=video_track.scan_type,
frameRate=video_track.frame_rate_ratio,
bandwidth=str(video_track.bandwidth))
if hasattr(video_track, 'max_playout_rate'):
representation.set('maxPlayoutRate', video_track.max_playout_rate)

Expand Down Expand Up @@ -1034,6 +1075,8 @@ def OutputHls(options, set_attributes, audio_sets, video_sets, subtitles_sets, s
iframes_playlist_path))
if supplemental_codec_string != '':
iframe_playlist_lines.append(',SUPPLEMENTAL-CODECS="{}"\n'.format(supplemental_codec_string))
else:
iframe_playlist_lines.append('\n')

master_playlist_file.write('\n# I-Frame Playlists\n')
master_playlist_file.write(''.join(iframe_playlist_lines))
Expand Down
23 changes: 20 additions & 3 deletions Source/Python/utils/mp4utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -427,17 +427,34 @@ def __init__(self, parent, info):
brand = 'db1p'
if brand in self.parent.info['file']['compatible_brands']:
self.dv_brand = brand
else:
print('WARNING: missing brand "db1p" in MP4 file for Dolby Vision Profile 8.1.')
self.supplemental_profile = brand
self.transfer_characteristics = '16'
self.matrix_coefficients = '9'
self.colour_primaries = '9'
elif bl_compatibility_id == 2:
self.video_range = 'SDR'
brand = 'db2g'
if brand in self.parent.info['file']['compatible_brands']:
self.dv_brand = brand
self.supplemental_profile = brand
elif bl_compatibility_id == 4:
self.video_range = 'HLG'
self.matrix_coefficients = '9'
self.colour_primaries = '9'
if 'db4g' in self.parent.info['file']['compatible_brands']:
self.dv_brand = 'db4g'
elif 'db4h' in self.parent.info['file']['compatible_brands']:
self.dv_brand = 'db4h'
brand = 'db4g'
self.dv_brand = brand
self.supplemental_profile = brand
self.transfer_characteristics = '14'
else:
brand = 'db4h'
self.dv_brand = brand
self.supplemental_profile = brand
self.transfer_characteristics = '18'
if 'db4h' not in self.parent.info['file']['compatible_brands']:
print('WARNING: missing brand "db4g" or "db4h" in MP4 file for Dolby Vision Profile 8.4. Will use "db4h" as default.')
else:
PrintErrorAndExit('ERROR: unsupported ccid for Dolby Vision profile 8/9.')
else:
Expand Down