<s> """<STR_LIT>""" <EOL> from . import scte35 <EOL> from . mp4filter import MP4Filter <EOL> from . structops import str_to_uint32 , uint32_to_str , str_to_uint64 , uint64_to_str , str_to_sint32 , sint32_to_str <EOL> from . ttml_timing_offset import adjust_ttml_content <EOL> KEEP_SIDX = False <EOL> class MediaSegmentFilterError ( Exception ) : <EOL> "<STR_LIT>" <EOL> class MediaSegmentFilter ( MP4Filter ) : <EOL> """<STR_LIT>""" <EOL> def __init__ ( self , file_name , seg_nr = None , seg_duration = <NUM_LIT:1> , offset = <NUM_LIT:0> , lmsg = False , track_timescale = None , <EOL> scte35_per_minute = <NUM_LIT:0> , rel_path = None , is_ttml = False ) : <EOL> MP4Filter . __init__ ( self , file_name ) <EOL> self . top_level_boxes_to_parse = [ "<STR_LIT>" , "<STR_LIT>" , "<STR_LIT>" , "<STR_LIT>" ] <EOL> self . composite_boxes_to_parse = [ '<STR_LIT>' , '<STR_LIT>' ] <EOL> self . seg_nr = seg_nr <EOL> self . seg_duration = seg_duration <EOL> self . offset = offset <EOL> self . track_timescale = track_timescale <EOL> self . rel_path = rel_path <EOL> self . lmsg = lmsg <EOL> self . size_change = <NUM_LIT:0> <EOL> self . tfdt_value = None <EOL> self . duration = None <EOL> self . scte35_per_minute = scte35_per_minute <EOL> self . is_ttml = is_ttml <EOL> self . ttml_size = None <EOL> if self . is_ttml : <EOL> self . data = self . find_and_process_mdat ( self . data ) <EOL> def process_styp ( self , data ) : <EOL> "<STR_LIT>" <EOL> lmsg = self . lmsg <EOL> output = "<STR_LIT>" <EOL> size = str_to_uint32 ( data [ : <NUM_LIT:4> ] ) <EOL> pos = <NUM_LIT:8> <EOL> brands = [ ] <EOL> while pos < size : <EOL> brand = data [ pos : pos + <NUM_LIT:4> ] <EOL> if brand != "<STR_LIT>" : <EOL> brands . append ( brand ) <EOL> pos += <NUM_LIT:4> <EOL> if lmsg : <EOL> brands . append ( "<STR_LIT>" ) <EOL> new_size = <NUM_LIT:8> + <NUM_LIT:4> * len ( brands ) <EOL> output += uint32_to_str ( new_size ) <EOL> output += "<STR_LIT>" <EOL> for brand in brands : <EOL> output += brand <EOL> scte35box = self . create_scte35box ( ) <EOL> output += scte35box <EOL> return output <EOL> def process_tfhd ( self , data ) : <EOL> "<STR_LIT>" <EOL> if not self . is_ttml : <EOL> return data <EOL> tf_flags = str_to_uint32 ( data [ <NUM_LIT:8> : <NUM_LIT:12> ] ) & <NUM_LIT> <EOL> pos = <NUM_LIT:16> <EOL> if tf_flags & <NUM_LIT> : <EOL> raise MediaSegmentFilterError ( "<STR_LIT>" ) <EOL> if tf_flags & <NUM_LIT> : <EOL> pos += <NUM_LIT:4> <EOL> if tf_flags & <NUM_LIT> == <NUM_LIT:0> : <EOL> raise MediaSegmentFilterError ( "<STR_LIT>" ) <EOL> else : <EOL> pos += <NUM_LIT:4> <EOL> output = data [ : pos ] <EOL> if tf_flags & <NUM_LIT> : <EOL> output += uint32_to_str ( self . ttml_size ) <EOL> pos += <NUM_LIT:4> <EOL> else : <EOL> raise MediaSegmentFilterError ( "<STR_LIT>" ) <EOL> output += data [ pos : ] <EOL> return output <EOL> def process_mfhd ( self , data ) : <EOL> "<STR_LIT>" <EOL> if self . seg_nr is None : <EOL> return data <EOL> else : <EOL> return data [ <NUM_LIT:0> : <NUM_LIT:12> ] + uint32_to_str ( self . seg_nr ) <EOL> def process_trun ( self , data ) : <EOL> "<STR_LIT>" <EOL> flags = str_to_uint32 ( data [ <NUM_LIT:8> : <NUM_LIT:12> ] ) & <NUM_LIT> <EOL> sample_count = str_to_uint32 ( data [ <NUM_LIT:12> : <NUM_LIT:16> ] ) <EOL> pos = <NUM_LIT:16> <EOL> data_offset_present = False <EOL> if flags & <NUM_LIT> : <EOL> data_offset_present = True <EOL> pos += <NUM_LIT:4> <EOL> if flags & <NUM_LIT> : <EOL> pos += <NUM_LIT:4> <EOL> sample_duration_present = flags & <NUM_LIT> <EOL> sample_size_present = flags & <NUM_LIT> <EOL> sample_flags_present = flags & <NUM_LIT> <EOL> sample_comp_time_present = flags & <NUM_LIT> <EOL> duration = <NUM_LIT:0> <EOL> for _ in range ( sample_count ) : <EOL> if sample_duration_present : <EOL> duration += str_to_uint32 ( data [ pos : pos + <NUM_LIT:4> ] ) <EOL> pos += <NUM_LIT:4> <EOL> if sample_size_present : <EOL> pos += <NUM_LIT:4> <EOL> if sample_flags_present : <EOL> pos += <NUM_LIT:4> <EOL> if sample_comp_time_present : <EOL> pos += <NUM_LIT:4> <EOL> self . duration = duration <EOL> output = data [ : <NUM_LIT:16> ] <EOL> if data_offset_present and self . size_change > <NUM_LIT:0> : <EOL> offset = str_to_sint32 ( data [ <NUM_LIT:16> : <NUM_LIT:20> ] ) <EOL> offset += self . size_change <EOL> output += sint32_to_str ( offset ) <EOL> else : <EOL> output += data [ <NUM_LIT:16> : <NUM_LIT:20> ] <EOL> output += data [ <NUM_LIT:20> : ] <EOL> return output <EOL> def process_sidx ( self , data ) : <EOL> "<STR_LIT>" <EOL> if not KEEP_SIDX : <EOL> return "<STR_LIT>" <EOL> output = "<STR_LIT>" <EOL> version = ord ( data [ <NUM_LIT:8> ] ) <EOL> timescale = str_to_uint32 ( data [ <NUM_LIT:16> : <NUM_LIT:20> ] ) <EOL> if version == <NUM_LIT:0> : <EOL> size = str_to_uint32 ( data [ <NUM_LIT:0> : <NUM_LIT:4> ] ) <EOL> sidx_size_expansion = <NUM_LIT:8> <EOL> output += uint32_to_str ( size + sidx_size_expansion ) <EOL> output += data [ <NUM_LIT:4> : <NUM_LIT:8> ] <EOL> output += chr ( <NUM_LIT:1> ) <EOL> output += data [ <NUM_LIT:9> : <NUM_LIT:20> ] <EOL> earliest_presentation_time = str_to_uint32 ( data [ <NUM_LIT:20> : <NUM_LIT> ] ) <EOL> first_offset = str_to_uint32 ( data [ <NUM_LIT> : <NUM_LIT> ] ) <EOL> else : <EOL> output += data [ <NUM_LIT:0> : <NUM_LIT:20> ] <EOL> earliest_presentation_time = str_to_uint64 ( data [ <NUM_LIT:20> : <NUM_LIT> ] ) <EOL> first_offset = str_to_uint64 ( data [ <NUM_LIT> : <NUM_LIT> ] ) <EOL> new_presentation_time = earliest_presentation_time + timescale * self . offset <EOL> output += uint64_to_str ( new_presentation_time ) <EOL> output += uint64_to_str ( first_offset ) <EOL> if version == <NUM_LIT:0> : <EOL> output += data [ <NUM_LIT> : ] <EOL> else : <EOL> output += data [ <NUM_LIT> : ] <EOL> return output <EOL> def process_tfdt_to_64bit ( self , data , output ) : <EOL> """<STR_LIT>""" <EOL> version = ord ( data [ <NUM_LIT:8> ] ) <EOL> tfdt_offset = self . offset * self . track_timescale <EOL> if version == <NUM_LIT:0> : <EOL> self . size_change = <NUM_LIT:4> <EOL> output = uint32_to_str ( str_to_uint32 ( data [ : <NUM_LIT:4> ] ) + self . size_change ) <EOL> output += data [ <NUM_LIT:4> : <NUM_LIT:8> ] <EOL> output += chr ( <NUM_LIT:1> ) <EOL> output += data [ <NUM_LIT:9> : <NUM_LIT:12> ] <EOL> base_media_decode_time = str_to_uint32 ( data [ <NUM_LIT:12> : <NUM_LIT:16> ] ) <EOL> else : <EOL> output = data [ : <NUM_LIT:12> ] <EOL> base_media_decode_time = str_to_uint64 ( data [ <NUM_LIT:12> : <NUM_LIT:20> ] ) <EOL> new_base_media_decode_time = base_media_decode_time + tfdt_offset <EOL> output += uint64_to_str ( new_base_media_decode_time ) <EOL> self . tfdt_value = new_base_media_decode_time <EOL> return output <EOL> def process_tfdt ( self , data ) : <EOL> """<STR_LIT>""" <EOL> version = ord ( data [ <NUM_LIT:8> ] ) <EOL> if self . track_timescale is not None : <EOL> tfdt_offset = self . offset * self . track_timescale <EOL> else : <EOL> tfdt_offset = <NUM_LIT:0> <EOL> if version == <NUM_LIT:0> : <EOL> base_media_decode_time = str_to_uint32 ( data [ <NUM_LIT:12> : <NUM_LIT:16> ] ) <EOL> new_base_media_decode_time = base_media_decode_time + tfdt_offset <EOL> if new_base_media_decode_time < <NUM_LIT> : <EOL> output = data [ : <NUM_LIT:12> ] <EOL> output += uint32_to_str ( new_base_media_decode_time ) <EOL> else : <EOL> self . size_change = <NUM_LIT:4> <EOL> output = uint32_to_str ( str_to_uint32 ( data [ : <NUM_LIT:4> ] ) + self . size_change ) <EOL> output += data [ <NUM_LIT:4> : <NUM_LIT:8> ] <EOL> output += chr ( <NUM_LIT:1> ) <EOL> output += data [ <NUM_LIT:9> : <NUM_LIT:12> ] <EOL> output += uint64_to_str ( new_base_media_decode_time ) <EOL> else : <EOL> output = data [ : <NUM_LIT:12> ] <EOL> base_media_decode_time = str_to_uint64 ( data [ <NUM_LIT:12> : <NUM_LIT:20> ] ) <EOL> new_base_media_decode_time = base_media_decode_time + tfdt_offset <EOL> output += uint64_to_str ( new_base_media_decode_time ) <EOL> self . tfdt_value = new_base_media_decode_time <EOL> return output <EOL> def get_tfdt_value ( self ) : <EOL> "<STR_LIT>" <EOL> return self . tfdt_value <EOL> def get_duration ( self ) : <EOL> "<STR_LIT>" <EOL> return self . duration <EOL> def create_scte35box ( self ) : <EOL> """<STR_LIT>""" <EOL> ad_duration = <NUM_LIT:10> <EOL> if self . scte35_per_minute < <NUM_LIT:1> or self . scte35_per_minute > <NUM_LIT:8> : <EOL> return "<STR_LIT>" <EOL> seg_starttime = self . seg_nr * self . seg_duration <EOL> sec_modulo_minute = seg_starttime % <NUM_LIT> <EOL> minute_start = seg_starttime - sec_modulo_minute <EOL> splice_insert_times = [ minute_start + <NUM_LIT:10> ] <EOL> if self . scte35_per_minute == <NUM_LIT:2> : <EOL> splice_insert_times . append ( minute_start + <NUM_LIT> ) <EOL> elif self . scte35_per_minute == <NUM_LIT:3> : <EOL> splice_insert_times . append ( minute_start + <NUM_LIT> ) <EOL> splice_insert_times . append ( minute_start + <NUM_LIT> ) <EOL> elif self . scte35_per_minute == <NUM_LIT:8> : <EOL> splice_insert_times . append ( minute_start + <NUM_LIT:30> ) <EOL> ad_duration = <NUM_LIT:20> <EOL> found_splice_time = - <NUM_LIT:1> <EOL> splice_time = None <EOL> seg_endtime = seg_starttime + self . seg_duration <EOL> for splice_time in splice_insert_times : <EOL> for pre_warning_time in ( splice_time - <NUM_LIT:6> , splice_time - <NUM_LIT:8> ) : <EOL> if seg_starttime <= pre_warning_time <= seg_endtime : <EOL> found_splice_time = splice_time <EOL> break <EOL> if found_splice_time >= <NUM_LIT:0> : <EOL> break <EOL> if found_splice_time < <NUM_LIT:0> : <EOL> return "<STR_LIT>" <EOL> timescale = <NUM_LIT> <EOL> emsg_id = splice_id = splice_time // <NUM_LIT:10> <EOL> emsg = scte35 . create_scte35_emsg ( timescale , seg_starttime * timescale , found_splice_time * timescale , <EOL> ad_duration * timescale , emsg_id , splice_id ) <EOL> return emsg <EOL> def find_and_process_mdat ( self , data ) : <EOL> "<STR_LIT>" <EOL> pos = <NUM_LIT:0> <EOL> output = "<STR_LIT>" <EOL> while pos < len ( data ) : <EOL> size = str_to_uint32 ( data [ pos : pos + <NUM_LIT:4> ] ) <EOL> boxtype = data [ pos + <NUM_LIT:4> : pos + <NUM_LIT:8> ] <EOL> if boxtype != '<STR_LIT>' : <EOL> output += data [ pos : pos + size ] <EOL> else : <EOL> output += self . update_ttml_mdat ( data [ pos : pos + size ] ) <EOL> pos += size <EOL> return output <EOL> def update_ttml_mdat ( self , data ) : <EOL> "<STR_LIT>" <EOL> ttml_xml = data [ <NUM_LIT:8> : ] <EOL> ttml_out = adjust_ttml_content ( ttml_xml , self . offset , self . seg_nr ) <EOL> self . ttml_size = len ( ttml_out ) <EOL> out_size = self . ttml_size + <NUM_LIT:8> <EOL> return uint32_to_str ( out_size ) + '<STR_LIT>' + ttml_out </s>
