# -*- Mode: Python -*- import struct import sys def as_binary (n, width): r = [] bit = 1 << width while width: width -= 1 bit >>= 1 if n & bit: r.append ('1') else: r.append ('0') return ''.join (r) #print as_binary (get_bits (0xf00f, 4, 8), 16) #print as_binary (get_bits (0x0ff0, 4, 8), 16) def get_bits (x, start, nbits): r = 0 for i in range (nbits): if x & (1<<(start+i)): r |= 1<>= 9+6 return n def progressive_divide (n, parts): result = [] for part in parts: n, rem = divmod (n, part) result.append (rem) result.append (n) return result last_pcr = 0 def parse_adaptation (p): global last_pcr flen = ord(p[0]) x = ord(p[1]) disc = get_bits (x, 7, 1) rand = get_bits (x, 6, 1) esp = get_bits (x, 5, 1) pcr = get_bits (x, 4, 1) opcr = get_bits (x, 3, 1) splc = get_bits (x, 2, 1) tpd = get_bits (x, 1, 1) afe = get_bits (x, 0, 1) if tpd: sys.stderr.write ('> %s\n' % (pretty (p))) if pcr: pcr = grok_pcr (p[2:8]) # convert to hh:mm:ss sec = pcr / 90000 # 90kHz clock ss, mm, hh, dd = progressive_divide (sec, (60, 60, 24)) if dd: sys.stderr.write ('%d %02d:%02d:%02d\n' % (dd, hh, mm, ss)) if sec < last_pcr: ss, mm, hh, dd = progressive_divide (last_pcr, (60, 60, 24)) sys.stderr.write ('? %d %02d:%02d:%02d\n' % (dd, hh, mm, ss)) last_pcr = sec #sys.stderr.write (as_binary (pcr, 34)) #import pdb; pdb.set_trace() if opcr: opcr = grok_pcr (p[8:14]) sys.stderr.write (' ' + as_binary (opcr, 34) + '\n') return locals() #unsigned char SonyA1::year() { return BCD( GetBits(352, 8) ); } #unsigned char SonyA1::month() { return BCD( GetBits(347, 5) ); } #unsigned char SonyA1::day() { return BCD( GetBits(338, 6) ); } #unsigned char SonyA1::hour() { return BCD( GetBits(386, 6) ); } #unsigned char SonyA1::minute() { return BCD( GetBits(377, 7) ); } #unsigned char SonyA1::second() { return BCD( GetBits(369, 7) ); } # #unsigned char SonyA1::timecode_hour() { return BCD( GetBits(322, 6) ); } #unsigned char SonyA1::timecode_minute() { return BCD( GetBits(313, 7) ); } #unsigned char SonyA1::timecode_second() { return BCD( GetBits(305, 7) ); } #unsigned char SonyA1::timecode_frame() { return BCD( GetBits(298, 6) ); } #bool SonyA1::scene_start() { return !GetBits(394, 1); } # ^ 8,5,6 def decode_pat (p): if ord(p[1]) in (0x70, 0x73): import pdb; pdb.set_trace() def pretty (p): return ''.join ('%02x' % ord(ch) for ch in p) def parse_ts (f, files): pause_mode = False while 1: header = f.read (4) if not header: break elif header[0] != 'G': break else: byte23 = struct.unpack ('>h', header[1:3])[0] #print '%16s' % (as_binary (byte23, 16),) tei = get_bits (byte23, 15, 1) pus = get_bits (byte23, 14, 1) tp = get_bits (byte23, 13, 1) pid = get_bits (byte23, 0, 13) #print '%s %s %s %2x' % (tei, pus, tp, pid) byte4 = ord (header[3]) #print 'byte4', as_binary (byte4, 8) scramble = get_bits (byte4, 6, 2) adapt = get_bits (byte4, 5, 1) pde = get_bits (byte4, 4, 1) continuity = get_bits (byte4, 0, 4) #print '%s %s %s %d' % (scramble, adapt, pde, continuity) #if adapt: # raise ValueError ("adaptation field not handled yet") #elif not pde: # raise ValueError ("no data??") #else: packet = f.read (184) if pid == 2065: sys.stderr.write ('%d %r\n' % (adapt, pretty (packet[63:],))) if False and adapt: #sys.stderr.write ('[%5d] ' % (pid,)) parse_adaptation (packet) else: #sys.stderr.write ('.') pass if 0: if not files.has_key (pid): files[pid] = open ('%d.ts' % (pid,), 'wb') #files[pid].write (header) files[pid].write (packet) if pus and packet[0] == '\xa0': info = packet[-23:] sys.stderr.write ('[%5d] %s\n' % (pid, pretty (info))) #sys.stderr.write ('[%5d] %r\n' % (pid, info)) return files def print_pcr (pcr): sec = pcr / 90000 # 90kHz clock ss, mm, hh, dd = progressive_divide (sec, (60, 60, 24)) sys.stderr.write ('%d %02d:%02d:%02d\n' % (dd, hh, mm, ss)) def yrgl (s): return ''.join ([as_binary (ord(ch),8) for ch in s]) MB = 1024 * 1024 def parse_ts2 (f): last = 400 n = 0 while 1: packet = f.read (188) n += 188 if not packet: break elif packet[0] != 'G': break else: byte23 = struct.unpack ('>h', packet[1:3])[0] #pus = get_bits (byte23, 14, 1) pus = byte23 & 16384 pid = byte23 & 0x1fff if pid == 2065: # and packet[4] == '\xe0': info2 = packet[109:109+3] if info2 != last: sys.stderr.write ('%5d %2x %s %r\n' % (n/MB, ord(packet[4]), pretty(info2), pretty (packet[63:],))) last = info2 if False and pus and packet[4] == '\xa0': info = packet[-23:] #if info[-1] == '\x00': #sys.stderr.write ('%5d %s\n' % (n/MB, pretty (info))) sys.stderr.write ('%5d %s\n' % (n/MB, yrgl (info[8:16]))) # 11:34:51 => 11:35:03 # d1b4d130 => 84b5d130 # # 11010001 10110100 11010001 0011 0000 # 5 1 3 4 1 1 # 10000100 10110101 11010001 0011 0000 # 0 4 3 5 1 1 # # def bcd (ch, bits0, bits1): return ((ord(ch)>>4) & bits0) * 10 + (ord(ch) & bits1) def grok_hms (hms): ss = bcd (hms[0], 0x7, 0xf) mm = bcd (hms[1], 0x7, 0xf) hh = bcd (hms[2], 0x3, 0xf) return hh, mm, ss # d4e706 # 11010100 11100111 00000110 # dd mm yy # 14 07 06 # xx001111 xxx23333 44445555 # def grok_ymd (ymd): dd = bcd (ymd[0], 3, 15) mm = bcd (ymd[1], 1, 15) yy = bcd (ymd[2], 15, 15) return 2000 + yy, mm, dd MB = 1024 * 1024 def parse_ts3 (f): last = (None, None) n = 0 num = 0 fo = None while 1: packet = f.read (188) n += 188 if not packet: break elif packet[0] != 'G': break else: byte23 = struct.unpack ('>h', packet[1:3])[0] #pus = get_bits (byte23, 14, 1) pus = byte23 & 16384 pid = byte23 & 0x1fff if pid == 2065: byte4 = ord (packet[3]) adapt = get_bits (byte4, 5, 1) ymd = packet[109:112] hms = packet[113:117] if True: #info2 != last[0]: sys.stderr.write ('%5d %d %s %r\n' % (n/MB, adapt, grok_ymd(ymd), grok_hms(hms))) #fo = open ('clip_%03d.%s.m2t' % (num,pretty(info2)), 'wb') num += 1 last = ymd, packet if pus and packet[4] == '\xa0': info = packet[-23:] if info[-1] == '\x00': sys.stderr.write ('%5d %s\n' % (n/MB, pretty (info))) sys.stderr.write ('%5d %s\n' % (n/MB, pretty (last[1][63:]))) #if fo: # fo.write (packet) if __name__ == '__main__': if 0: files = {} try: parse_ts (open (sys.argv[1], 'rb'), files) finally: for pid, file in files.iteritems(): file.close() else: parse_ts3 (open (sys.argv[1], 'rb'))