|
|
@@ -0,0 +1,115 @@ |
|
|
|
#!/usr/bin/env python |
|
|
|
# Copyright 2009 John-Mark Gurney <jmg@funkthat.com> |
|
|
|
'''MPEG-TS clip''' |
|
|
|
|
|
|
|
__version__ = '$Change: 1308 $' |
|
|
|
# $Id: //depot/python/pymeds/main/shoutcast.py#22 $ |
|
|
|
|
|
|
|
import bisect |
|
|
|
import email |
|
|
|
import os.path |
|
|
|
|
|
|
|
from DIDLLite import VideoItem, Resource |
|
|
|
from FSStorage import registerklassfun |
|
|
|
|
|
|
|
from twisted.web import static |
|
|
|
|
|
|
|
class ClipProxyFile: |
|
|
|
def __init__(self, f, p): |
|
|
|
self.fp = open(f) |
|
|
|
self.p = p |
|
|
|
self.pos = 0 |
|
|
|
lp = p[-1] |
|
|
|
self.size = lp[0] + lp[1] |
|
|
|
|
|
|
|
def read(self, s=None): |
|
|
|
if s is None: |
|
|
|
s = self.size - self.pos |
|
|
|
|
|
|
|
p = bisect.bisect_right(self.p, (self.pos,)) |
|
|
|
if p > 0: |
|
|
|
p -= 1 |
|
|
|
# We might be able to do this with proper construction of |
|
|
|
# self.p, but this is easier. |
|
|
|
r = [] |
|
|
|
fp = self.fp |
|
|
|
records = iter(self.p[p:]) |
|
|
|
while s: |
|
|
|
rec = records.next() |
|
|
|
diff = self.pos - rec[0] |
|
|
|
rlen = min(s, rec[1] - diff) |
|
|
|
fp.seek(rec[2] + diff) |
|
|
|
r.append(fp.read(rlen)) |
|
|
|
s -= rlen |
|
|
|
self.pos += rlen |
|
|
|
|
|
|
|
return ''.join(r) |
|
|
|
|
|
|
|
def close(self): |
|
|
|
self.fp.close() |
|
|
|
|
|
|
|
def seek(self, p, d=0): |
|
|
|
assert d == 0 |
|
|
|
self.pos = p |
|
|
|
if self.pos > self.size: |
|
|
|
self.pos = self.size |
|
|
|
|
|
|
|
def tell(self): |
|
|
|
return self.pos |
|
|
|
|
|
|
|
class ClipProxy(static.File): |
|
|
|
isLeaf = True |
|
|
|
|
|
|
|
synchronized = [ 'parsefile', 'getsize', 'open' ] |
|
|
|
|
|
|
|
def __init__(self, f, *args): |
|
|
|
self.__mtime = None |
|
|
|
static.File.__init__(self, f, *args) |
|
|
|
self.parsefile(self.path) |
|
|
|
|
|
|
|
def parsefile(self, f): |
|
|
|
if self.getModificationTime() == self.__mtime: |
|
|
|
return |
|
|
|
|
|
|
|
self.__mtime = self.getModificationTime() |
|
|
|
i = email.message_from_file(open(f)) |
|
|
|
self.origfile = i['file'] |
|
|
|
self.date = eval(i['datetuple'], { '__builtins__': {} }) |
|
|
|
# date is UTC |
|
|
|
p = [ map(int, x.split()) for x in i.get_payload().split('\n') if x ] |
|
|
|
pos = 0 |
|
|
|
self.pos = par = [] |
|
|
|
for j in p: |
|
|
|
l = j[1] - j[0] + 188 |
|
|
|
par.append((pos, l, j[0])) |
|
|
|
pos += l |
|
|
|
self.__size = pos |
|
|
|
|
|
|
|
def getsize(self): |
|
|
|
return self.__size |
|
|
|
|
|
|
|
def open(self): |
|
|
|
return ClipProxyFile(self.origfile, self.pos) |
|
|
|
|
|
|
|
def restat(self): |
|
|
|
static.File.restat(self) |
|
|
|
self.parsefile(self.path) |
|
|
|
|
|
|
|
class ClipFile(VideoItem): |
|
|
|
def __init__(self, *args, **kwargs): |
|
|
|
file = kwargs.pop('file') |
|
|
|
mimetype = 'video/mpeg' |
|
|
|
kwargs['content'] = ClipProxy(file, mimetype) |
|
|
|
VideoItem.__init__(self, *args, **kwargs) |
|
|
|
self.url = '%s/%s' % (self.cd.urlbase, self.id) |
|
|
|
self.res = Resource(self.url, 'http-get:*:%s:*' % mimetype) |
|
|
|
|
|
|
|
def detectclipfile(origpath, fobj): |
|
|
|
path = os.path.basename(origpath) |
|
|
|
ext = os.path.splitext(path)[1] |
|
|
|
if ext == '.clip': |
|
|
|
return ClipFile, { 'file': origpath } |
|
|
|
|
|
|
|
return None, None |
|
|
|
|
|
|
|
registerklassfun(detectclipfile) |