diff --git a/Source/Python/utils/mp4-dash.py b/Source/Python/utils/mp4-dash.py index e226cae3..c994568f 100755 --- a/Source/Python/utils/mp4-dash.py +++ b/Source/Python/utils/mp4-dash.py @@ -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$)' @@ -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' @@ -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) @@ -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)) diff --git a/Source/Python/utils/mp4utils.py b/Source/Python/utils/mp4utils.py index 58f3c103..183bff1e 100644 --- a/Source/Python/utils/mp4utils.py +++ b/Source/Python/utils/mp4utils.py @@ -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: