mirror of
https://github.com/python/cpython.git
synced 2025-07-30 06:34:15 +00:00
Created Vedit.py, the video editor. This uses the classes in Viewer.py.
Viewer.py in turn requires changes to VFile.py (unfortunately that file is now a complete mess...).
This commit is contained in:
parent
e1b4d7ce14
commit
9ee7e15966
6 changed files with 1080 additions and 217 deletions
|
@ -100,6 +100,10 @@ Vtime.py (unrelated to vtime!!!) Copy a video file,
|
||||||
manipulating the time codes (e.g. faster/slower, or
|
manipulating the time codes (e.g. faster/slower, or
|
||||||
regenerate time codes, or drop frames too close apart)
|
regenerate time codes, or drop frames too close apart)
|
||||||
|
|
||||||
|
Vedit.py interactive video editing program
|
||||||
|
|
||||||
|
Viewer.py two viewer classes used by Vedit
|
||||||
|
|
||||||
|
|
||||||
The following are C programs, either for efficiency or because they
|
The following are C programs, either for efficiency or because they
|
||||||
need to link with a C library:
|
need to link with a C library:
|
||||||
|
|
|
@ -52,116 +52,12 @@ def conv_rgb8(rgb,d1,d2):
|
||||||
# xorigin, yorigin
|
# xorigin, yorigin
|
||||||
# fallback
|
# fallback
|
||||||
|
|
||||||
class VinFile:
|
|
||||||
|
|
||||||
# init() and initfp() raise Error if the header is bad.
|
|
||||||
# init() raises whatever open() raises if the file can't be opened.
|
|
||||||
|
|
||||||
def init(self, filename):
|
# XXX it's a total mess now -- VFile is a new base class
|
||||||
if filename == '-':
|
# XXX to support common functionality (e.g. showframe)
|
||||||
return self.initfp(sys.stdin, filename)
|
|
||||||
return self.initfp(open(filename, 'r'), filename)
|
|
||||||
|
|
||||||
def initfp(self, fp, filename):
|
|
||||||
self.colormapinited = 0
|
|
||||||
self.magnify = 1.0
|
|
||||||
self.xorigin = self.yorigin = 0
|
|
||||||
self.fallback = 1
|
|
||||||
self.skipchrom = 0
|
|
||||||
self.fp = fp
|
|
||||||
self.filename = filename
|
|
||||||
self.quiet = 0
|
|
||||||
#
|
|
||||||
line = self.fp.readline()
|
|
||||||
if line == 'CMIF video 1.0\n':
|
|
||||||
self.version = 1.0
|
|
||||||
elif line == 'CMIF video 2.0\n':
|
|
||||||
self.version = 2.0
|
|
||||||
elif line == 'CMIF video 3.0\n':
|
|
||||||
self.version = 3.0
|
|
||||||
else:
|
|
||||||
raise Error, self.filename + ': bad video format'
|
|
||||||
#
|
|
||||||
if self.version < 2.0:
|
|
||||||
self.c0bits, self.c1bits, self.c2bits = 8, 0, 0
|
|
||||||
self.chrompack = 0
|
|
||||||
self.offset = 0
|
|
||||||
self.format = 'grey'
|
|
||||||
elif self.version == 2.0:
|
|
||||||
line = self.fp.readline()
|
|
||||||
try:
|
|
||||||
self.c0bits, self.c1bits, self.c2bits, \
|
|
||||||
self.chrompack = eval(line[:-1])
|
|
||||||
if self.c1bits or self.c2bits:
|
|
||||||
self.format = 'yiq'
|
|
||||||
else:
|
|
||||||
self.format = 'grey'
|
|
||||||
self.offset = 0
|
|
||||||
except:
|
|
||||||
raise Error, \
|
|
||||||
self.filename + ': bad 2.0 color info'
|
|
||||||
elif self.version == 3.0:
|
|
||||||
line = self.fp.readline()
|
|
||||||
try:
|
|
||||||
self.format, rest = eval(line[:-1])
|
|
||||||
if self.format == 'rgb':
|
|
||||||
self.offset = 0
|
|
||||||
self.c0bits = 0
|
|
||||||
self.c1bits = 0
|
|
||||||
self.c2bits = 0
|
|
||||||
self.chrompack = 0
|
|
||||||
elif self.format == 'grey':
|
|
||||||
self.offset = 0
|
|
||||||
self.c0bits = rest
|
|
||||||
self.c1bits = self.c2bits = \
|
|
||||||
self.chrompack = 0
|
|
||||||
else:
|
|
||||||
self.c0bits,self.c1bits,self.c2bits,\
|
|
||||||
self.chrompack,self.offset = rest
|
|
||||||
except:
|
|
||||||
raise Error, \
|
|
||||||
self.filename + ': bad 3.0 color info'
|
|
||||||
|
|
||||||
try:
|
|
||||||
self.convcolor = eval('conv_'+self.format)
|
|
||||||
except:
|
|
||||||
raise Error, \
|
|
||||||
self.filename + ': unknown colorsys ' + self.format
|
|
||||||
#
|
|
||||||
line = self.fp.readline()
|
|
||||||
try:
|
|
||||||
x = eval(line[:-1])
|
|
||||||
if self.version > 1.0 or len(x) == 3:
|
|
||||||
self.width, self.height, self.packfactor = x
|
|
||||||
if self.packfactor == 0:
|
|
||||||
self.format = 'rgb'
|
|
||||||
else:
|
|
||||||
sef.width, self.height = x
|
|
||||||
self.packfactor = 2
|
|
||||||
except:
|
|
||||||
raise Error, self.filename + ': bad (w,h,pf) info'
|
|
||||||
self.frameno = 0
|
|
||||||
self.framecache = []
|
|
||||||
self.hascache = 0
|
|
||||||
#
|
|
||||||
return self
|
|
||||||
|
|
||||||
def warmcache(self):
|
|
||||||
if self.hascache: return
|
|
||||||
n = 0
|
|
||||||
try:
|
|
||||||
while 1:
|
|
||||||
void = self.skipnextframe()
|
|
||||||
n = n + 1
|
|
||||||
except EOFError:
|
|
||||||
pass
|
|
||||||
if not self.hascache:
|
|
||||||
raise Error, 'Cannot warm cache'
|
|
||||||
|
|
||||||
def close(self):
|
|
||||||
self.fp.close()
|
|
||||||
self.fp = None
|
|
||||||
|
|
||||||
|
class VFile:
|
||||||
|
|
||||||
#
|
#
|
||||||
# getinfo returns all info pertaining to a film. The returned tuple
|
# getinfo returns all info pertaining to a film. The returned tuple
|
||||||
|
@ -179,96 +75,12 @@ class VinFile:
|
||||||
self.fp.seek(0)
|
self.fp.seek(0)
|
||||||
x = self.initfp(self.fp, self.filename)
|
x = self.initfp(self.fp, self.filename)
|
||||||
|
|
||||||
def rewind(self):
|
def setconvcolor(self):
|
||||||
if self.hascache:
|
|
||||||
self.frameno = 0
|
|
||||||
else:
|
|
||||||
self.reopen()
|
|
||||||
|
|
||||||
def position(self):
|
|
||||||
if self.frameno >= len(self.framecache):
|
|
||||||
raise EOFError
|
|
||||||
self.fp.seek(self.framecache[self.frameno][0])
|
|
||||||
|
|
||||||
# getnextframe() raises EOFError (built-in) if there is no next frame,
|
|
||||||
# or if the next frame is broken.
|
|
||||||
# So to getnextframeheader(), getnextframedata() and skipnextframe().
|
|
||||||
|
|
||||||
def getnextframe(self):
|
|
||||||
time, size, chromsize = self.getnextframeheader()
|
|
||||||
data, chromdata = self.getnextframedata(size, chromsize)
|
|
||||||
return time, data, chromdata
|
|
||||||
|
|
||||||
def getnextframedata(self, size, chromsize):
|
|
||||||
if self.hascache:
|
|
||||||
self.position()
|
|
||||||
self.frameno = self.frameno + 1
|
|
||||||
data = self.fp.read(size)
|
|
||||||
if len(data) <> size: raise EOFError
|
|
||||||
if chromsize:
|
|
||||||
chromdata = self.fp.read(chromsize)
|
|
||||||
if len(chromdata) <> chromsize: raise EOFError
|
|
||||||
else:
|
|
||||||
chromdata = None
|
|
||||||
#
|
|
||||||
return data, chromdata
|
|
||||||
|
|
||||||
def skipnextframe(self):
|
|
||||||
time, size, chromsize = self.getnextframeheader()
|
|
||||||
self.skipnextframedata(size, chromsize)
|
|
||||||
return time
|
|
||||||
|
|
||||||
def skipnextframedata(self, size, chromsize):
|
|
||||||
if self.hascache:
|
|
||||||
self.frameno = self.frameno + 1
|
|
||||||
return
|
|
||||||
# Note that this won't raise EOFError for a partial frame.
|
|
||||||
try:
|
try:
|
||||||
self.fp.seek(size + chromsize, 1) # Relative seek
|
self.convcolor = eval('conv_'+self.format)
|
||||||
except:
|
except:
|
||||||
# Assume it's a pipe -- read the data to discard it
|
raise Error, \
|
||||||
dummy = self.fp.read(size + chromsize)
|
self.filename + ': unknown colorsys ' + self.format
|
||||||
|
|
||||||
def getnextframeheader(self):
|
|
||||||
if self.hascache:
|
|
||||||
if self.frameno >= len(self.framecache):
|
|
||||||
raise EOFError
|
|
||||||
return self.framecache[self.frameno][1]
|
|
||||||
line = self.fp.readline()
|
|
||||||
if not line:
|
|
||||||
self.hascache = 1
|
|
||||||
raise EOFError
|
|
||||||
#
|
|
||||||
w, h, pf = self.width, self.height, self.packfactor
|
|
||||||
try:
|
|
||||||
x = eval(line[:-1])
|
|
||||||
if type(x) in (type(0), type(0.0)):
|
|
||||||
time = x
|
|
||||||
if pf == 0:
|
|
||||||
size = w * h * 4
|
|
||||||
else:
|
|
||||||
size = (w/pf) * (h/pf)
|
|
||||||
elif len(x) == 2:
|
|
||||||
time, size = x
|
|
||||||
cp = self.chrompack
|
|
||||||
if cp:
|
|
||||||
cw = (w + cp - 1) / cp
|
|
||||||
ch = (h + cp - 1) / cp
|
|
||||||
chromsize = 2 * cw * ch
|
|
||||||
else:
|
|
||||||
chromsize = 0
|
|
||||||
else:
|
|
||||||
time, size, chromsize = x
|
|
||||||
except:
|
|
||||||
raise Error, self.filename + ': bad frame header'
|
|
||||||
cdata = (self.fp.tell(), (time, size, chromsize))
|
|
||||||
self.framecache.append(cdata)
|
|
||||||
return time, size, chromsize
|
|
||||||
|
|
||||||
def shownextframe(self):
|
|
||||||
time, data, chromdata = self.getnextframe()
|
|
||||||
self.showframe(data, chromdata)
|
|
||||||
return time
|
|
||||||
|
|
||||||
def showframe(self, data, chromdata):
|
def showframe(self, data, chromdata):
|
||||||
w, h, pf = self.width, self.height, self.packfactor
|
w, h, pf = self.width, self.height, self.packfactor
|
||||||
|
@ -369,6 +181,205 @@ class VinFile:
|
||||||
gl.mapcolor(index, r, g, b)
|
gl.mapcolor(index, r, g, b)
|
||||||
void = gl.gflush()
|
void = gl.gflush()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class VinFile(VFile):
|
||||||
|
|
||||||
|
# init() and initfp() raise Error if the header is bad.
|
||||||
|
# init() raises whatever open() raises if the file can't be opened.
|
||||||
|
|
||||||
|
def init(self, filename):
|
||||||
|
if filename == '-':
|
||||||
|
return self.initfp(sys.stdin, filename)
|
||||||
|
return self.initfp(open(filename, 'r'), filename)
|
||||||
|
|
||||||
|
def initfp(self, fp, filename):
|
||||||
|
self.colormapinited = 0
|
||||||
|
self.magnify = 1.0
|
||||||
|
self.xorigin = self.yorigin = 0
|
||||||
|
self.fallback = 1
|
||||||
|
self.skipchrom = 0
|
||||||
|
self.fp = fp
|
||||||
|
self.filename = filename
|
||||||
|
self.quiet = 0
|
||||||
|
#
|
||||||
|
line = self.fp.readline()
|
||||||
|
if line == 'CMIF video 1.0\n':
|
||||||
|
self.version = 1.0
|
||||||
|
elif line == 'CMIF video 2.0\n':
|
||||||
|
self.version = 2.0
|
||||||
|
elif line == 'CMIF video 3.0\n':
|
||||||
|
self.version = 3.0
|
||||||
|
else:
|
||||||
|
raise Error, self.filename + ': bad video format'
|
||||||
|
#
|
||||||
|
if self.version < 2.0:
|
||||||
|
self.c0bits, self.c1bits, self.c2bits = 8, 0, 0
|
||||||
|
self.chrompack = 0
|
||||||
|
self.offset = 0
|
||||||
|
self.format = 'grey'
|
||||||
|
elif self.version == 2.0:
|
||||||
|
line = self.fp.readline()
|
||||||
|
try:
|
||||||
|
self.c0bits, self.c1bits, self.c2bits, \
|
||||||
|
self.chrompack = eval(line[:-1])
|
||||||
|
if self.c1bits or self.c2bits:
|
||||||
|
self.format = 'yiq'
|
||||||
|
else:
|
||||||
|
self.format = 'grey'
|
||||||
|
self.offset = 0
|
||||||
|
except:
|
||||||
|
raise Error, \
|
||||||
|
self.filename + ': bad 2.0 color info'
|
||||||
|
elif self.version == 3.0:
|
||||||
|
line = self.fp.readline()
|
||||||
|
try:
|
||||||
|
self.format, rest = eval(line[:-1])
|
||||||
|
if self.format == 'rgb':
|
||||||
|
self.offset = 0
|
||||||
|
self.c0bits = 0
|
||||||
|
self.c1bits = 0
|
||||||
|
self.c2bits = 0
|
||||||
|
self.chrompack = 0
|
||||||
|
elif self.format == 'grey':
|
||||||
|
self.offset = 0
|
||||||
|
self.c0bits = rest
|
||||||
|
self.c1bits = self.c2bits = \
|
||||||
|
self.chrompack = 0
|
||||||
|
else:
|
||||||
|
self.c0bits,self.c1bits,self.c2bits,\
|
||||||
|
self.chrompack,self.offset = rest
|
||||||
|
except:
|
||||||
|
raise Error, \
|
||||||
|
self.filename + ': bad 3.0 color info'
|
||||||
|
|
||||||
|
self.setconvcolor()
|
||||||
|
#
|
||||||
|
line = self.fp.readline()
|
||||||
|
try:
|
||||||
|
x = eval(line[:-1])
|
||||||
|
if self.version > 1.0 or len(x) == 3:
|
||||||
|
self.width, self.height, self.packfactor = x
|
||||||
|
if self.packfactor == 0:
|
||||||
|
self.format = 'rgb'
|
||||||
|
else:
|
||||||
|
sef.width, self.height = x
|
||||||
|
self.packfactor = 2
|
||||||
|
except:
|
||||||
|
raise Error, self.filename + ': bad (w,h,pf) info'
|
||||||
|
self.frameno = 0
|
||||||
|
self.framecache = []
|
||||||
|
self.hascache = 0
|
||||||
|
#
|
||||||
|
return self
|
||||||
|
|
||||||
|
def warmcache(self):
|
||||||
|
if self.hascache: return
|
||||||
|
n = 0
|
||||||
|
try:
|
||||||
|
while 1:
|
||||||
|
void = self.skipnextframe()
|
||||||
|
n = n + 1
|
||||||
|
except EOFError:
|
||||||
|
pass
|
||||||
|
if not self.hascache:
|
||||||
|
raise Error, 'Cannot warm cache'
|
||||||
|
|
||||||
|
def close(self):
|
||||||
|
self.fp.close()
|
||||||
|
self.fp = None
|
||||||
|
|
||||||
|
def rewind(self):
|
||||||
|
if self.hascache:
|
||||||
|
self.frameno = 0
|
||||||
|
else:
|
||||||
|
self.reopen()
|
||||||
|
|
||||||
|
def position(self):
|
||||||
|
if self.frameno >= len(self.framecache):
|
||||||
|
raise EOFError
|
||||||
|
self.fp.seek(self.framecache[self.frameno][0])
|
||||||
|
|
||||||
|
# getnextframe() raises EOFError (built-in) if there is no next frame,
|
||||||
|
# or if the next frame is broken.
|
||||||
|
# So to getnextframeheader(), getnextframedata() and skipnextframe().
|
||||||
|
|
||||||
|
def getnextframe(self):
|
||||||
|
time, size, chromsize = self.getnextframeheader()
|
||||||
|
data, chromdata = self.getnextframedata(size, chromsize)
|
||||||
|
return time, data, chromdata
|
||||||
|
|
||||||
|
def getnextframedata(self, size, chromsize):
|
||||||
|
if self.hascache:
|
||||||
|
self.position()
|
||||||
|
self.frameno = self.frameno + 1
|
||||||
|
data = self.fp.read(size)
|
||||||
|
if len(data) <> size: raise EOFError
|
||||||
|
if chromsize:
|
||||||
|
chromdata = self.fp.read(chromsize)
|
||||||
|
if len(chromdata) <> chromsize: raise EOFError
|
||||||
|
else:
|
||||||
|
chromdata = None
|
||||||
|
#
|
||||||
|
return data, chromdata
|
||||||
|
|
||||||
|
def skipnextframe(self):
|
||||||
|
time, size, chromsize = self.getnextframeheader()
|
||||||
|
self.skipnextframedata(size, chromsize)
|
||||||
|
return time
|
||||||
|
|
||||||
|
def skipnextframedata(self, size, chromsize):
|
||||||
|
if self.hascache:
|
||||||
|
self.frameno = self.frameno + 1
|
||||||
|
return
|
||||||
|
# Note that this won't raise EOFError for a partial frame.
|
||||||
|
try:
|
||||||
|
self.fp.seek(size + chromsize, 1) # Relative seek
|
||||||
|
except:
|
||||||
|
# Assume it's a pipe -- read the data to discard it
|
||||||
|
dummy = self.fp.read(size + chromsize)
|
||||||
|
|
||||||
|
def getnextframeheader(self):
|
||||||
|
if self.hascache:
|
||||||
|
if self.frameno >= len(self.framecache):
|
||||||
|
raise EOFError
|
||||||
|
return self.framecache[self.frameno][1]
|
||||||
|
line = self.fp.readline()
|
||||||
|
if not line:
|
||||||
|
self.hascache = 1
|
||||||
|
raise EOFError
|
||||||
|
#
|
||||||
|
w, h, pf = self.width, self.height, self.packfactor
|
||||||
|
try:
|
||||||
|
x = eval(line[:-1])
|
||||||
|
if type(x) in (type(0), type(0.0)):
|
||||||
|
time = x
|
||||||
|
if pf == 0:
|
||||||
|
size = w * h * 4
|
||||||
|
else:
|
||||||
|
size = (w/pf) * (h/pf)
|
||||||
|
elif len(x) == 2:
|
||||||
|
time, size = x
|
||||||
|
cp = self.chrompack
|
||||||
|
if cp:
|
||||||
|
cw = (w + cp - 1) / cp
|
||||||
|
ch = (h + cp - 1) / cp
|
||||||
|
chromsize = 2 * cw * ch
|
||||||
|
else:
|
||||||
|
chromsize = 0
|
||||||
|
else:
|
||||||
|
time, size, chromsize = x
|
||||||
|
except:
|
||||||
|
raise Error, self.filename + ': bad frame header'
|
||||||
|
cdata = (self.fp.tell(), (time, size, chromsize))
|
||||||
|
self.framecache.append(cdata)
|
||||||
|
return time, size, chromsize
|
||||||
|
|
||||||
|
def shownextframe(self):
|
||||||
|
time, data, chromdata = self.getnextframe()
|
||||||
|
self.showframe(data, chromdata)
|
||||||
|
return time
|
||||||
|
|
||||||
#
|
#
|
||||||
# A set of routines to grab images from windows
|
# A set of routines to grab images from windows
|
||||||
#
|
#
|
||||||
|
@ -417,7 +428,7 @@ def grab_hsv(w, h, pf):
|
||||||
# Notably it will accept almost any garbage and write it to the video
|
# Notably it will accept almost any garbage and write it to the video
|
||||||
# output file
|
# output file
|
||||||
#
|
#
|
||||||
class VoutFile:
|
class VoutFile(VFile):
|
||||||
def init(self, filename):
|
def init(self, filename):
|
||||||
if filename == '-':
|
if filename == '-':
|
||||||
return self.initfp(sys.stdout, filename)
|
return self.initfp(sys.stdout, filename)
|
||||||
|
@ -434,21 +445,21 @@ class VoutFile:
|
||||||
self.offset = 0
|
self.offset = 0
|
||||||
self.chrompack = 0
|
self.chrompack = 0
|
||||||
self.headerwritten = 0
|
self.headerwritten = 0
|
||||||
|
self.quiet = 0
|
||||||
|
self.magnify = 1
|
||||||
|
self.setconvcolor()
|
||||||
|
self.xorigin = self.yorigin = 0
|
||||||
return self
|
return self
|
||||||
|
|
||||||
def close(self):
|
def close(self):
|
||||||
self.fp.close()
|
self.fp.close()
|
||||||
x = self.initfp(None, None)
|
x = self.initfp(None, None)
|
||||||
|
|
||||||
def getinfo(self):
|
|
||||||
return (self.format, self.width, self.height, self.packfactor,\
|
|
||||||
self.c0bits, self.c1bits, self.c2bits, self.offset, \
|
|
||||||
self.chrompack)
|
|
||||||
|
|
||||||
def setinfo(self, values):
|
def setinfo(self, values):
|
||||||
self.format, self.width, self.height, self.packfactor,\
|
self.format, self.width, self.height, self.packfactor,\
|
||||||
self.c0bits, self.c1bits, self.c2bits, self.offset, \
|
self.c0bits, self.c1bits, self.c2bits, self.offset, \
|
||||||
self.chrompack = values
|
self.chrompack = values
|
||||||
|
self.setconvcolor()
|
||||||
|
|
||||||
def writeheader(self):
|
def writeheader(self):
|
||||||
self.headerwritten = 1
|
self.headerwritten = 1
|
||||||
|
|
247
Demo/sgi/video/Vedit.py
Executable file
247
Demo/sgi/video/Vedit.py
Executable file
|
@ -0,0 +1,247 @@
|
||||||
|
#! /ufs/guido/bin/sgi/python
|
||||||
|
|
||||||
|
# Edit CMIF movies interactively -- copy one or more files to an output file
|
||||||
|
|
||||||
|
|
||||||
|
# Possibilities:
|
||||||
|
#
|
||||||
|
# - convert between formats (grey, rgb, rgb8, ...)
|
||||||
|
# - change size
|
||||||
|
# - cut out a given area of the image
|
||||||
|
# - change time base (a la Vtime)
|
||||||
|
# - skip stretches of frames
|
||||||
|
|
||||||
|
|
||||||
|
import sys
|
||||||
|
import os
|
||||||
|
import gl, GL, DEVICE
|
||||||
|
import fl, FL
|
||||||
|
import flp
|
||||||
|
import Viewer
|
||||||
|
import getopt
|
||||||
|
import string
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
qsize = 20
|
||||||
|
opts, args = getopt.getopt(sys.argv[1:], 'q:')
|
||||||
|
for o, a in opts:
|
||||||
|
if o == '-q':
|
||||||
|
qsize = string.atoi(a)
|
||||||
|
ed = Editor().init(qsize)
|
||||||
|
if args[0:]:
|
||||||
|
ed.open_input(args[0])
|
||||||
|
if args[1:]:
|
||||||
|
ed.open_output(args[1])
|
||||||
|
while 1:
|
||||||
|
dummy = fl.do_forms()
|
||||||
|
|
||||||
|
|
||||||
|
class Editor:
|
||||||
|
|
||||||
|
def init(self, qsize):
|
||||||
|
self.qsize = qsize
|
||||||
|
self.vin = None
|
||||||
|
self.vout = None
|
||||||
|
self.ifile = ''
|
||||||
|
self.ofile = ''
|
||||||
|
formdef = flp.parse_form('VeditForm', 'form')
|
||||||
|
flp.create_full_form(self, formdef)
|
||||||
|
self.form.show_form(FL.PLACE_SIZE, FL.TRUE, 'Vedit')
|
||||||
|
fl.set_event_call_back(self.do_event)
|
||||||
|
return self
|
||||||
|
|
||||||
|
def do_event(self, (dev, val)):
|
||||||
|
if dev == DEVICE.REDRAW:
|
||||||
|
if self.vin:
|
||||||
|
self.vin.redraw(val)
|
||||||
|
if self.vout:
|
||||||
|
self.vout.redraw(val)
|
||||||
|
|
||||||
|
|
||||||
|
def iocheck(self):
|
||||||
|
self.msg('')
|
||||||
|
if self.vin == None and self.vout == None:
|
||||||
|
self.err('Please open input and output files first')
|
||||||
|
return 0
|
||||||
|
return self.icheck() and self.ocheck()
|
||||||
|
|
||||||
|
def icheck(self):
|
||||||
|
self.msg('')
|
||||||
|
if self.vin == None:
|
||||||
|
self.err('Please open an input file first')
|
||||||
|
return 0
|
||||||
|
return 1
|
||||||
|
|
||||||
|
def ocheck(self):
|
||||||
|
self.msg('')
|
||||||
|
if self.vout == None:
|
||||||
|
self.err('Please open an output file first')
|
||||||
|
return 0
|
||||||
|
return 1
|
||||||
|
|
||||||
|
|
||||||
|
def cb_in_new(self, args):
|
||||||
|
self.msg('')
|
||||||
|
hd, tl = os.path.split(self.ifile)
|
||||||
|
filename = fl.file_selector('Input video file', hd, '', tl)
|
||||||
|
if not filename: return
|
||||||
|
self.open_input(filename)
|
||||||
|
|
||||||
|
def cb_in_close(self, args):
|
||||||
|
self.msg('')
|
||||||
|
self.close_input()
|
||||||
|
|
||||||
|
def cb_in_skip(self, args):
|
||||||
|
if not self.icheck(): return
|
||||||
|
if not self.vin.get(): self.err('End of input file')
|
||||||
|
self.ishow()
|
||||||
|
|
||||||
|
def cb_in_back(self, args):
|
||||||
|
if not self.icheck(): return
|
||||||
|
if not self.vin.backup(): self.err('Input buffer exhausted')
|
||||||
|
self.ishow()
|
||||||
|
|
||||||
|
def cb_in_rewind(self, args):
|
||||||
|
if not self.icheck(): return
|
||||||
|
self.vin.rewind()
|
||||||
|
self.ishow()
|
||||||
|
|
||||||
|
|
||||||
|
def cb_copy(self, args):
|
||||||
|
if not self.iocheck(): return
|
||||||
|
data = self.vin.get()
|
||||||
|
if data:
|
||||||
|
if self.vout.getinfo() <> self.vin.getinfo():
|
||||||
|
print 'Copying info...'
|
||||||
|
self.vout.setinfo(self.vin.getinfo())
|
||||||
|
self.vout.put(data)
|
||||||
|
self.oshow()
|
||||||
|
self.ishow()
|
||||||
|
|
||||||
|
def cb_uncopy(self, args):
|
||||||
|
if not self.iocheck(): return
|
||||||
|
if not self.vout.backup():
|
||||||
|
self.err('Output buffer exhausted')
|
||||||
|
return
|
||||||
|
self.oshow()
|
||||||
|
if not self.vin.backup():
|
||||||
|
self.err('Input buffer exhausted')
|
||||||
|
return
|
||||||
|
self.ishow()
|
||||||
|
|
||||||
|
|
||||||
|
def cb_out_new(self, args):
|
||||||
|
self.msg('')
|
||||||
|
hd, tl = os.path.split(self.ofile)
|
||||||
|
filename = fl.file_selector('Output video file', hd, '', tl)
|
||||||
|
if not filename: return
|
||||||
|
self.open_output(filename)
|
||||||
|
|
||||||
|
def cb_out_close(self, args):
|
||||||
|
self.msg('')
|
||||||
|
self.close_output()
|
||||||
|
|
||||||
|
def cb_out_skip(self, arg):
|
||||||
|
if not self.ocheck(): return
|
||||||
|
if not self.vout.forward(): self.err('Output buffer exhausted')
|
||||||
|
self.oshow()
|
||||||
|
|
||||||
|
def cb_out_back(self, args):
|
||||||
|
if not self.ocheck(): return
|
||||||
|
if not self.vout.backup(): self.err('Output buffer exhausted')
|
||||||
|
self.oshow()
|
||||||
|
|
||||||
|
def cb_out_rewind(self, args):
|
||||||
|
if not self.ocheck(): return
|
||||||
|
self.vout.rewind()
|
||||||
|
self.oshow()
|
||||||
|
|
||||||
|
|
||||||
|
def cb_quit(self, args):
|
||||||
|
self.close_input()
|
||||||
|
self.close_output()
|
||||||
|
sys.exit(0)
|
||||||
|
|
||||||
|
|
||||||
|
def open_input(self, filename):
|
||||||
|
self.ifile = filename
|
||||||
|
basename = os.path.split(filename)[1]
|
||||||
|
title = 'in: ' + basename
|
||||||
|
try:
|
||||||
|
vin = Viewer.InputViewer().init(filename, \
|
||||||
|
title, self.qsize)
|
||||||
|
except:
|
||||||
|
self.err('Can\'t open input file', filename)
|
||||||
|
return
|
||||||
|
self.close_input()
|
||||||
|
self.vin = vin
|
||||||
|
self.in_file.label = basename
|
||||||
|
self.ishow()
|
||||||
|
|
||||||
|
def close_input(self):
|
||||||
|
if self.vin:
|
||||||
|
self.msg('Closing input file...')
|
||||||
|
self.vin.close()
|
||||||
|
self.msg('')
|
||||||
|
self.vin = None
|
||||||
|
self.in_file.label = '(none)'
|
||||||
|
self.format('in')
|
||||||
|
|
||||||
|
def ishow(self):
|
||||||
|
self.vin.show()
|
||||||
|
self.format('in')
|
||||||
|
|
||||||
|
def open_output(self, filename):
|
||||||
|
self.ofile = filename
|
||||||
|
basename = os.path.split(filename)[1]
|
||||||
|
title = 'out: ' + basename
|
||||||
|
try:
|
||||||
|
vout = Viewer.OutputViewer().init(filename, \
|
||||||
|
title, self.qsize)
|
||||||
|
except:
|
||||||
|
self.err('Can\'t open output file', filename)
|
||||||
|
return
|
||||||
|
self.close_output()
|
||||||
|
self.vout = vout
|
||||||
|
self.out_file.label = basename
|
||||||
|
if self.vin:
|
||||||
|
self.vout.setinfo(self.vin.getinfo())
|
||||||
|
self.oshow()
|
||||||
|
|
||||||
|
def close_output(self):
|
||||||
|
if self.vout:
|
||||||
|
self.msg('Closing output file...')
|
||||||
|
self.vout.close()
|
||||||
|
self.msg('')
|
||||||
|
self.vout = None
|
||||||
|
self.out_file.label = '(none)'
|
||||||
|
self.format('out')
|
||||||
|
|
||||||
|
def oshow(self):
|
||||||
|
self.vout.show()
|
||||||
|
self.format('out')
|
||||||
|
|
||||||
|
|
||||||
|
def msg(self, *args):
|
||||||
|
str = string.strip(string.join(args))
|
||||||
|
self.msg_area.label = str
|
||||||
|
|
||||||
|
def err(self, *args):
|
||||||
|
gl.ringbell()
|
||||||
|
apply(self.msg, args)
|
||||||
|
|
||||||
|
def format(self, io):
|
||||||
|
v = getattr(self, 'v' + io)
|
||||||
|
if v == None:
|
||||||
|
left = right = pos = 0
|
||||||
|
else:
|
||||||
|
left, right = v.qsizes()
|
||||||
|
pos = v.tell()
|
||||||
|
left = pos - left
|
||||||
|
right = pos + right
|
||||||
|
getattr(self, io + '_info1').label = `left`
|
||||||
|
getattr(self, io + '_info2').label = `pos`
|
||||||
|
getattr(self, io + '_info3').label = `right`
|
||||||
|
|
||||||
|
main()
|
360
Demo/sgi/video/VeditForm.fd
Normal file
360
Demo/sgi/video/VeditForm.fd
Normal file
|
@ -0,0 +1,360 @@
|
||||||
|
Magic: 12321
|
||||||
|
|
||||||
|
Internal Form Definition File
|
||||||
|
(do not change)
|
||||||
|
|
||||||
|
Number of forms: 1
|
||||||
|
|
||||||
|
=============== FORM ===============
|
||||||
|
Name: form
|
||||||
|
Width: 480.000000
|
||||||
|
Height: 350.000000
|
||||||
|
Number of Objects: 23
|
||||||
|
|
||||||
|
--------------------
|
||||||
|
class: 1
|
||||||
|
type: 1
|
||||||
|
box: 0.000000 0.000000 480.000000 350.000000
|
||||||
|
boxtype: 1
|
||||||
|
colors: 47 47
|
||||||
|
alignment: 4
|
||||||
|
style: 0
|
||||||
|
size: 11.000000
|
||||||
|
lcol: 0
|
||||||
|
label:
|
||||||
|
name:
|
||||||
|
callback:
|
||||||
|
argument:
|
||||||
|
|
||||||
|
--------------------
|
||||||
|
class: 11
|
||||||
|
type: 4
|
||||||
|
box: 170.000000 110.000000 140.000000 40.000000
|
||||||
|
boxtype: 1
|
||||||
|
colors: 47 47
|
||||||
|
alignment: 4
|
||||||
|
style: 0
|
||||||
|
size: 11.000000
|
||||||
|
lcol: 0
|
||||||
|
label: -> Copy ->
|
||||||
|
name:
|
||||||
|
callback: cb_copy
|
||||||
|
argument: 0
|
||||||
|
|
||||||
|
--------------------
|
||||||
|
class: 11
|
||||||
|
type: 4
|
||||||
|
box: 10.000000 110.000000 140.000000 40.000000
|
||||||
|
boxtype: 1
|
||||||
|
colors: 47 47
|
||||||
|
alignment: 4
|
||||||
|
style: 0
|
||||||
|
size: 11.000000
|
||||||
|
lcol: 0
|
||||||
|
label: Forward
|
||||||
|
name:
|
||||||
|
callback: cb_in_skip
|
||||||
|
argument: 0
|
||||||
|
|
||||||
|
--------------------
|
||||||
|
class: 11
|
||||||
|
type: 0
|
||||||
|
box: 10.000000 10.000000 140.000000 40.000000
|
||||||
|
boxtype: 1
|
||||||
|
colors: 47 47
|
||||||
|
alignment: 4
|
||||||
|
style: 0
|
||||||
|
size: 11.000000
|
||||||
|
lcol: 0
|
||||||
|
label: Rewind input
|
||||||
|
name:
|
||||||
|
callback: cb_in_rewind
|
||||||
|
argument: 0
|
||||||
|
|
||||||
|
--------------------
|
||||||
|
class: 11
|
||||||
|
type: 0
|
||||||
|
box: 330.000000 10.000000 140.000000 40.000000
|
||||||
|
boxtype: 1
|
||||||
|
colors: 47 47
|
||||||
|
alignment: 4
|
||||||
|
style: 0
|
||||||
|
size: 11.000000
|
||||||
|
lcol: 0
|
||||||
|
label: Reset output
|
||||||
|
name:
|
||||||
|
callback: cb_out_rewind
|
||||||
|
argument: 0
|
||||||
|
|
||||||
|
--------------------
|
||||||
|
class: 11
|
||||||
|
type: 0
|
||||||
|
box: 10.000000 260.000000 80.000000 40.000000
|
||||||
|
boxtype: 1
|
||||||
|
colors: 47 47
|
||||||
|
alignment: 4
|
||||||
|
style: 0
|
||||||
|
size: 11.000000
|
||||||
|
lcol: 0
|
||||||
|
label: Input file...
|
||||||
|
name:
|
||||||
|
callback: cb_in_new
|
||||||
|
argument: 0
|
||||||
|
|
||||||
|
--------------------
|
||||||
|
class: 11
|
||||||
|
type: 0
|
||||||
|
box: 330.000000 260.000000 80.000000 40.000000
|
||||||
|
boxtype: 1
|
||||||
|
colors: 47 47
|
||||||
|
alignment: 4
|
||||||
|
style: 0
|
||||||
|
size: 11.000000
|
||||||
|
lcol: 0
|
||||||
|
label: Output file...
|
||||||
|
name:
|
||||||
|
callback: cb_out_new
|
||||||
|
argument: 0
|
||||||
|
|
||||||
|
--------------------
|
||||||
|
class: 2
|
||||||
|
type: 0
|
||||||
|
box: 10.000000 210.000000 140.000000 40.000000
|
||||||
|
boxtype: 6
|
||||||
|
colors: 47 47
|
||||||
|
alignment: 2
|
||||||
|
style: 0
|
||||||
|
size: 11.000000
|
||||||
|
lcol: 0
|
||||||
|
label: (none)
|
||||||
|
name: in_file
|
||||||
|
callback:
|
||||||
|
argument:
|
||||||
|
|
||||||
|
--------------------
|
||||||
|
class: 2
|
||||||
|
type: 0
|
||||||
|
box: 330.000000 210.000000 140.000000 40.000000
|
||||||
|
boxtype: 6
|
||||||
|
colors: 47 47
|
||||||
|
alignment: 2
|
||||||
|
style: 0
|
||||||
|
size: 11.000000
|
||||||
|
lcol: 0
|
||||||
|
label: (none)
|
||||||
|
name: out_file
|
||||||
|
callback:
|
||||||
|
argument:
|
||||||
|
|
||||||
|
--------------------
|
||||||
|
class: 2
|
||||||
|
type: 0
|
||||||
|
box: 10.000000 160.000000 30.000000 30.000000
|
||||||
|
boxtype: 6
|
||||||
|
colors: 47 47
|
||||||
|
alignment: 2
|
||||||
|
style: 0
|
||||||
|
size: 8.000000
|
||||||
|
lcol: 0
|
||||||
|
label:
|
||||||
|
name: in_info1
|
||||||
|
callback:
|
||||||
|
argument:
|
||||||
|
|
||||||
|
--------------------
|
||||||
|
class: 11
|
||||||
|
type: 0
|
||||||
|
box: 170.000000 260.000000 140.000000 40.000000
|
||||||
|
boxtype: 1
|
||||||
|
colors: 47 47
|
||||||
|
alignment: 4
|
||||||
|
style: 0
|
||||||
|
size: 11.000000
|
||||||
|
lcol: 0
|
||||||
|
label: Quit
|
||||||
|
name:
|
||||||
|
callback: cb_quit
|
||||||
|
argument: 0
|
||||||
|
|
||||||
|
--------------------
|
||||||
|
class: 11
|
||||||
|
type: 4
|
||||||
|
box: 330.000000 60.000000 140.000000 40.000000
|
||||||
|
boxtype: 1
|
||||||
|
colors: 47 47
|
||||||
|
alignment: 4
|
||||||
|
style: 0
|
||||||
|
size: 11.000000
|
||||||
|
lcol: 0
|
||||||
|
label: Back
|
||||||
|
name:
|
||||||
|
callback: cb_out_back
|
||||||
|
argument: 0
|
||||||
|
|
||||||
|
--------------------
|
||||||
|
class: 11
|
||||||
|
type: 4
|
||||||
|
box: 10.000000 60.000000 140.000000 40.000000
|
||||||
|
boxtype: 1
|
||||||
|
colors: 47 47
|
||||||
|
alignment: 4
|
||||||
|
style: 0
|
||||||
|
size: 11.000000
|
||||||
|
lcol: 0
|
||||||
|
label: Back
|
||||||
|
name:
|
||||||
|
callback: cb_in_back
|
||||||
|
argument: 0
|
||||||
|
|
||||||
|
--------------------
|
||||||
|
class: 11
|
||||||
|
type: 4
|
||||||
|
box: 330.000000 110.000000 140.000000 40.000000
|
||||||
|
boxtype: 1
|
||||||
|
colors: 47 47
|
||||||
|
alignment: 4
|
||||||
|
style: 0
|
||||||
|
size: 11.000000
|
||||||
|
lcol: 0
|
||||||
|
label: Forward
|
||||||
|
name:
|
||||||
|
callback: cb_out_skip
|
||||||
|
argument: 0
|
||||||
|
|
||||||
|
--------------------
|
||||||
|
class: 11
|
||||||
|
type: 4
|
||||||
|
box: 170.000000 60.000000 140.000000 40.000000
|
||||||
|
boxtype: 1
|
||||||
|
colors: 47 47
|
||||||
|
alignment: 4
|
||||||
|
style: 0
|
||||||
|
size: 11.000000
|
||||||
|
lcol: 0
|
||||||
|
label: Uncopy
|
||||||
|
name:
|
||||||
|
callback: cb_uncopy
|
||||||
|
argument: 0
|
||||||
|
|
||||||
|
--------------------
|
||||||
|
class: 11
|
||||||
|
type: 0
|
||||||
|
box: 100.000000 260.000000 50.000000 40.000000
|
||||||
|
boxtype: 1
|
||||||
|
colors: 47 47
|
||||||
|
alignment: 4
|
||||||
|
style: 0
|
||||||
|
size: 11.000000
|
||||||
|
lcol: 0
|
||||||
|
label: Close
|
||||||
|
name:
|
||||||
|
callback: cb_in_close
|
||||||
|
argument: 0
|
||||||
|
|
||||||
|
--------------------
|
||||||
|
class: 11
|
||||||
|
type: 0
|
||||||
|
box: 420.000000 260.000000 50.000000 40.000000
|
||||||
|
boxtype: 1
|
||||||
|
colors: 47 47
|
||||||
|
alignment: 4
|
||||||
|
style: 0
|
||||||
|
size: 11.000000
|
||||||
|
lcol: 0
|
||||||
|
label: Close
|
||||||
|
name:
|
||||||
|
callback: cb_out_close
|
||||||
|
argument: 0
|
||||||
|
|
||||||
|
--------------------
|
||||||
|
class: 2
|
||||||
|
type: 0
|
||||||
|
box: 10.000000 310.000000 460.000000 30.000000
|
||||||
|
boxtype: 6
|
||||||
|
colors: 47 47
|
||||||
|
alignment: 2
|
||||||
|
style: 0
|
||||||
|
size: 11.000000
|
||||||
|
lcol: 0
|
||||||
|
label: CMIF Video Editor, by Guido van Rossum
|
||||||
|
name: msg_area
|
||||||
|
callback:
|
||||||
|
argument:
|
||||||
|
|
||||||
|
--------------------
|
||||||
|
class: 2
|
||||||
|
type: 0
|
||||||
|
box: 50.000000 160.000000 60.000004 40.000000
|
||||||
|
boxtype: 6
|
||||||
|
colors: 47 47
|
||||||
|
alignment: 2
|
||||||
|
style: 0
|
||||||
|
size: 11.000000
|
||||||
|
lcol: 0
|
||||||
|
label:
|
||||||
|
name: in_info2
|
||||||
|
callback:
|
||||||
|
argument:
|
||||||
|
|
||||||
|
--------------------
|
||||||
|
class: 2
|
||||||
|
type: 0
|
||||||
|
box: 120.000000 160.000000 30.000000 30.000000
|
||||||
|
boxtype: 6
|
||||||
|
colors: 47 47
|
||||||
|
alignment: 2
|
||||||
|
style: 0
|
||||||
|
size: 8.000000
|
||||||
|
lcol: 0
|
||||||
|
label:
|
||||||
|
name: in_info3
|
||||||
|
callback:
|
||||||
|
argument:
|
||||||
|
|
||||||
|
--------------------
|
||||||
|
class: 2
|
||||||
|
type: 0
|
||||||
|
box: 330.000000 160.000000 30.000000 30.000000
|
||||||
|
boxtype: 6
|
||||||
|
colors: 47 47
|
||||||
|
alignment: 2
|
||||||
|
style: 0
|
||||||
|
size: 8.000000
|
||||||
|
lcol: 0
|
||||||
|
label:
|
||||||
|
name: out_info1
|
||||||
|
callback:
|
||||||
|
argument:
|
||||||
|
|
||||||
|
--------------------
|
||||||
|
class: 2
|
||||||
|
type: 0
|
||||||
|
box: 370.000000 160.000000 60.000004 40.000000
|
||||||
|
boxtype: 6
|
||||||
|
colors: 47 47
|
||||||
|
alignment: 2
|
||||||
|
style: 0
|
||||||
|
size: 11.000000
|
||||||
|
lcol: 0
|
||||||
|
label:
|
||||||
|
name: out_info2
|
||||||
|
callback:
|
||||||
|
argument:
|
||||||
|
|
||||||
|
--------------------
|
||||||
|
class: 2
|
||||||
|
type: 0
|
||||||
|
box: 440.000000 160.000000 30.000000 30.000000
|
||||||
|
boxtype: 6
|
||||||
|
colors: 47 47
|
||||||
|
alignment: 2
|
||||||
|
style: 0
|
||||||
|
size: 8.000000
|
||||||
|
lcol: 0
|
||||||
|
label:
|
||||||
|
name: out_info3
|
||||||
|
callback:
|
||||||
|
argument:
|
||||||
|
|
||||||
|
==============================
|
||||||
|
create_the_forms
|
242
Demo/sgi/video/Viewer.py
Executable file
242
Demo/sgi/video/Viewer.py
Executable file
|
@ -0,0 +1,242 @@
|
||||||
|
import gl, GL
|
||||||
|
import VFile
|
||||||
|
import os
|
||||||
|
|
||||||
|
|
||||||
|
class InputViewer:
|
||||||
|
|
||||||
|
def init(self, filename, title, qsize):
|
||||||
|
try:
|
||||||
|
self.vin = VFile.VinFile().init(filename)
|
||||||
|
except (EOFError, VFile.Error):
|
||||||
|
raise IOError, 'bad video input file'
|
||||||
|
if not title:
|
||||||
|
title = os.path.split(filename)[1]
|
||||||
|
self.filename = filename
|
||||||
|
self.title = title
|
||||||
|
self.qsize = qsize
|
||||||
|
gl.foreground()
|
||||||
|
gl.prefsize(self.vin.width, self.vin.height)
|
||||||
|
self.wid = -1
|
||||||
|
self.reset()
|
||||||
|
return self
|
||||||
|
|
||||||
|
def close(self):
|
||||||
|
self.vin.close()
|
||||||
|
if self.wid > 0:
|
||||||
|
gl.winclose(self.wid)
|
||||||
|
|
||||||
|
def rewind(self):
|
||||||
|
self.vin.rewind()
|
||||||
|
self.reset()
|
||||||
|
|
||||||
|
def getinfo(self):
|
||||||
|
return self.vin.getinfo()
|
||||||
|
|
||||||
|
# Internal
|
||||||
|
def reset(self):
|
||||||
|
if self.wid > 0:
|
||||||
|
gl.winset(self.wid)
|
||||||
|
gl.clear()
|
||||||
|
self.vin.initcolormap()
|
||||||
|
self.queue = []
|
||||||
|
self.qindex = 0
|
||||||
|
self.lost = 0
|
||||||
|
self.lastt = 0
|
||||||
|
self.eofread = 0
|
||||||
|
|
||||||
|
# Internal
|
||||||
|
def fillq(self):
|
||||||
|
if self.qindex < len(self.queue) or self.eofread: return
|
||||||
|
try:
|
||||||
|
t, d, cd = self.vin.getnextframe()
|
||||||
|
except EOFError:
|
||||||
|
self.eofread = 1
|
||||||
|
return
|
||||||
|
dt = t - self.lastt
|
||||||
|
self.lastt = t
|
||||||
|
self.queue.append(dt, d, cd)
|
||||||
|
while len(self.queue) > self.qsize:
|
||||||
|
del self.queue[0]
|
||||||
|
self.qindex = self.qindex - 1
|
||||||
|
self.lost = self.lost + 1
|
||||||
|
|
||||||
|
def show(self):
|
||||||
|
if self.wid < 0:
|
||||||
|
gl.foreground()
|
||||||
|
gl.prefsize(self.vin.width, self.vin.height)
|
||||||
|
self.wid = gl.winopen(self.title)
|
||||||
|
gl.clear()
|
||||||
|
self.vin.initcolormap()
|
||||||
|
self.fillq()
|
||||||
|
gl.winset(self.wid)
|
||||||
|
if self.qindex >= len(self.queue):
|
||||||
|
gl.clear()
|
||||||
|
return
|
||||||
|
dt, d, cd = self.queue[self.qindex]
|
||||||
|
self.vin.showframe(d, cd)
|
||||||
|
|
||||||
|
def redraw(self, wid):
|
||||||
|
if wid == self.wid >= 0:
|
||||||
|
gl.winset(self.wid)
|
||||||
|
gl.reshapeviewport()
|
||||||
|
self.show()
|
||||||
|
|
||||||
|
def get(self):
|
||||||
|
if self.qindex >= len(self.queue):
|
||||||
|
self.fillq()
|
||||||
|
if self.eofread:
|
||||||
|
return None
|
||||||
|
item = self.queue[self.qindex]
|
||||||
|
self.qindex = self.qindex + 1
|
||||||
|
return item
|
||||||
|
|
||||||
|
def backup(self):
|
||||||
|
if self.qindex == 0:
|
||||||
|
return 0
|
||||||
|
self.qindex = self.qindex - 1
|
||||||
|
return 1
|
||||||
|
|
||||||
|
def tell(self):
|
||||||
|
return self.lost + self.qindex
|
||||||
|
|
||||||
|
def qsizes(self):
|
||||||
|
return self.qindex, len(self.queue) - self.qindex
|
||||||
|
|
||||||
|
|
||||||
|
class OutputViewer:
|
||||||
|
|
||||||
|
def init(self, filename, title, qsize):
|
||||||
|
try:
|
||||||
|
self.vout = VFile.VoutFile().init(filename)
|
||||||
|
except (EOFError, VFile.Error):
|
||||||
|
raise IOError, 'bad video output file'
|
||||||
|
if not title:
|
||||||
|
title = os.path.split(filename)[1]
|
||||||
|
self.filename = filename
|
||||||
|
self.title = title
|
||||||
|
self.qsize = qsize
|
||||||
|
gl.foreground()
|
||||||
|
self.wid = -1
|
||||||
|
self.reset()
|
||||||
|
return self
|
||||||
|
|
||||||
|
def close(self):
|
||||||
|
while self.queue:
|
||||||
|
self.flushq()
|
||||||
|
self.vout.close()
|
||||||
|
if self.wid > 0:
|
||||||
|
gl.winclose(self.wid)
|
||||||
|
|
||||||
|
def rewind(self):
|
||||||
|
info = self.vout.getinfo()
|
||||||
|
self.vout.close()
|
||||||
|
self.vout = VFile.VoutFile().init(self.filename)
|
||||||
|
self.vout.setinfo(info)
|
||||||
|
self.reset()
|
||||||
|
|
||||||
|
def getinfo(self):
|
||||||
|
return self.vout.getinfo()
|
||||||
|
|
||||||
|
def setinfo(self, info):
|
||||||
|
if info == self.getinfo(): return # No change
|
||||||
|
self.vout.setinfo(info)
|
||||||
|
if self.wid > 0:
|
||||||
|
gl.winclose(self.wid)
|
||||||
|
self.wid = -1
|
||||||
|
|
||||||
|
# Internal
|
||||||
|
def reset(self):
|
||||||
|
if self.wid > 0:
|
||||||
|
gl.winset(self.wid)
|
||||||
|
gl.clear()
|
||||||
|
self.vout.initcolormap()
|
||||||
|
self.queue = []
|
||||||
|
self.spares = []
|
||||||
|
self.written = 0
|
||||||
|
self.lastt = 0
|
||||||
|
|
||||||
|
# Internal
|
||||||
|
def flushq(self):
|
||||||
|
if self.written == 0:
|
||||||
|
self.vout.writeheader()
|
||||||
|
dt, d, cd = self.queue[0]
|
||||||
|
self.lastt = self.lastt + dt
|
||||||
|
self.vout.writeframe(self.lastt, d, cd)
|
||||||
|
del self.queue[0]
|
||||||
|
self.written = self.written + 1
|
||||||
|
|
||||||
|
def show(self):
|
||||||
|
if self.wid < 0:
|
||||||
|
gl.foreground()
|
||||||
|
gl.prefsize(self.vout.width, self.vout.height)
|
||||||
|
self.wid = gl.winopen(self.title)
|
||||||
|
gl.clear()
|
||||||
|
self.vout.initcolormap()
|
||||||
|
gl.winset(self.wid)
|
||||||
|
if not self.queue:
|
||||||
|
gl.clear()
|
||||||
|
return
|
||||||
|
dt, d, cd = self.queue[-1]
|
||||||
|
self.vout.showframe(d, cd)
|
||||||
|
|
||||||
|
def redraw(self, wid):
|
||||||
|
if wid == self.wid >= 0:
|
||||||
|
gl.winset(self.wid)
|
||||||
|
gl.reshapeviewport()
|
||||||
|
self.show()
|
||||||
|
|
||||||
|
def backup(self):
|
||||||
|
if len(self.queue) < 1: return 0
|
||||||
|
self.spares.insert(0, self.queue[-1])
|
||||||
|
del self.queue[-1]
|
||||||
|
return 1
|
||||||
|
|
||||||
|
def forward(self):
|
||||||
|
if not self.spares: return 0
|
||||||
|
self.queue.append(self.spares[0])
|
||||||
|
del self.spares[0]
|
||||||
|
return 1
|
||||||
|
|
||||||
|
def put(self, item):
|
||||||
|
self.queue.append(item)
|
||||||
|
self.spares = []
|
||||||
|
while len(self.queue) > self.qsize:
|
||||||
|
self.flushq()
|
||||||
|
|
||||||
|
def tell(self):
|
||||||
|
return self.written + len(self.queue)
|
||||||
|
|
||||||
|
def qsizes(self):
|
||||||
|
return len(self.queue), len(self.spares)
|
||||||
|
|
||||||
|
|
||||||
|
def test():
|
||||||
|
import sys
|
||||||
|
a = InputViewer().init(sys.argv[1], '')
|
||||||
|
b = OutputViewer().init(sys.argv[2], '')
|
||||||
|
b.setinfo(a.getinfo())
|
||||||
|
|
||||||
|
while 1:
|
||||||
|
a.show()
|
||||||
|
data = a.get()
|
||||||
|
if data is None:
|
||||||
|
break
|
||||||
|
b.put(data)
|
||||||
|
b.show()
|
||||||
|
|
||||||
|
while a.backup():
|
||||||
|
data = a.get()
|
||||||
|
b.put(data)
|
||||||
|
b.show()
|
||||||
|
if a.backup(): a.show()
|
||||||
|
|
||||||
|
while 1:
|
||||||
|
data = a.get()
|
||||||
|
if data is None:
|
||||||
|
break
|
||||||
|
b.put(data)
|
||||||
|
b.show()
|
||||||
|
a.show()
|
||||||
|
|
||||||
|
b.close()
|
|
@ -200,13 +200,15 @@ def playonce(vin):
|
||||||
vin.magnify = magnify
|
vin.magnify = magnify
|
||||||
|
|
||||||
if threading:
|
if threading:
|
||||||
|
MAXSIZE = 20 # Don't read ahead too much
|
||||||
import thread
|
import thread
|
||||||
queue = []
|
import Queue
|
||||||
|
queue = Queue.Queue().init(MAXSIZE)
|
||||||
stop = []
|
stop = []
|
||||||
thread.start_new_thread(read_ahead, (vin, queue, stop))
|
thread.start_new_thread(read_ahead, (vin, queue, stop))
|
||||||
# Get the read-ahead thread going
|
# Get the read-ahead thread going
|
||||||
while len(queue) < 5 and None not in queue:
|
while queue.qsize() < MAXSIZE/2 and not stop:
|
||||||
time.millisleep(10)
|
time.millisleep(100)
|
||||||
|
|
||||||
tin = 0
|
tin = 0
|
||||||
told = 0
|
told = 0
|
||||||
|
@ -227,21 +229,18 @@ def playonce(vin):
|
||||||
if debug: sys.stderr.write('\n')
|
if debug: sys.stderr.write('\n')
|
||||||
if threading:
|
if threading:
|
||||||
stop.append(None)
|
stop.append(None)
|
||||||
while len(stop) < 2:
|
while 1:
|
||||||
time.millisleep(10)
|
item = queue.get()
|
||||||
|
if item == None: break
|
||||||
return (dev != LEFTMOUSE)
|
return (dev != LEFTMOUSE)
|
||||||
if dev == REDRAW:
|
if dev == REDRAW:
|
||||||
gl.reshapeviewport()
|
gl.reshapeviewport()
|
||||||
if data: vin.showframe(data, cdata)
|
if data: vin.showframe(data, cdata)
|
||||||
if threading:
|
if threading:
|
||||||
if not queue:
|
if debug and queue.empty(): sys.stderr.write('.')
|
||||||
if debug: sys.stderr.write('.')
|
item = queue.get()
|
||||||
time.millisleep(10)
|
if item == None: break
|
||||||
continue
|
tin, data, cdata = item
|
||||||
q0 = queue[0]
|
|
||||||
if q0 == None: break
|
|
||||||
del queue[0]
|
|
||||||
tin, data, cdata = q0
|
|
||||||
else:
|
else:
|
||||||
try:
|
try:
|
||||||
tin, size, csize = vin.getnextframeheader()
|
tin, size, csize = vin.getnextframeheader()
|
||||||
|
@ -301,13 +300,13 @@ def playonce(vin):
|
||||||
|
|
||||||
def read_ahead(vin, queue, stop):
|
def read_ahead(vin, queue, stop):
|
||||||
try:
|
try:
|
||||||
while not stop: queue.append(vin.getnextframe())
|
while not stop: queue.put(vin.getnextframe())
|
||||||
except EOFError:
|
except EOFError:
|
||||||
queue.append(None)
|
pass
|
||||||
|
queue.put(None)
|
||||||
stop.append(None)
|
stop.append(None)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# Don't forget to call the main program
|
# Don't forget to call the main program
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue