Browse Source

add the mpegtsmod module which looks inside and sees what streams

are available..  the PID demuxer currently isn't fast enough (it's
written in python), but once fixed should be interesting...

[git-p4: depot-paths = "//depot/": change = 858]
v0.3
John-Mark Gurney 18 years ago
parent
commit
be108d0648
2 changed files with 197 additions and 1 deletions
  1. +196
    -0
      mpegtsmod.py
  2. +1
    -1
      pymediaserv

+ 196
- 0
mpegtsmod.py View File

@@ -0,0 +1,196 @@
#!/usr/bin/env python
# Copyright 2006 John-Mark Gurney <gurney_j@resnet.uoregon.edu>
'''MPEG-TS Handling'''

__version__ = '$Change$'
# $Id$

default_audio_lang = 'eng'

import os
import sets

import sys
mpegtspath = '/Users/jgurney/p4/bktrau/info'
if mpegtspath not in sys.path:
sys.path.append(mpegtspath)
import mpegts

from DIDLLite import StorageFolder, VideoItem, Resource
from FSStorage import FSObject, registerklassfun

from twisted.python import log, threadable
from twisted.spread import pb
from twisted.web import resource, server

class _LimitedFile(file):
def __init__(self, *args, **kwargs):
self.__size = kwargs['size']
del kwargs['size']
file.__init__(self, *args, **kwargs)

def remain(self):
pos = self.tell()
if pos > self.__size:
return 0
return self.__size - pos

def read(self, size=-1):
if size < 0:
return file.read(self, self.remain())

return file.read(self, min(size, self.remain()))

def _gennameindexes(chan):
ret = []
d = {}

for i in chan:
t = '%s %s.%s' % (i['name'], i['major'], i['minor'])
ret.append(t)
d[t] = i

return ret, d

class MPEGTSTransfer(pb.Viewable):
def __init__(self, iterable, request):
self.iter = iter(iterable)
self.request = request
request.registerProducer(self, 0)

def resumeProducing(self):
if not self.request:
return
# get data and write to request.
try:
data = self.iter.next()
if data:
# this .write will spin the reactor, calling
# .doWrite and then .resumeProducing again, so
# be prepared for a re-entrant call
self.request.write(data)
except StopIteration:
if self.request:
self.request.unregisterProducer()
self.request.finish()
self.request = None

def pauseProducing(self):
pass

def stopProducing(self):
# close zipfile
self.request = None

# Remotely relay producer interface.

def view_resumeProducing(self, issuer):
self.resumeProducing()

def view_pauseProducing(self, issuer):
self.pauseProducing()

def view_stopProducing(self, issuer):
self.stopProducing()

synchronized = ['resumeProducing', 'stopProducing']

threadable.synchronize(MPEGTSTransfer)

class MPEGTSResource(resource.Resource):
isLeaf = True

def __init__(self, iter_):
resource.Resource.__init__(self)

self.iter = iter_

def render(self, request):
request.setHeader('content-type', 'video/mpeg')

if request.method == 'HEAD':
return ''

# return data
MPEGTSTransfer(self.iter, request)
# and make sure the connection doesn't get closed
return server.NOT_DONE_YET

class MPEGTS(FSObject, VideoItem):
def __init__(self, *args, **kwargs):
path = kwargs['path']
del kwargs['path']
self.tvct = kwargs['tvct']
del kwargs['tvct']

log.msg('MPEGTS tvct:', self.tvct)
kwargs['content'] = MPEGTSResource(
mpegts.iteravpids(mpegts.TSPStream(open(path)),
sum(mpegts.getaudiovideopids(self.tvct['PMT']), [])))
VideoItem.__init__(self, *args, **kwargs)
FSObject.__init__(self, path)

self.url = '%s/%s' % (self.cd.urlbase, self.id)
self.res = Resource(self.url, 'http-get:*:video/mpeg:*')

def doUpdate(self):
pass

class MultiMPEGTS(FSObject, StorageFolder):
def __init__(self, *args, **kwargs):
path = kwargs['path']
del kwargs['path']

StorageFolder.__init__(self, *args, **kwargs)
FSObject.__init__(self, path)

# mapping from path to objectID
self.pathObjmap = {}

def doUpdate(self):
f = mpegts.TSPStream(_LimitedFile(self.FSpath,
size= 2*1024*1024))
self.tvct = mpegts.GetTVCT(f)

doupdate = False
origchildren, toindex = _gennameindexes(self.tvct['channels'])
children = sets.Set(origchildren)
for i in self.pathObjmap.keys():
if i not in children:
doupdate = True
# delete
self.cd.delItem(self.pathObjmap[i])
del self.pathObjmap[i]

for i in origchildren:
if i in self.pathObjmap:
continue

# new object
self.pathObjmap[i] = self.cd.addItem(self.id, MPEGTS,
i, path = self.FSpath, tvct = toindex[i])
doupdate = True

if doupdate:
StorageFolder.doUpdate(self)

def detectmpegts(path, fobj):
try:
f = mpegts.TSPStream(_LimitedFile(path, size= 2*1024*1024))
tvct = mpegts.GetTVCT(f)
except:
import traceback
traceback.print_exc(file=log.logfile)
raise

log.msg('tvct:', tvct)
if len(tvct['channels']) == 1:
return None, None
return MPEGTS, { 'path': path, 'tvct': tvct['channels'][0] }
elif len(tvct['channels']) > 1:
return MultiMPEGTS, { 'path': path }

return None, None

registerklassfun(detectmpegts)

+ 1
- 1
pymediaserv View File

@@ -25,7 +25,7 @@ def tryloadmodule(mod):
pass

# ZipStorage w/ tar support should be last as it will gobble up empty files.
modules = [ 'dvd', 'shoutcast', 'ZipStorage' ]
modules = [ 'dvd', 'mpegtsmod', 'shoutcast', 'ZipStorage' ]
modmap = {}
for i in modules:
modmap[i] = tryloadmodule(i)


Loading…
Cancel
Save