Redesigned option processing and added several new options.

Added optional read-ahead thread.
Changed mouse interface.
This commit is contained in:
Guido van Rossum 1992-08-21 12:34:55 +00:00
parent 8a861be7f3
commit e755aa50e2
1 changed files with 212 additions and 115 deletions

View File

@ -1,77 +1,124 @@
#! /ufs/guido/bin/sgi/python-405
#! /ufs/guido/bin/sgi/python
#! /usr/local/python #! /usr/local/python
# Play CMIF movie files # Play CMIF movie files
# Usage: # Help function
#
# Vplay [-L] [-M maginfy] [-m msec] [-q] [-r msec] [-s factor] [file] ... 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).'
# Options: # Imported modules
#
# -L : loop, playing the movie over and over again
# -M magnify : magnify the image by the given factor
# -m n : drop frames closer than n msec (default 0)
# -q : quiet, no informative messages
# -r n : regenerate input time base n msec apart
# -s speed : speed change factor after other processing (default 1.0)
# file ... : file(s) to play; default film.video
# User interface:
#
# Place the windo where you want it. The size is determined by the
# movie file and the -m option.
#
# Press ESC or select the window manager Quit or Close window option
# to close a window; if more files are given the window for the next
# file now pops up. Unless looping, the window closes automatically
# at the end of the movie.
import sys import sys
sys.path.append('/ufs/guido/src/video') sys.path.append('/ufs/guido/src/video') # Increase chance of finding VFile
import VFile import VFile
import time import time
import gl, GL import gl, GL
from DEVICE import * from DEVICE import REDRAW, ESCKEY, LEFTMOUSE, WINSHUT, WINQUIT
import getopt import getopt
import string import string
# Global options # Global options
magnify = 1 debug = 0
looping = 0 looping = 0
speed = 1.0 magnify = 1
mindelta = 0 mindelta = 0
nowait = 0
quiet = 0 quiet = 0
regen = None regen = None
speed = 1.0
threading = 0
xoff = yoff = None
# Main program -- mostly command line parsing # Main program -- mostly command line parsing
def main(): def main():
global magnify, looping, speed, mindelta, quiet, regen global debug, looping, magnify, mindelta, nowait, quiet, regen, speed
opts, args = getopt.getopt(sys.argv[1:], 'LM:m:qr:s:') global threading, xoff, yoff
for opt, arg in opts:
if opt == '-L': # Parse command line
looping = 1 try:
elif opt == '-M': opts, args = getopt.getopt(sys.argv[1:], 'M:dlm:nqr:s:tx:y:')
magnify = string.atoi(arg) except getopt.error, msg:
elif opt == '-m': sys.stdout = sys.stderr
mindelta = string.atoi(arg) print 'Error:', msg, '\n'
elif opt == '-q': help()
quiet = 1 sys.exit(2)
elif opt == '-r':
regen = string.atoi(arg) # Interpret options
elif opt == '-s': try:
speed = float(eval(arg)) for opt, arg in opts:
if not args: if opt == '-M': magnify = string.atoi(arg)
args = ['film.video'] 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
for filename in args: for filename in args:
process(filename) sts = (process(filename) or sts)
# Exit with proper exit status
sys.exit(sts)
# Process one movie file # Process one movie file
@ -81,13 +128,13 @@ def process(filename):
vin = VFile.VinFile().init(filename) vin = VFile.VinFile().init(filename)
except IOError, msg: except IOError, msg:
sys.stderr.write(filename + ': I/O error: ' + `msg` + '\n') sys.stderr.write(filename + ': I/O error: ' + `msg` + '\n')
return return 1
except VFile.Error, msg: except VFile.Error, msg:
sys.stderr.write(msg + '\n') sys.stderr.write(msg + '\n')
return return 1
except EOFError: except EOFError:
sys.stderr.write(filename + ': EOF in video header\n') sys.stderr.write(filename + ': EOF in video header\n')
return return 1
if not quiet: if not quiet:
print 'File: ', filename print 'File: ', filename
@ -99,108 +146,145 @@ def process(filename):
print 'Offset: ', vin.offset print 'Offset: ', vin.offset
gl.foreground() gl.foreground()
gl.prefsize(vin.width * magnify, vin.height * magnify)
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)
win = gl.winopen(filename) win = gl.winopen(filename)
if quiet: gl.clear()
vin.quiet = 1
if quiet: vin.quiet = 1
vin.initcolormap() vin.initcolormap()
gl.qdevice(ESCKEY) gl.qdevice(ESCKEY)
gl.qdevice(WINSHUT) gl.qdevice(WINSHUT)
gl.qdevice(WINQUIT) gl.qdevice(WINQUIT)
gl.qdevice(LEFTMOUSE)
while 1: stop = 0
stop = playonce(vin)
if stop or not looping:
break
gl.wintitle('(done) ' + filename)
while not stop: while not stop:
dev, val = gl.qread() gl.wintitle(filename)
if dev in (ESCKEY, WINSHUT, WINQUIT): stop = (playonce(vin) or nowait)
stop = 1 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
gl.winclose(win) gl.winclose(win)
return 0
# Play a movie once; return 1 if user wants to stop, 0 if not # Play a movie once; return 1 if user wants to stop, 0 if not
def playonce(vin): def playonce(vin):
if vin.hascache: vin.rewind()
vin.rewind()
vin.colormapinited = 1 vin.colormapinited = 1
vin.magnify = magnify vin.magnify = magnify
if threading:
import thread
queue = []
stop = []
thread.start_new_thread(read_ahead, (vin, queue, stop))
# Get the read-ahead thread going
while len(queue) < 5 and None not in queue:
time.millisleep(10)
tin = 0 tin = 0
told = 0 told = 0
nin = 0 nin = 0
nout = 0 nout = 0
nmissed = 0 nlate = 0
nskipped = 0 nskipped = 0
data = None
t0 = time.millitimer() tlast = t0 = time.millitimer()
while 1: while 1:
try:
tin, size, csize = vin.getnextframeheader()
except EOFError:
break
nin = nin+1
if regen:
tout = nin * regen
else:
tout = tin
tout = int(tout / speed)
if tout - told < mindelta:
try:
vin.skipnextframedata(size, csize)
except EOFError:
print '[short data at EOF]'
break
nskipped = nskipped + 1
else:
told = tout
dt = tout + t0 - time.millitimer()
if dt < 0:
try:
vin.skipnextframedata(size, csize)
except EOFError:
print '[short data at EOF]'
break
nmissed = nmissed + 1
else:
try:
data, cdata = vin.getnextframedata \
(size, csize)
except EOFError:
print '[short data at EOF]'
break
dt = tout + t0 - time.millitimer()
if dt > 0:
time.millisleep(dt)
vin.showframe(data, cdata)
nout = nout + 1
if gl.qtest(): if gl.qtest():
dev, val = gl.qread() dev, val = gl.qread()
if dev in (ESCKEY, WINSHUT, WINQUIT): if dev == ESCKEY and val == 1 or \
return 1 dev in (WINSHUT, WINQUIT) or \
dev == LEFTMOUSE and val == 1:
if debug: sys.stderr.write('\n')
if threading:
stop.append(None)
while len(stop) < 2:
time.millisleep(10)
return (dev != LEFTMOUSE)
if dev == REDRAW: if dev == REDRAW:
gl.reshapeviewport() gl.reshapeviewport()
if data: if data: vin.showframe(data, cdata)
vin.showframe(data, cdata) if threading:
if not queue:
if debug: sys.stderr.write('.')
time.millisleep(10)
continue
q0 = queue[0]
if q0 == None: break
del queue[0]
tin, data, cdata = q0
else:
try:
tin, size, csize = vin.getnextframeheader()
except EOFError:
break
nin = nin+1
if regen: tout = nin * regen
else: tout = tin
tout = int(tout / speed)
if tout - told < mindelta:
nskipped = nskipped + 1
else:
if not threading:
try:
data, cdata = \
vin.getnextframedata(size, csize)
except EOFError:
if not quiet:
print '[incomplete last frame]'
break
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
t1 = time.millitimer() t1 = time.millitimer()
if quiet: if debug: sys.stderr.write('\n')
return 0
if quiet: return 0
print 'Recorded:', nin, 'frames in', tin*0.001, 'sec.', print 'Recorded:', nin, 'frames in', tin*0.001, 'sec.',
if tin: print '-- average', int(nin*10000.0/tin)*0.1, 'frames/sec', if tin: print '-- average', int(nin*10000.0/tin)*0.1, 'frames/sec',
print print
if nskipped: if nskipped: print 'Skipped', nskipped, 'frames'
print 'Skipped', nskipped, 'frames'
tout = t1-t0 tout = t1-t0
print 'Played:', nout, print 'Played:', nout,
@ -208,12 +292,25 @@ def playonce(vin):
if tout: print '-- average', int(nout*10000.0/tout)*0.1, 'frames/sec', if tout: print '-- average', int(nout*10000.0/tout)*0.1, 'frames/sec',
print print
if nmissed: if nlate: print 'There were', nlate, 'late frames'
print 'Missed', nmissed, 'frames'
return 0 return 0
# Read-ahead thread
def read_ahead(vin, queue, stop):
try:
while not stop: queue.append(vin.getnextframe())
except EOFError:
queue.append(None)
stop.append(None)
# Don't forget to call the main program # Don't forget to call the main program
main() try:
main()
except KeyboardInterrupt:
print '[Interrupt]'