1992-08-21 12:34:55 +00:00
|
|
|
#! /ufs/guido/bin/sgi/python-405
|
|
|
|
#! /ufs/guido/bin/sgi/python
|
1992-08-18 17:01:02 +00:00
|
|
|
#! /usr/local/python
|
|
|
|
|
|
|
|
# Play CMIF movie files
|
|
|
|
|
|
|
|
|
1992-08-21 12:34:55 +00:00
|
|
|
# Help function
|
1992-08-18 17:01:02 +00:00
|
|
|
|
1992-08-21 12:34:55 +00:00
|
|
|
def help():
|
|
|
|
print 'Usage: Vplay [options] [file] ...'
|
|
|
|
print
|
|
|
|
print 'Options:'
|
|
|
|
print '-M magnify : magnify the image by the given factor'
|
|
|
|
print '-d : write some debug stuff on stderr'
|
|
|
|
print '-l : loop, playing the movie over and over again'
|
|
|
|
print '-m delta : drop frames closer than delta msec (default 0)'
|
|
|
|
print '-q : quiet, no informative messages'
|
|
|
|
print '-r delta : regenerate input time base delta msec apart'
|
|
|
|
print '-s speed : speed change factor (default 1.0)'
|
|
|
|
print '-t : use a 2nd thread for read-ahead'
|
|
|
|
print '-x left : window offset from left of screen'
|
|
|
|
print '-y top : window offset from top of screen'
|
|
|
|
print 'file ... : file(s) to play; default film.video'
|
|
|
|
print
|
|
|
|
print 'User interface:'
|
|
|
|
print 'Press the left mouse button to stop or restart the movie.'
|
|
|
|
print 'Press ESC or use the window manager Close or Quit command'
|
|
|
|
print 'to close the window and play the next file (if any).'
|
1992-08-18 17:01:02 +00:00
|
|
|
|
|
|
|
|
1992-08-21 12:34:55 +00:00
|
|
|
# Imported modules
|
1992-08-18 17:01:02 +00:00
|
|
|
|
1992-08-18 14:16:12 +00:00
|
|
|
import sys
|
1992-08-21 12:34:55 +00:00
|
|
|
sys.path.append('/ufs/guido/src/video') # Increase chance of finding VFile
|
1992-08-18 14:16:12 +00:00
|
|
|
import VFile
|
|
|
|
import time
|
|
|
|
import gl, GL
|
1992-08-21 12:34:55 +00:00
|
|
|
from DEVICE import REDRAW, ESCKEY, LEFTMOUSE, WINSHUT, WINQUIT
|
1992-08-18 17:01:02 +00:00
|
|
|
import getopt
|
|
|
|
import string
|
|
|
|
|
|
|
|
|
|
|
|
# Global options
|
|
|
|
|
1992-08-21 12:34:55 +00:00
|
|
|
debug = 0
|
1992-08-18 17:01:02 +00:00
|
|
|
looping = 0
|
1992-08-21 12:34:55 +00:00
|
|
|
magnify = 1
|
1992-08-20 11:52:42 +00:00
|
|
|
mindelta = 0
|
1992-08-21 12:34:55 +00:00
|
|
|
nowait = 0
|
1992-08-20 11:52:42 +00:00
|
|
|
quiet = 0
|
|
|
|
regen = None
|
1992-08-21 12:34:55 +00:00
|
|
|
speed = 1.0
|
|
|
|
threading = 0
|
|
|
|
xoff = yoff = None
|
1992-08-18 17:01:02 +00:00
|
|
|
|
|
|
|
|
|
|
|
# Main program -- mostly command line parsing
|
1992-08-18 14:16:12 +00:00
|
|
|
|
|
|
|
def main():
|
1992-08-21 12:34:55 +00:00
|
|
|
global debug, looping, magnify, mindelta, nowait, quiet, regen, speed
|
|
|
|
global threading, xoff, yoff
|
|
|
|
|
|
|
|
# Parse command line
|
|
|
|
try:
|
|
|
|
opts, args = getopt.getopt(sys.argv[1:], 'M:dlm:nqr:s:tx:y:')
|
|
|
|
except getopt.error, msg:
|
|
|
|
sys.stdout = sys.stderr
|
|
|
|
print 'Error:', msg, '\n'
|
|
|
|
help()
|
|
|
|
sys.exit(2)
|
|
|
|
|
|
|
|
# Interpret options
|
|
|
|
try:
|
|
|
|
for opt, arg in opts:
|
|
|
|
if opt == '-M': magnify = string.atoi(arg)
|
|
|
|
if opt == '-d': debug = debug + 1
|
|
|
|
if opt == '-l': looping = 1
|
|
|
|
if opt == '-m': mindelta = string.atoi(arg)
|
|
|
|
if opt == '-n': nowait = 1
|
|
|
|
if opt == '-q': quiet = 1
|
|
|
|
if opt == '-r': regen = string.atoi(arg)
|
|
|
|
if opt == '-s':
|
|
|
|
try:
|
|
|
|
speed = float(eval(arg))
|
|
|
|
except:
|
|
|
|
sys.stdout = sys.stderr
|
|
|
|
print 'Option -s needs float argument'
|
|
|
|
sys.exit(2)
|
|
|
|
if opt == '-t':
|
|
|
|
try:
|
|
|
|
import thread
|
|
|
|
threading = 1
|
|
|
|
except ImportError:
|
|
|
|
print 'Sorry, this version of Python',
|
|
|
|
print 'does not support threads:',
|
|
|
|
print '-t ignored'
|
|
|
|
if opt == '-x': xoff = string.atoi(arg)
|
|
|
|
if opt == '-y': yoff = string.atoi(arg)
|
|
|
|
except string.atoi_error:
|
|
|
|
sys.stdout = sys.stderr
|
|
|
|
print 'Option', opt, 'require integer argument'
|
|
|
|
sys.exit(2)
|
|
|
|
|
|
|
|
# Check validity of certain options combinations
|
|
|
|
if nowait and looping:
|
|
|
|
print 'Warning: -n and -l are mutually exclusive; -n ignored'
|
|
|
|
nowait = 0
|
|
|
|
if xoff <> None and yoff == None:
|
|
|
|
print 'Warning: -x without -y ignored'
|
|
|
|
if xoff == None and yoff <> None:
|
|
|
|
print 'Warning: -y without -x ignored'
|
|
|
|
|
|
|
|
# Process all files
|
|
|
|
if not args: args = ['film.video']
|
|
|
|
sts = 0
|
1992-08-18 17:01:02 +00:00
|
|
|
for filename in args:
|
1992-08-21 12:34:55 +00:00
|
|
|
sts = (process(filename) or sts)
|
|
|
|
|
|
|
|
# Exit with proper exit status
|
|
|
|
sys.exit(sts)
|
1992-08-18 17:01:02 +00:00
|
|
|
|
|
|
|
|
1992-08-20 11:52:42 +00:00
|
|
|
# Process one movie file
|
1992-08-18 14:16:12 +00:00
|
|
|
|
|
|
|
def process(filename):
|
1992-08-20 11:52:42 +00:00
|
|
|
try:
|
|
|
|
vin = VFile.VinFile().init(filename)
|
|
|
|
except IOError, msg:
|
|
|
|
sys.stderr.write(filename + ': I/O error: ' + `msg` + '\n')
|
1992-08-21 12:34:55 +00:00
|
|
|
return 1
|
1992-08-20 11:52:42 +00:00
|
|
|
except VFile.Error, msg:
|
|
|
|
sys.stderr.write(msg + '\n')
|
1992-08-21 12:34:55 +00:00
|
|
|
return 1
|
1992-08-20 11:52:42 +00:00
|
|
|
except EOFError:
|
|
|
|
sys.stderr.write(filename + ': EOF in video header\n')
|
1992-08-21 12:34:55 +00:00
|
|
|
return 1
|
1992-08-20 11:52:42 +00:00
|
|
|
|
|
|
|
if not quiet:
|
|
|
|
print 'File: ', filename
|
|
|
|
print 'Version: ', vin.version
|
|
|
|
print 'Size: ', vin.width, 'x', vin.height
|
|
|
|
print 'Pack: ', vin.packfactor, '; chrom:', vin.chrompack
|
|
|
|
print 'Bits: ', vin.c0bits, vin.c1bits, vin.c2bits
|
|
|
|
print 'Format: ', vin.format
|
|
|
|
print 'Offset: ', vin.offset
|
1992-08-18 14:16:12 +00:00
|
|
|
|
|
|
|
gl.foreground()
|
1992-08-21 12:34:55 +00:00
|
|
|
|
|
|
|
width, height = vin.width * magnify, vin.height * magnify
|
|
|
|
if xoff <> None and yoff <> None:
|
|
|
|
scrheight = gl.getgdesc(GL.GD_YPMAX)
|
|
|
|
gl.prefposition(xoff, xoff+width-1, \
|
|
|
|
scrheight-yoff-height, scrheight-yoff-1)
|
|
|
|
else:
|
|
|
|
gl.prefsize(width, height)
|
|
|
|
|
1992-08-20 11:52:42 +00:00
|
|
|
win = gl.winopen(filename)
|
1992-08-21 12:34:55 +00:00
|
|
|
gl.clear()
|
|
|
|
|
|
|
|
if quiet: vin.quiet = 1
|
1992-08-18 14:16:12 +00:00
|
|
|
vin.initcolormap()
|
|
|
|
|
|
|
|
gl.qdevice(ESCKEY)
|
|
|
|
gl.qdevice(WINSHUT)
|
|
|
|
gl.qdevice(WINQUIT)
|
1992-08-21 12:34:55 +00:00
|
|
|
gl.qdevice(LEFTMOUSE)
|
1992-08-18 14:16:12 +00:00
|
|
|
|
1992-08-21 12:34:55 +00:00
|
|
|
stop = 0
|
1992-08-20 11:52:42 +00:00
|
|
|
|
|
|
|
while not stop:
|
1992-08-21 12:34:55 +00:00
|
|
|
gl.wintitle(filename)
|
|
|
|
stop = (playonce(vin) or nowait)
|
|
|
|
gl.wintitle('(done) ' + filename)
|
|
|
|
if not looping:
|
|
|
|
while not stop:
|
|
|
|
dev, val = gl.qread()
|
|
|
|
if dev == LEFTMOUSE and val == 1:
|
|
|
|
break # Continue outer loop
|
|
|
|
if dev == ESCKEY and val == 1 or \
|
|
|
|
dev in (WINSHUT, WINQUIT):
|
|
|
|
stop = 1
|
|
|
|
|
|
|
|
# Set xoff, yoff for the next window from the current window
|
|
|
|
global xoff, yoff
|
|
|
|
xoff, yoff = gl.getorigin()
|
|
|
|
width, height = gl.getsize()
|
|
|
|
scrheight = gl.getgdesc(GL.GD_YPMAX)
|
|
|
|
yoff = scrheight - yoff - height
|
1992-08-20 11:52:42 +00:00
|
|
|
gl.winclose(win)
|
|
|
|
|
1992-08-21 12:34:55 +00:00
|
|
|
return 0
|
|
|
|
|
1992-08-20 11:52:42 +00:00
|
|
|
|
|
|
|
# Play a movie once; return 1 if user wants to stop, 0 if not
|
|
|
|
|
|
|
|
def playonce(vin):
|
1992-08-21 12:34:55 +00:00
|
|
|
vin.rewind()
|
1992-08-20 11:52:42 +00:00
|
|
|
vin.colormapinited = 1
|
|
|
|
vin.magnify = magnify
|
|
|
|
|
1992-08-21 12:34:55 +00:00
|
|
|
if threading:
|
1992-08-25 12:29:30 +00:00
|
|
|
MAXSIZE = 20 # Don't read ahead too much
|
1992-08-21 12:34:55 +00:00
|
|
|
import thread
|
1992-08-25 12:29:30 +00:00
|
|
|
import Queue
|
|
|
|
queue = Queue.Queue().init(MAXSIZE)
|
1992-08-21 12:34:55 +00:00
|
|
|
stop = []
|
|
|
|
thread.start_new_thread(read_ahead, (vin, queue, stop))
|
|
|
|
# Get the read-ahead thread going
|
1992-08-25 12:29:30 +00:00
|
|
|
while queue.qsize() < MAXSIZE/2 and not stop:
|
|
|
|
time.millisleep(100)
|
1992-08-21 12:34:55 +00:00
|
|
|
|
1992-08-20 11:52:42 +00:00
|
|
|
tin = 0
|
|
|
|
told = 0
|
|
|
|
nin = 0
|
|
|
|
nout = 0
|
1992-08-21 12:34:55 +00:00
|
|
|
nlate = 0
|
1992-08-20 11:52:42 +00:00
|
|
|
nskipped = 0
|
1992-08-21 12:34:55 +00:00
|
|
|
data = None
|
1992-08-20 11:52:42 +00:00
|
|
|
|
1992-08-21 12:34:55 +00:00
|
|
|
tlast = t0 = time.millitimer()
|
1992-08-20 11:52:42 +00:00
|
|
|
|
1992-08-18 14:16:12 +00:00
|
|
|
while 1:
|
1992-08-21 12:34:55 +00:00
|
|
|
if gl.qtest():
|
|
|
|
dev, val = gl.qread()
|
|
|
|
if dev == ESCKEY and val == 1 or \
|
|
|
|
dev in (WINSHUT, WINQUIT) or \
|
|
|
|
dev == LEFTMOUSE and val == 1:
|
|
|
|
if debug: sys.stderr.write('\n')
|
|
|
|
if threading:
|
|
|
|
stop.append(None)
|
1992-08-25 12:29:30 +00:00
|
|
|
while 1:
|
|
|
|
item = queue.get()
|
|
|
|
if item == None: break
|
1992-08-21 12:34:55 +00:00
|
|
|
return (dev != LEFTMOUSE)
|
|
|
|
if dev == REDRAW:
|
|
|
|
gl.reshapeviewport()
|
|
|
|
if data: vin.showframe(data, cdata)
|
|
|
|
if threading:
|
1992-08-25 12:29:30 +00:00
|
|
|
if debug and queue.empty(): sys.stderr.write('.')
|
|
|
|
item = queue.get()
|
|
|
|
if item == None: break
|
|
|
|
tin, data, cdata = item
|
1992-08-20 11:52:42 +00:00
|
|
|
else:
|
1992-08-18 14:16:12 +00:00
|
|
|
try:
|
1992-08-21 12:34:55 +00:00
|
|
|
tin, size, csize = vin.getnextframeheader()
|
1992-08-18 14:16:12 +00:00
|
|
|
except EOFError:
|
1992-08-20 11:52:42 +00:00
|
|
|
break
|
1992-08-21 12:34:55 +00:00
|
|
|
nin = nin+1
|
|
|
|
if regen: tout = nin * regen
|
|
|
|
else: tout = tin
|
|
|
|
tout = int(tout / speed)
|
|
|
|
if tout - told < mindelta:
|
1992-08-20 11:52:42 +00:00
|
|
|
nskipped = nskipped + 1
|
|
|
|
else:
|
1992-08-21 12:34:55 +00:00
|
|
|
if not threading:
|
1992-08-20 11:52:42 +00:00
|
|
|
try:
|
1992-08-21 12:34:55 +00:00
|
|
|
data, cdata = \
|
|
|
|
vin.getnextframedata(size, csize)
|
1992-08-20 11:52:42 +00:00
|
|
|
except EOFError:
|
1992-08-21 12:34:55 +00:00
|
|
|
if not quiet:
|
|
|
|
print '[incomplete last frame]'
|
1992-08-20 11:52:42 +00:00
|
|
|
break
|
1992-08-21 12:34:55 +00:00
|
|
|
now = time.millitimer()
|
|
|
|
dt = (tout-told) - (now-tlast)
|
|
|
|
told = tout
|
|
|
|
if debug: sys.stderr.write(`dt/10` + ' ')
|
|
|
|
if dt < 0: nlate = nlate + 1
|
|
|
|
if dt > 0:
|
|
|
|
time.millisleep(dt)
|
|
|
|
now = now + dt
|
|
|
|
tlast = now
|
|
|
|
vin.showframe(data, cdata)
|
|
|
|
nout = nout + 1
|
1992-08-20 11:52:42 +00:00
|
|
|
|
|
|
|
t1 = time.millitimer()
|
|
|
|
|
1992-08-21 12:34:55 +00:00
|
|
|
if debug: sys.stderr.write('\n')
|
|
|
|
|
|
|
|
if quiet: return 0
|
1992-08-20 11:52:42 +00:00
|
|
|
|
|
|
|
print 'Recorded:', nin, 'frames in', tin*0.001, 'sec.',
|
|
|
|
if tin: print '-- average', int(nin*10000.0/tin)*0.1, 'frames/sec',
|
|
|
|
print
|
|
|
|
|
1992-08-21 12:34:55 +00:00
|
|
|
if nskipped: print 'Skipped', nskipped, 'frames'
|
1992-08-20 11:52:42 +00:00
|
|
|
|
|
|
|
tout = t1-t0
|
|
|
|
print 'Played:', nout,
|
|
|
|
print 'frames in', tout*0.001, 'sec.',
|
|
|
|
if tout: print '-- average', int(nout*10000.0/tout)*0.1, 'frames/sec',
|
|
|
|
print
|
|
|
|
|
1992-08-21 12:34:55 +00:00
|
|
|
if nlate: print 'There were', nlate, 'late frames'
|
1992-08-20 11:52:42 +00:00
|
|
|
|
|
|
|
return 0
|
1992-08-18 14:16:12 +00:00
|
|
|
|
1992-08-18 17:01:02 +00:00
|
|
|
|
1992-08-21 12:34:55 +00:00
|
|
|
# Read-ahead thread
|
|
|
|
|
|
|
|
def read_ahead(vin, queue, stop):
|
|
|
|
try:
|
1992-08-25 12:29:30 +00:00
|
|
|
while not stop: queue.put(vin.getnextframe())
|
1992-08-21 12:34:55 +00:00
|
|
|
except EOFError:
|
1992-08-25 12:29:30 +00:00
|
|
|
pass
|
|
|
|
queue.put(None)
|
1992-08-21 12:34:55 +00:00
|
|
|
stop.append(None)
|
|
|
|
|
|
|
|
|
1992-08-18 17:01:02 +00:00
|
|
|
# Don't forget to call the main program
|
|
|
|
|
1992-08-21 12:34:55 +00:00
|
|
|
try:
|
|
|
|
main()
|
|
|
|
except KeyboardInterrupt:
|
|
|
|
print '[Interrupt]'
|