blob: facd20f3fea65ee82a24a2aced35efee2f4306d3 [file] [log] [blame]
Guido van Rossume755aa51992-08-21 12:34:55 +00001#! /ufs/guido/bin/sgi/python-405
2#! /ufs/guido/bin/sgi/python
Guido van Rossum82534fd1992-08-18 17:01:02 +00003#! /usr/local/python
4
5# Play CMIF movie files
6
7
Guido van Rossume755aa51992-08-21 12:34:55 +00008# Help function
9
10def help():
11 print 'Usage: Vplay [options] [file] ...'
12 print
13 print 'Options:'
14 print '-M magnify : magnify the image by the given factor'
15 print '-d : write some debug stuff on stderr'
16 print '-l : loop, playing the movie over and over again'
17 print '-m delta : drop frames closer than delta msec (default 0)'
Guido van Rossume1783321992-09-07 09:35:23 +000018 print '-n : don\'t wait after each file'
Guido van Rossume755aa51992-08-21 12:34:55 +000019 print '-q : quiet, no informative messages'
20 print '-r delta : regenerate input time base delta msec apart'
21 print '-s speed : speed change factor (default 1.0)'
22 print '-t : use a 2nd thread for read-ahead'
23 print '-x left : window offset from left of screen'
24 print '-y top : window offset from top of screen'
25 print 'file ... : file(s) to play; default film.video'
26 print
27 print 'User interface:'
28 print 'Press the left mouse button to stop or restart the movie.'
29 print 'Press ESC or use the window manager Close or Quit command'
30 print 'to close the window and play the next file (if any).'
Guido van Rossum82534fd1992-08-18 17:01:02 +000031
32
Guido van Rossume755aa51992-08-21 12:34:55 +000033# Imported modules
Guido van Rossum82534fd1992-08-18 17:01:02 +000034
Guido van Rossum843d1531992-08-18 14:16:12 +000035import sys
Guido van Rossume755aa51992-08-21 12:34:55 +000036sys.path.append('/ufs/guido/src/video') # Increase chance of finding VFile
Guido van Rossum843d1531992-08-18 14:16:12 +000037import VFile
38import time
39import gl, GL
Guido van Rossume755aa51992-08-21 12:34:55 +000040from DEVICE import REDRAW, ESCKEY, LEFTMOUSE, WINSHUT, WINQUIT
Guido van Rossum82534fd1992-08-18 17:01:02 +000041import getopt
42import string
43
44
45# Global options
46
Guido van Rossume755aa51992-08-21 12:34:55 +000047debug = 0
Guido van Rossum82534fd1992-08-18 17:01:02 +000048looping = 0
Guido van Rossume755aa51992-08-21 12:34:55 +000049magnify = 1
Guido van Rossum78aab861992-08-20 11:52:42 +000050mindelta = 0
Guido van Rossume755aa51992-08-21 12:34:55 +000051nowait = 0
Guido van Rossum78aab861992-08-20 11:52:42 +000052quiet = 0
53regen = None
Guido van Rossume755aa51992-08-21 12:34:55 +000054speed = 1.0
55threading = 0
56xoff = yoff = None
Guido van Rossum82534fd1992-08-18 17:01:02 +000057
58
59# Main program -- mostly command line parsing
Guido van Rossum843d1531992-08-18 14:16:12 +000060
61def main():
Guido van Rossume755aa51992-08-21 12:34:55 +000062 global debug, looping, magnify, mindelta, nowait, quiet, regen, speed
63 global threading, xoff, yoff
64
65 # Parse command line
66 try:
67 opts, args = getopt.getopt(sys.argv[1:], 'M:dlm:nqr:s:tx:y:')
68 except getopt.error, msg:
69 sys.stdout = sys.stderr
70 print 'Error:', msg, '\n'
71 help()
72 sys.exit(2)
73
74 # Interpret options
75 try:
76 for opt, arg in opts:
Guido van Rossume0be2b31992-09-01 14:45:57 +000077 if opt == '-M': magnify = float(eval(arg))
Guido van Rossume755aa51992-08-21 12:34:55 +000078 if opt == '-d': debug = debug + 1
79 if opt == '-l': looping = 1
80 if opt == '-m': mindelta = string.atoi(arg)
81 if opt == '-n': nowait = 1
82 if opt == '-q': quiet = 1
83 if opt == '-r': regen = string.atoi(arg)
84 if opt == '-s':
85 try:
86 speed = float(eval(arg))
87 except:
88 sys.stdout = sys.stderr
89 print 'Option -s needs float argument'
90 sys.exit(2)
91 if opt == '-t':
92 try:
93 import thread
94 threading = 1
95 except ImportError:
96 print 'Sorry, this version of Python',
97 print 'does not support threads:',
98 print '-t ignored'
99 if opt == '-x': xoff = string.atoi(arg)
100 if opt == '-y': yoff = string.atoi(arg)
101 except string.atoi_error:
102 sys.stdout = sys.stderr
103 print 'Option', opt, 'require integer argument'
104 sys.exit(2)
105
106 # Check validity of certain options combinations
107 if nowait and looping:
108 print 'Warning: -n and -l are mutually exclusive; -n ignored'
109 nowait = 0
110 if xoff <> None and yoff == None:
111 print 'Warning: -x without -y ignored'
112 if xoff == None and yoff <> None:
113 print 'Warning: -y without -x ignored'
114
115 # Process all files
116 if not args: args = ['film.video']
117 sts = 0
Guido van Rossum82534fd1992-08-18 17:01:02 +0000118 for filename in args:
Guido van Rossume755aa51992-08-21 12:34:55 +0000119 sts = (process(filename) or sts)
120
121 # Exit with proper exit status
122 sys.exit(sts)
Guido van Rossum82534fd1992-08-18 17:01:02 +0000123
124
Guido van Rossum78aab861992-08-20 11:52:42 +0000125# Process one movie file
Guido van Rossum843d1531992-08-18 14:16:12 +0000126
127def process(filename):
Guido van Rossum78aab861992-08-20 11:52:42 +0000128 try:
129 vin = VFile.VinFile().init(filename)
130 except IOError, msg:
131 sys.stderr.write(filename + ': I/O error: ' + `msg` + '\n')
Guido van Rossume755aa51992-08-21 12:34:55 +0000132 return 1
Guido van Rossum78aab861992-08-20 11:52:42 +0000133 except VFile.Error, msg:
134 sys.stderr.write(msg + '\n')
Guido van Rossume755aa51992-08-21 12:34:55 +0000135 return 1
Guido van Rossum78aab861992-08-20 11:52:42 +0000136 except EOFError:
137 sys.stderr.write(filename + ': EOF in video header\n')
Guido van Rossume755aa51992-08-21 12:34:55 +0000138 return 1
Guido van Rossum78aab861992-08-20 11:52:42 +0000139
140 if not quiet:
Guido van Rossume1783321992-09-07 09:35:23 +0000141 vin.printinfo()
Guido van Rossum843d1531992-08-18 14:16:12 +0000142
143 gl.foreground()
Guido van Rossume755aa51992-08-21 12:34:55 +0000144
Guido van Rossume0be2b31992-09-01 14:45:57 +0000145 width, height = int(vin.width * magnify), int(vin.height * magnify)
Guido van Rossume755aa51992-08-21 12:34:55 +0000146 if xoff <> None and yoff <> None:
147 scrheight = gl.getgdesc(GL.GD_YPMAX)
148 gl.prefposition(xoff, xoff+width-1, \
149 scrheight-yoff-height, scrheight-yoff-1)
150 else:
151 gl.prefsize(width, height)
152
Guido van Rossum78aab861992-08-20 11:52:42 +0000153 win = gl.winopen(filename)
Guido van Rossume755aa51992-08-21 12:34:55 +0000154 gl.clear()
155
156 if quiet: vin.quiet = 1
Guido van Rossum843d1531992-08-18 14:16:12 +0000157 vin.initcolormap()
158
159 gl.qdevice(ESCKEY)
160 gl.qdevice(WINSHUT)
161 gl.qdevice(WINQUIT)
Guido van Rossume755aa51992-08-21 12:34:55 +0000162 gl.qdevice(LEFTMOUSE)
Guido van Rossum843d1531992-08-18 14:16:12 +0000163
Guido van Rossume755aa51992-08-21 12:34:55 +0000164 stop = 0
Guido van Rossum78aab861992-08-20 11:52:42 +0000165
166 while not stop:
Guido van Rossume755aa51992-08-21 12:34:55 +0000167 gl.wintitle(filename)
168 stop = (playonce(vin) or nowait)
169 gl.wintitle('(done) ' + filename)
170 if not looping:
171 while not stop:
172 dev, val = gl.qread()
173 if dev == LEFTMOUSE and val == 1:
174 break # Continue outer loop
175 if dev == ESCKEY and val == 1 or \
176 dev in (WINSHUT, WINQUIT):
177 stop = 1
Guido van Rossum78aab861992-08-20 11:52:42 +0000178
Guido van Rossume755aa51992-08-21 12:34:55 +0000179 # Set xoff, yoff for the next window from the current window
180 global xoff, yoff
181 xoff, yoff = gl.getorigin()
182 width, height = gl.getsize()
183 scrheight = gl.getgdesc(GL.GD_YPMAX)
184 yoff = scrheight - yoff - height
Guido van Rossum78aab861992-08-20 11:52:42 +0000185 gl.winclose(win)
186
Guido van Rossume755aa51992-08-21 12:34:55 +0000187 return 0
188
Guido van Rossum78aab861992-08-20 11:52:42 +0000189
190# Play a movie once; return 1 if user wants to stop, 0 if not
191
192def playonce(vin):
Guido van Rossume755aa51992-08-21 12:34:55 +0000193 vin.rewind()
Guido van Rossum78aab861992-08-20 11:52:42 +0000194 vin.colormapinited = 1
195 vin.magnify = magnify
196
Guido van Rossume755aa51992-08-21 12:34:55 +0000197 if threading:
Guido van Rossum9ee7e151992-08-25 12:29:30 +0000198 MAXSIZE = 20 # Don't read ahead too much
Guido van Rossume755aa51992-08-21 12:34:55 +0000199 import thread
Guido van Rossum9ee7e151992-08-25 12:29:30 +0000200 import Queue
201 queue = Queue.Queue().init(MAXSIZE)
Guido van Rossume755aa51992-08-21 12:34:55 +0000202 stop = []
203 thread.start_new_thread(read_ahead, (vin, queue, stop))
204 # Get the read-ahead thread going
Guido van Rossum9ee7e151992-08-25 12:29:30 +0000205 while queue.qsize() < MAXSIZE/2 and not stop:
206 time.millisleep(100)
Guido van Rossume755aa51992-08-21 12:34:55 +0000207
Guido van Rossum78aab861992-08-20 11:52:42 +0000208 tin = 0
Guido van Rossume1783321992-09-07 09:35:23 +0000209 toffset = 0
210 oldtin = 0
Guido van Rossum78aab861992-08-20 11:52:42 +0000211 told = 0
212 nin = 0
213 nout = 0
Guido van Rossume755aa51992-08-21 12:34:55 +0000214 nlate = 0
Guido van Rossum78aab861992-08-20 11:52:42 +0000215 nskipped = 0
Guido van Rossume755aa51992-08-21 12:34:55 +0000216 data = None
Guido van Rossum78aab861992-08-20 11:52:42 +0000217
Guido van Rossume755aa51992-08-21 12:34:55 +0000218 tlast = t0 = time.millitimer()
Guido van Rossum78aab861992-08-20 11:52:42 +0000219
220 while 1:
Guido van Rossum78aab861992-08-20 11:52:42 +0000221 if gl.qtest():
Guido van Rossum843d1531992-08-18 14:16:12 +0000222 dev, val = gl.qread()
Guido van Rossume755aa51992-08-21 12:34:55 +0000223 if dev == ESCKEY and val == 1 or \
224 dev in (WINSHUT, WINQUIT) or \
225 dev == LEFTMOUSE and val == 1:
226 if debug: sys.stderr.write('\n')
227 if threading:
228 stop.append(None)
Guido van Rossum9ee7e151992-08-25 12:29:30 +0000229 while 1:
230 item = queue.get()
231 if item == None: break
Guido van Rossume755aa51992-08-21 12:34:55 +0000232 return (dev != LEFTMOUSE)
Guido van Rossum843d1531992-08-18 14:16:12 +0000233 if dev == REDRAW:
234 gl.reshapeviewport()
Guido van Rossume755aa51992-08-21 12:34:55 +0000235 if data: vin.showframe(data, cdata)
236 if threading:
Guido van Rossum9ee7e151992-08-25 12:29:30 +0000237 if debug and queue.empty(): sys.stderr.write('.')
238 item = queue.get()
239 if item == None: break
240 tin, data, cdata = item
Guido van Rossume755aa51992-08-21 12:34:55 +0000241 else:
242 try:
243 tin, size, csize = vin.getnextframeheader()
244 except EOFError:
245 break
246 nin = nin+1
Guido van Rossume1783321992-09-07 09:35:23 +0000247 if tin+toffset < oldtin:
248 print 'Fix reversed time:', oldtin, 'to', tin
249 toffset = oldtin - tin
250 tin = tin + toffset
251 oldtin = tin
Guido van Rossume755aa51992-08-21 12:34:55 +0000252 if regen: tout = nin * regen
253 else: tout = tin
254 tout = int(tout / speed)
255 if tout - told < mindelta:
256 nskipped = nskipped + 1
Guido van Rossume1783321992-09-07 09:35:23 +0000257 if not threading:
258 vin.skipnextframedata(size, csize)
Guido van Rossume755aa51992-08-21 12:34:55 +0000259 else:
260 if not threading:
261 try:
262 data, cdata = \
263 vin.getnextframedata(size, csize)
264 except EOFError:
265 if not quiet:
266 print '[incomplete last frame]'
267 break
268 now = time.millitimer()
269 dt = (tout-told) - (now-tlast)
270 told = tout
271 if debug: sys.stderr.write(`dt/10` + ' ')
272 if dt < 0: nlate = nlate + 1
273 if dt > 0:
274 time.millisleep(dt)
275 now = now + dt
276 tlast = now
277 vin.showframe(data, cdata)
278 nout = nout + 1
Guido van Rossum78aab861992-08-20 11:52:42 +0000279
280 t1 = time.millitimer()
281
Guido van Rossume755aa51992-08-21 12:34:55 +0000282 if debug: sys.stderr.write('\n')
283
284 if quiet: return 0
Guido van Rossum78aab861992-08-20 11:52:42 +0000285
286 print 'Recorded:', nin, 'frames in', tin*0.001, 'sec.',
287 if tin: print '-- average', int(nin*10000.0/tin)*0.1, 'frames/sec',
288 print
289
Guido van Rossume755aa51992-08-21 12:34:55 +0000290 if nskipped: print 'Skipped', nskipped, 'frames'
Guido van Rossum78aab861992-08-20 11:52:42 +0000291
292 tout = t1-t0
293 print 'Played:', nout,
294 print 'frames in', tout*0.001, 'sec.',
295 if tout: print '-- average', int(nout*10000.0/tout)*0.1, 'frames/sec',
296 print
297
Guido van Rossume755aa51992-08-21 12:34:55 +0000298 if nlate: print 'There were', nlate, 'late frames'
Guido van Rossum78aab861992-08-20 11:52:42 +0000299
300 return 0
Guido van Rossum843d1531992-08-18 14:16:12 +0000301
Guido van Rossum82534fd1992-08-18 17:01:02 +0000302
Guido van Rossume755aa51992-08-21 12:34:55 +0000303# Read-ahead thread
304
305def read_ahead(vin, queue, stop):
306 try:
Guido van Rossum9ee7e151992-08-25 12:29:30 +0000307 while not stop: queue.put(vin.getnextframe())
Guido van Rossume755aa51992-08-21 12:34:55 +0000308 except EOFError:
Guido van Rossum9ee7e151992-08-25 12:29:30 +0000309 pass
310 queue.put(None)
Guido van Rossume755aa51992-08-21 12:34:55 +0000311 stop.append(None)
312
313
Guido van Rossum82534fd1992-08-18 17:01:02 +0000314# Don't forget to call the main program
315
Guido van Rossume755aa51992-08-21 12:34:55 +0000316try:
317 main()
318except KeyboardInterrupt:
319 print '[Interrupt]'