def parse_private_upid_SBSB(bites, upid_length): bitbin = BitBin(bites) return { "private_cni": hex(bitbin.asint(16)), "private_version": bitbin.asint(8), "private_transmission_id": struct.unpack("<Q", bitbin.asbites(64))[0], "private_product_code": struct.unpack("<Q", bitbin.asbites(64))[0], "private_web_publication_key": bitbin.astext(25 * 8), }
def decode(self): """ decode SCTE35 Time Descriptor """ bitbin = BitBin(self.bites) self.parse_id(bitbin) self.tai_seconds = bitbin.asint(48) self.tai_ns = bitbin.asint(32) self.utc_offset = bitbin.asint(16)
def decode(self): """ decode SCTE35 Dtmf Descriptor """ bitbin = BitBin(self.bites) self.parse_id(bitbin) self.preroll = bitbin.asint(8) self.dtmf_count = d_c = bitbin.asint(3) bitbin.forward(5) while d_c: d_c -= 1 self.dtmf_chars.append(bitbin.astext(8))
def parse_pusi(self, packet): bitbin = BitBin(packet) if bitbin.asint(24) != 1: return if bitbin.asint(8) in self.NON_PTS_STREAM_IDS: return # PES_packet_length = bitbin.forward(16) if bitbin.asint(2) != 2: return bitbin.forward(6) ''' PES_scramble_control = bitbin.asint(2) PES_priority = bitbin.asint(1) data_align_ind = bitbin.asint(1) copyright = bitbin.asint(1) orig_or_copy = bitbin.asint(1) ''' if bitbin.asint(2) != 2: return bitbin.forward(14) if bitbin.asint(4) != 2: return a = bitbin.asint(3) << 30 bitbin.forward(1) b = bitbin.asint(15) << 15 bitbin.forward(1) c = bitbin.asint(15) d = (a + b + c) / 90000.0 fpts = f'PTS \033[92m{d:.3f}\033[0m ' print(f'\r{fpts}', end="\r") return
def decode(self): """ decode SCTE35 Avail Descriptor """ bitbin = BitBin(self.bites) self.parse_id(bitbin) self.provider_avail_id = bitbin.asint(32)
def decode(self): """ Decode SCTE35 Audio Descriptor """ bitbin = BitBin(self.bites) self.parse_id(bitbin) self.audio_count = a_c = bitbin.asint(4) bitbin.forward(4) while a_c: a_c -= 1 comp = {} comp["component_tag"] = bitbin.asint(8) comp["ISO_code="] = bitbin.asint(24) comp["bit_stream_mode"] = bitbin.asint(3) comp["num_channels"] = bitbin.asint(4) comp["full_srvc_audio"] = bitbin.asflag(1) self.components.append(comp)
def parse_tspacket(packet, packetnum): three_bytes = BitBin(packet[:3]) tei = three_bytes.asflag(1) pusi = three_bytes.asflag(1) ts_priority = three_bytes.asflag(1) pid = three_bytes.asint(13) if pusi: parse_pes(packet, packetnum)
def _program_association_table(self, pkt): """ parse program association table ( pid 0 ) to program to program table pid mappings. """ sectionlen = (pkt[6] & 15 << 8) | pkt[7] pkt = pkt[13:(sectionlen + 5)] bitbin = BitBin(pkt) slib = sectionlen << 3 slib -= 40 while slib > 32: program_number = bitbin.asint(16) bitbin.forward(3) if program_number == 0: bitbin.forward(13) else: self._pmt_pids.add(bitbin.asint(13)) slib -= 32 bitbin.forward(32)
def decode(self, bites): bitbin = BitBin(bites) self.table_id = bitbin.ashex(8) if self.table_id != "0xfc": to_stderr("splice info section table id should be 0xfc") self.section_syntax_indicator = bitbin.asflag(1) self.private = bitbin.asflag(1) self.reserved = bitbin.ashex(2) if self.reserved != "0x3": to_stderr("splice info section reserved should be 0x3") self.section_length = bitbin.asint(12) self.protocol_version = bitbin.asint(8) if self.protocol_version != 0: to_stderr("splice info section protocol version should be 0") self.encrypted_packet = bitbin.asflag(1) self.encryption_algorithm = bitbin.asint(6) self.pts_adjustment = bitbin.as90k(33) self.cw_index = bitbin.ashex(8) self.tier = bitbin.ashex(12) self.splice_command_length = bitbin.asint(12) self.splice_command_type = bitbin.asint(8) self.descriptor_loop_length = 0
def decode(self, bites): bitbin = BitBin(bites) self.table_id = bitbin.ashex(8) if self.table_id != '0xfc': raise ValueError('splice_info_section.table_id should be 0xfc') self.section_syntax_indicator = bitbin.asflag(1) self.private = bitbin.asflag(1) self.reserved = bitbin.ashex(2) if self.reserved != '0x3': raise ValueError('splice_info_section.reserved should be 0x3') self.section_length = bitbin.asint(12) self.protocol_version = bitbin.asint(8) if self.protocol_version != 0: raise ValueError( 'splice_info_section.protocol_version should be 0') self.encrypted_packet = bitbin.asflag(1) self.encryption_algorithm = bitbin.asint(6) self.pts_adjustment = bitbin.as90k(33) self.cw_index = bitbin.ashex(8) self.tier = bitbin.ashex(12) self.splice_command_length = bitbin.asint(12) self.splice_command_type = bitbin.asint(8) self.descriptor_loop_length = 0
def decode(self): """ SpliceInsert.decode """ bitbin = BitBin(self.bites) start = bitbin.idx self.splice_event_id = bitbin.asint(32) self.splice_event_cancel_indicator = bitbin.asflag(1) bitbin.forward(7) if not self.splice_event_cancel_indicator: self._decode_flags(bitbin) if self.program_splice_flag: if not self.splice_immediate_flag: self._decode_pts(bitbin) else: self._decode_components(bitbin) if not self.splice_immediate_flag: self._decode_pts(bitbin) if self.duration_flag: self._decode_break(bitbin) self.unique_program_id = bitbin.asint(16) self.avail_num = bitbin.asint(8) self.avail_expected = bitbin.asint(8) self._set_len(start, bitbin.idx)
def parse_pes(packet, packetnum): bb = BitBin(packet[3:]) if bb.asint(24) == 1 and bb.asint(8) not in NON_PTS_STREAM_IDS: PES_packet_length = bb.asint(16) if bb.asint(2) == 2: bb.asint(6) if bb.asint(2) in [2, 3]: bb.asint(14) if bb.asint(4) in [2, 3]: to33 = bb.asint(3) << 30 bb.asflag(1) to30 = bb.asint(15) << 15 bs.asflag(1) to15 = bb.asint(15) d = to33 + to30 + to15 print(f" PTS {d/90000:.6f} on Packet {packetnum}")
class Splice: descriptor_map = { 0: Avail_Descriptor, 1: Dtmf_Descriptor, 2: Segmentation_Descriptor, 3: Time_Descriptor, 4: Audio_Descriptor } command_map = { 0: Splice_Null, 4: Splice_Schedule, 5: Splice_Insert, 6: Time_Signal, 7: Bandwidth_Reservation, 255: Private_Command } def __init__(self, mesg): mesg = self.mkbits(mesg) self.bitbin = BitBin(mesg) self.descriptors = [] self.info_section = None self.command = None self.do() def do(self): self.info_section = Splice_Info_Section() self.info_section.decode(self.bitbin) self.set_splice_command() self.descriptorloop() self.info_section.crc = self.bitbin.ashex(32) def descriptorloop(self): self.info_section.descriptor_loop_length = self.bitbin.asint(16) dll = self.info_section.descriptor_loop_length tag_plus_header_size = 2 # 1 byte for descriptor_tag, 1 byte for header? while dll > 0: try: sd = self.set_splice_descriptor() sdl = sd.descriptor_length self.descriptors.append(sd) except: sdl = 0 bit_move = sdl + tag_plus_header_size dll -= bit_move def kvprint(self, obj): print(f'{json.dumps(vars(obj))}') def sectionstart(self, section_name): print(f'{section_name}') def mkbits(self, s): if s[:2].lower() == '0x': s = s[2:] if s[:2].lower() == 'fc': return bytes.fromhex(s) try: return b64decode(s) except: return s def set_splice_command(self): sct = self.info_section.splice_command_type if sct not in self.command_map.keys(): raise ValueError('unknown splice command type') self.command = self.command_map[sct]() self.command.decode(self.bitbin) def set_splice_descriptor(self): # splice_descriptor_tag 8 uimsbf tag = self.bitbin.asint(8) if tag in self.descriptor_map.keys(): return self.descriptor_map[tag](self.bitbin, tag) def show_info_section(self): if self.info_section and self.command: self.sectionstart('Splice Info Section') self.kvprint(self.info_section) else: return False def show_command(self): if self.command: self.sectionstart('Splice Command') self.kvprint(self.command) else: return False def show_descriptors(self): if len(self.descriptors) > 0: for d in self.descriptors: idx = self.descriptors.index(d) self.sectionstart(f'Splice Descriptor {idx}') self.kvprint(d) def show(self): if self.info_section and self.command: self.sectionstart('[SCTE 35 Message]') self.show_info_section() self.show_command() self.show_descriptors() else: return False