The 0.5 release happened on 2/15, not on 2/14. :-)
[python/dscho.git] / Demo / sgi / video / Vplay.py
blob176c0e5a0c0dcbf5b853fea9316b53f279a249f0
1 #! /usr/bin/env python
3 # Play CMIF movie files
6 # Help function
8 def help():
9 print 'Usage: Vplay [options] [file] ...'
10 print
11 print 'Options:'
12 print '-M magnify : magnify the image by the given factor'
13 print '-d : write some debug stuff on stderr'
14 print '-l : loop, playing the movie over and over again'
15 print '-m delta : drop frames closer than delta seconds (default 0.)'
16 print '-n : don\'t wait after each file'
17 print '-q : quiet, no informative messages'
18 print '-r delta : regenerate input time base delta seconds apart'
19 print '-s speed : speed change factor (default 1.0)'
20 print '-t : use a 2nd thread for read-ahead'
21 print '-x left : window offset from left of screen'
22 print '-y top : window offset from top of screen'
23 print '-w width : window width'
24 print '-h height : window height'
25 print '-b color : background color (white,black or (r,g,b))'
26 print 'file ... : file(s) to play; default film.video'
27 print
28 print 'User interface:'
29 print 'Press the left mouse button to stop or restart the movie.'
30 print 'Press ESC or use the window manager Close or Quit command'
31 print 'to close the window and play the next file (if any).'
34 # Imported modules
36 import sys
37 sys.path.append('/ufs/guido/src/video') # Increase chance of finding VFile
38 import VFile
39 import time
40 import gl, GL
41 from DEVICE import REDRAW, ESCKEY, LEFTMOUSE, WINSHUT, WINQUIT
42 import getopt
43 import string
46 # Global options
48 debug = 0
49 looping = 0
50 magnify = 1
51 mindelta = 0
52 nowait = 0
53 quiet = 0
54 regen = None
55 speed = 1.0
56 threading = 0
57 xoff = yoff = None
58 xwsiz = ywsiz = None
59 bgcolor = None
62 # Main program -- mostly command line parsing
64 def main():
65 global debug, looping, magnify, mindelta, nowait, quiet, regen, speed
66 global threading, xoff, yoff, xwsiz, ywsiz, bgcolor
68 # Parse command line
69 try:
70 opts, args = getopt.getopt(sys.argv[1:], \
71 'M:dlm:nqr:s:tx:y:w:h:b:')
72 except getopt.error, msg:
73 sys.stdout = sys.stderr
74 print 'Error:', msg, '\n'
75 help()
76 sys.exit(2)
78 # Interpret options
79 try:
80 for opt, arg in opts:
81 if opt == '-M': magnify = float(eval(arg))
82 if opt == '-d': debug = debug + 1
83 if opt == '-l': looping = 1
84 if opt == '-m': mindelta = float(eval(arg))
85 if opt == '-n': nowait = 1
86 if opt == '-q': quiet = 1
87 if opt == '-r': regen = float(eval(arg))
88 if opt == '-s':
89 try:
90 speed = float(eval(arg))
91 except:
92 sys.stdout = sys.stderr
93 print 'Option -s needs float argument'
94 sys.exit(2)
95 if opt == '-t':
96 try:
97 import thread
98 threading = 1
99 except ImportError:
100 print 'Sorry, this version of Python',
101 print 'does not support threads:',
102 print '-t ignored'
103 if opt == '-x': xoff = string.atoi(arg)
104 if opt == '-y': yoff = string.atoi(arg)
105 if opt == '-w': xwsiz = string.atoi(arg)
106 if opt == '-h': ywsiz = string.atoi(arg)
107 if opt == '-b':
108 if arg == 'black':
109 bgcolor = (0,0,0)
110 elif arg == 'white':
111 bgcolor = (255,255,255)
112 else:
113 try:
114 bgcolor = eval(arg)
115 xxr, xxg, xxb = bgcolor
116 except:
117 print '-b needs (r,g,b) tuple'
118 sys.exit(2)
119 except string.atoi_error:
120 sys.stdout = sys.stderr
121 print 'Option', opt, 'requires integer argument'
122 sys.exit(2)
124 # Check validity of certain options combinations
125 if nowait and looping:
126 print 'Warning: -n and -l are mutually exclusive; -n ignored'
127 nowait = 0
128 if xoff <> None and yoff == None:
129 print 'Warning: -x without -y ignored'
130 if xoff == None and yoff <> None:
131 print 'Warning: -y without -x ignored'
133 # Process all files
134 if not args: args = ['film.video']
135 sts = 0
136 for filename in args:
137 sts = (process(filename) or sts)
139 # Exit with proper exit status
140 sys.exit(sts)
143 # Process one movie file
145 def process(filename):
146 try:
147 vin = VFile.VinFile(filename)
148 except IOError, msg:
149 sys.stderr.write(filename + ': I/O error: ' + `msg` + '\n')
150 return 1
151 except VFile.Error, msg:
152 sys.stderr.write(msg + '\n')
153 return 1
154 except EOFError:
155 sys.stderr.write(filename + ': EOF in video header\n')
156 return 1
158 if not quiet:
159 vin.printinfo()
161 gl.foreground()
163 width, height = int(vin.width * magnify), int(vin.height * magnify)
164 xborder = yborder = 0
165 if xwsiz:
166 vin.xorigin = (xwsiz - width)/2
167 width = xwsiz
168 if ywsiz:
169 vin.yorigin = (ywsiz - height)/2
170 height = ywsiz
171 if xoff <> None and yoff <> None:
172 scrheight = gl.getgdesc(GL.GD_YPMAX)
173 gl.prefposition(xoff, xoff+width-1, \
174 scrheight-yoff-height, scrheight-yoff-1)
175 else:
176 gl.prefsize(width, height)
178 win = gl.winopen(filename)
179 gl.clear()
181 if quiet: vin.quiet = 1
182 vin.initcolormap()
184 if bgcolor:
185 r, g, b = bgcolor
186 vin.clearto(r,g,b)
188 gl.qdevice(ESCKEY)
189 gl.qdevice(WINSHUT)
190 gl.qdevice(WINQUIT)
191 gl.qdevice(LEFTMOUSE)
193 stop = 0
195 while not stop:
196 gl.wintitle(filename)
197 stop = (playonce(vin) or nowait)
198 gl.wintitle('(done) ' + filename)
199 if not looping:
200 while not stop:
201 dev, val = gl.qread()
202 if dev == REDRAW:
203 if bgcolor:
204 r,g,b = bgcolor
205 vin.clearto(r,g,b)
206 else:
207 vin.clear()
208 if dev == LEFTMOUSE and val == 1:
209 break # Continue outer loop
210 if dev == ESCKEY and val == 1 or \
211 dev in (WINSHUT, WINQUIT):
212 stop = 1
214 # Set xoff, yoff for the next window from the current window
215 global xoff, yoff
216 xoff, yoff = gl.getorigin()
217 width, height = gl.getsize()
218 scrheight = gl.getgdesc(GL.GD_YPMAX)
219 yoff = scrheight - yoff - height
220 gl.winclose(win)
222 return 0
225 # Play a movie once; return 1 if user wants to stop, 0 if not
227 def playonce(vin):
228 vin.rewind()
229 vin.colormapinited = 1
230 vin.magnify = magnify
232 if threading:
233 MAXSIZE = 20 # Don't read ahead too much
234 import thread
235 import Queue
236 queue = Queue.Queue(MAXSIZE)
237 stop = []
238 thread.start_new_thread(read_ahead, (vin, queue, stop))
239 # Get the read-ahead thread going
240 while queue.qsize() < MAXSIZE/2 and not stop:
241 time.sleep(0.100)
243 tin = 0
244 toffset = 0
245 oldtin = 0
246 told = 0
247 nin = 0
248 nout = 0
249 nlate = 0
250 nskipped = 0
251 data = None
253 tlast = t0 = time.time()
255 while 1:
256 if gl.qtest():
257 dev, val = gl.qread()
258 if dev == ESCKEY and val == 1 or \
259 dev in (WINSHUT, WINQUIT) or \
260 dev == LEFTMOUSE and val == 1:
261 if debug: sys.stderr.write('\n')
262 if threading:
263 stop.append(None)
264 while 1:
265 item = queue.get()
266 if item == None: break
267 return (dev != LEFTMOUSE)
268 if dev == REDRAW:
269 gl.reshapeviewport()
270 if data: vin.showframe(data, cdata)
271 if threading:
272 if debug and queue.empty(): sys.stderr.write('.')
273 item = queue.get()
274 if item == None: break
275 tin, data, cdata = item
276 else:
277 try:
278 tin, size, csize = vin.getnextframeheader()
279 except EOFError:
280 break
281 tin = tin*0.001
282 nin = nin+1
283 if tin+toffset < oldtin:
284 print 'Fix reversed time:', oldtin, 'to', tin
285 toffset = oldtin - tin
286 tin = tin + toffset
287 oldtin = tin
288 if regen: tout = nin * regen
289 else: tout = tin
290 tout = tout / speed
291 if tout - told < mindelta:
292 nskipped = nskipped + 1
293 if not threading:
294 vin.skipnextframedata(size, csize)
295 else:
296 if not threading:
297 try:
298 data, cdata = \
299 vin.getnextframedata(size, csize)
300 except EOFError:
301 if not quiet:
302 print '[incomplete last frame]'
303 break
304 now = time.time()
305 dt = (tout-told) - (now-tlast)
306 told = tout
307 if debug: sys.stderr.write(`round(dt, 3)` + ' ')
308 if dt < 0: nlate = nlate + 1
309 if dt > 0:
310 time.sleep(dt)
311 now = time.time()
312 tlast = now
313 vin.showframe(data, cdata)
314 nout = nout + 1
316 t1 = time.time()
318 if debug: sys.stderr.write('\n')
320 if quiet: return 0
322 print 'Recorded:', nin, 'frames in', round(tin, 3), 'sec.',
323 if tin: print '-- average', round(nin/tin, 1), 'frames/sec',
324 print
326 if nskipped: print 'Skipped', nskipped, 'frames'
328 tout = t1-t0
329 print 'Played:', nout,
330 print 'frames in', round(tout, 3), 'sec.',
331 if tout: print '-- average', round(nout/tout, 1), 'frames/sec',
332 print
334 if nlate: print 'There were', nlate, 'late frames'
336 return 0
339 # Read-ahead thread
341 def read_ahead(vin, queue, stop):
342 try:
343 while not stop: queue.put(vin.getnextframe())
344 except EOFError:
345 pass
346 queue.put(None)
347 stop.append(None)
350 # Don't forget to call the main program
352 try:
353 main()
354 except KeyboardInterrupt:
355 print '[Interrupt]'