#!/usr/bin/env python # # Very simple looped file output via various formats for testing # purposes # import os, sys, time import socket, struct from optparse import OptionParser # Cmd line optp = OptionParser() optp.add_option('-p', '--protocol', default='udp') optp.add_option('-d', '--debug', default=False, action='store_true') optp.add_option('--port', default=9983, type='int') optp.add_option('-i', '--ipaddr', default='127.0.0.1') (opts,args) = optp.parse_args() DEBUG = opts.debug PKT_SIZE = 188 * 200 # Debug def out ( pre, msg ): print '%0.3f %s: %s' % (time.time(), pre, msg) def debug ( msg ): if DEBUG: out('D', msg) def info ( msg ): out('I', msg) # Extract PCR def extract_pcr ( tsb, pcr_pid ): while len(tsb) >= 188: pkt = map(ord, tsb[:16]) tsb = tsb[188:] # TODO: TSB resync # Errors if pkt[0] != 0x47 or pkt[1] & 0x80: continue # PID pid = ((pkt[1] & 0x1f) << 8) | pkt[2] #print time.time() #print '%04X %d' % (pid, pid) #print ' '.join(map(lambda x: '%02X' % x, pkt)) # Not PCR if pcr_pid and pcr_pid != pid: continue # PCR if pkt[3] & 0x20 and pkt[4] and pkt[5] == 0x10: #print 'PCR' pcr = pkt[6] << 25 pcr = pcr + (pkt[7] << 17) pcr = pcr + (pkt[8] << 9) pcr = pcr + (pkt[9] << 1) pcr = pcr + ((pkt[10] >> 7) & 0x1) pcr_pid = pid #print pcr return (pcr_pid, pcr) return (None, None) # Loop file def output_file ( path, cb ): fp = open(path) pcr_pid = None pcr_last = None pcr_init = None pcr_rtc = None while True: if not fp: info('open') fp = open(path) pcr_last = pcr_init = pcr_rtc = None tsb = fp.read(PKT_SIZE) # EOF if len(tsb) != PKT_SIZE: info('close') fp.close() fp = None # Extract PCR (pid, pcr) = extract_pcr(tsb, pcr_pid) if pid: pcr_pid = pid debug('%d %d' % (pid, pcr)) # Wait if pcr_init: #debug('checking') d = pcr - pcr_init d = d / 90000.0 d = d + pcr_rtc if d > time.time(): s = d - time.time() debug('wait %f' % s) time.sleep(s) else: print 'behind' else: pcr_init = pcr pcr_rtc = time.time() # Send if cb: cb(tsb) # Unicast if opts.protocol == 'http': pass # Multicast elif opts.protocol in [ 'udp', 'rtp' ]: g = opts.ipaddr p = opts.port # Setup multicast connection a = socket.getaddrinfo(g, None)[0] s = socket.socket(a[0], socket.SOCK_DGRAM) # Set Time-to-live (optional) ttl = struct.pack('@i', 2) if a[0] == socket.AF_INET: # IPv4 s.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, ttl) else: s.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_MULTICAST_HOPS, ttl) # UDP output def udp_out ( tsb ): debug('send %d' % len(tsb)) try: s.sendto(tsb, (a[4][0], p)) except: pass debug('sent') # RTP output def rtp_out ( tsb ): debug('send %d' % len(tsb)) rtp = '\x80\x21' rtp = rtp + ('\x00' * 2) # TVH ignores seqnum rtp = rtp + ('\x00' * 4) # TVH ignores timestamp rtp = rtp + ('\x00' * 4) # TVH ignores SSRC #rtp = rtp + ('\x00' * 4) # TVH ignores CSRC # TODO: add CC and extension for testing rtp = rtp + tsb try: s.sendto(rtp, (a[4][0], p)) except: pass debug('sent') # Process if opts.protocol == 'udp': output_file(args[0], udp_out) else: output_file(args[0], rtp_out)