diff --git a/mpegtsmod.py b/mpegtsmod.py index 97fd86d..00563a1 100644 --- a/mpegtsmod.py +++ b/mpegtsmod.py @@ -5,6 +5,7 @@ __version__ = '$Change$' # $Id$ +tsselpypath = '/Users/jgurney/p4/bktrau/info/tssel.py' default_audio_lang = 'eng' import os @@ -15,12 +16,14 @@ mpegtspath = '/Users/jgurney/p4/bktrau/info' if mpegtspath not in sys.path: sys.path.append(mpegtspath) import mpegts +import tssel from DIDLLite import StorageFolder, VideoItem, Resource from FSStorage import FSObject, registerklassfun from twisted.python import log, threadable from twisted.spread import pb +from twisted.internet import process, protocol, reactor from twisted.web import resource, server class _LimitedFile(file): @@ -97,13 +100,65 @@ class MPEGTSTransfer(pb.Viewable): threadable.synchronize(MPEGTSTransfer) +class DynamTSTransfer(protocol.ProcessProtocol): + def __init__(self, path, pmt, *pids): + self.path = path + self.pmt = pmt + self.pids = pids + + def outReceived(self, data): + self.request.write(data) + + def outConnectionLost(self): + if self.request: + self.request.unregisterProducer() + self.request.finish() + self.request = None + + def errReceived(self, data): + pass + #log.msg(data) + + def stopProducing(self): + if self.request: + self.request.unregisterProducer() + self.request.finish() + + if self.proc: + self.proc.loseConnection() + self.proc.signalProcess('INT') + + self.request = None + self.proc = None + + pauseProducing = lambda x: x.proc.pauseProducing() + resumeProducing = lambda x: x.proc.resumeProducing() + + def render(self, request): + path = self.path + pmt = self.pmt + pids = self.pids + self.request = request + + request.setHeader('content-type', 'video/mpeg') + if request.method == 'HEAD': + return '' + + args = [ 'tssel.py', path, str(pmt), ] + map(str, pids) + self.proc = process.Process(reactor, tsselpypath, args, + None, None, self) + self.proc.closeStdin() + request.registerProducer(self, 1) + + return server.NOT_DONE_YET + class MPEGTSResource(resource.Resource): isLeaf = True - def __init__(self, iter_): + def __init__(self, *args): resource.Resource.__init__(self) - self.iter = iter_ + self.args = args def render(self, request): request.setHeader('content-type', 'video/mpeg') @@ -112,20 +167,19 @@ class MPEGTSResource(resource.Resource): return '' # return data - MPEGTSTransfer(self.iter, request) - # and make sure the connection doesn't get closed - return server.NOT_DONE_YET + return DynamTSTransfer(*self.args).render(request) class MPEGTS(FSObject, VideoItem): def __init__(self, *args, **kwargs): - path = kwargs['path'] + self.path = path = kwargs['path'] del kwargs['path'] - self.tvct = kwargs['tvct'] + self.tvct = tvct = kwargs['tvct'] del kwargs['tvct'] - kwargs['content'] = MPEGTSResource( - mpegts.iteravpids(mpegts.TSPStream(open(path)), - sum(mpegts.getaudiovideopids(self.tvct['PMT']), []))) + #log.msg('tvct w/ keys:', tvct, tvct.keys()) + + kwargs['content'] = MPEGTSResource(path, tvct['PMTpid'], + *sum(mpegts.getaudiovideopids(tvct['PMT']), [])) VideoItem.__init__(self, *args, **kwargs) FSObject.__init__(self, path) @@ -166,6 +220,12 @@ class MultiMPEGTS(FSObject, StorageFolder): continue # new object + if toindex[i]['prog_num'] == 0: + log.msg('bogus:', toindex[i]) + continue + + #log.msg('real tvct:', toindex[i], toindex.keys(), + self.tvct) self.pathObjmap[i] = self.cd.addItem(self.id, MPEGTS, i, path = self.FSpath, tvct = toindex[i]) doupdate = True @@ -178,10 +238,10 @@ def detectmpegts(path, fobj): tvct = mpegts.GetTVCT(f) if len(tvct['channels']) == 1: - return None, None + #return None, None # We might reenable this once we have pid filtering working # fast enough. - #return MPEGTS, { 'path': path, 'tvct': tvct['channels'][0] } + return MPEGTS, { 'path': path, 'tvct': tvct['channels'][0] } elif len(tvct['channels']) > 1: return MultiMPEGTS, { 'path': path }