blob: 4a51c6e394a19fb847590f052d8fe97b9ff12a80 [file] [log] [blame]
Guido van Rossume755aa51992-08-21 12:34:55 +00001#! /ufs/guido/bin/sgi/python
Guido van Rossum82534fd1992-08-18 17:01:02 +00002
3# Play CMIF movie files
4
5
Guido van Rossume755aa51992-08-21 12:34:55 +00006# Help function
7
8def 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 msec (default 0)'
Guido van Rossume1783321992-09-07 09:35:23 +000016 print '-n : don\'t wait after each file'
Guido van Rossume755aa51992-08-21 12:34:55 +000017 print '-q : quiet, no informative messages'
18 print '-r delta : regenerate input time base delta msec 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 'file ... : file(s) to play; default film.video'
24 print
25 print 'User interface:'
26 print 'Press the left mouse button to stop or restart the movie.'
27 print 'Press ESC or use the window manager Close or Quit command'
28 print 'to close the window and play the next file (if any).'
Guido van Rossum82534fd1992-08-18 17:01:02 +000029
30
Guido van Rossume755aa51992-08-21 12:34:55 +000031# Imported modules
Guido van Rossum82534fd1992-08-18 17:01:02 +000032
Guido van Rossum843d1531992-08-18 14:16:12 +000033import sys
Guido van Rossume755aa51992-08-21 12:34:55 +000034sys.path.append('/ufs/guido/src/video') # Increase chance of finding VFile
Guido van Rossum843d1531992-08-18 14:16:12 +000035import VFile
36import time
37import gl, GL
Guido van Rossume755aa51992-08-21 12:34:55 +000038from DEVICE import REDRAW, ESCKEY, LEFTMOUSE, WINSHUT, WINQUIT
Guido van Rossum82534fd1992-08-18 17:01:02 +000039import getopt
40import string
41
42
43# Global options
44
Guido van Rossume755aa51992-08-21 12:34:55 +000045debug = 0
Guido van Rossum82534fd1992-08-18 17:01:02 +000046looping = 0
Guido van Rossume755aa51992-08-21 12:34:55 +000047magnify = 1
Guido van Rossum78aab861992-08-20 11:52:42 +000048mindelta = 0
Guido van Rossume755aa51992-08-21 12:34:55 +000049nowait = 0
Guido van Rossum78aab861992-08-20 11:52:42 +000050quiet = 0
51regen = None
Guido van Rossume755aa51992-08-21 12:34:55 +000052speed = 1.0
53threading = 0
54xoff = yoff = None
Guido van Rossum82534fd1992-08-18 17:01:02 +000055
56
57# Main program -- mostly command line parsing
Guido van Rossum843d1531992-08-18 14:16:12 +000058
59def main():
Guido van Rossume755aa51992-08-21 12:34:55 +000060 global debug, looping, magnify, mindelta, nowait, quiet, regen, speed
61 global threading, xoff, yoff
62
63 # Parse command line
64 try:
65 opts, args = getopt.getopt(sys.argv[1:], 'M:dlm:nqr:s:tx:y:')
66 except getopt.error, msg:
67 sys.stdout = sys.stderr
68 print 'Error:', msg, '\n'
69 help()
70 sys.exit(2)
71
72 # Interpret options
73 try:
74 for opt, arg in opts:
Guido van Rossume0be2b31992-09-01 14:45:57 +000075 if opt == '-M': magnify = float(eval(arg))
Guido van Rossume755aa51992-08-21 12:34:55 +000076 if opt == '-d': debug = debug + 1
77 if opt == '-l': looping = 1
78 if opt == '-m': mindelta = string.atoi(arg)
79 if opt == '-n': nowait = 1
80 if opt == '-q': quiet = 1
81 if opt == '-r': regen = string.atoi(arg)
82 if opt == '-s':
83 try:
84 speed = float(eval(arg))
85 except:
86 sys.stdout = sys.stderr
87 print 'Option -s needs float argument'
88 sys.exit(2)
89 if opt == '-t':
90 try:
91 import thread
92 threading = 1
93 except ImportError:
94 print 'Sorry, this version of Python',
95 print 'does not support threads:',
96 print '-t ignored'
97 if opt == '-x': xoff = string.atoi(arg)
98 if opt == '-y': yoff = string.atoi(arg)
99 except string.atoi_error:
100 sys.stdout = sys.stderr
101 print 'Option', opt, 'require integer argument'
102 sys.exit(2)
103
104 # Check validity of certain options combinations
105 if nowait and looping:
106 print 'Warning: -n and -l are mutually exclusive; -n ignored'
107 nowait = 0
108 if xoff <> None and yoff == None:
109 print 'Warning: -x without -y ignored'
110 if xoff == None and yoff <> None:
111 print 'Warning: -y without -x ignored'
112
113 # Process all files
114 if not args: args = ['film.video']
115 sts = 0
Guido van Rossum82534fd1992-08-18 17:01:02 +0000116 for filename in args:
Guido van Rossume755aa51992-08-21 12:34:55 +0000117 sts = (process(filename) or sts)
118
119 # Exit with proper exit status
120 sys.exit(sts)
Guido van Rossum82534fd1992-08-18 17:01:02 +0000121
122
Guido van Rossum78aab861992-08-20 11:52:42 +0000123# Process one movie file
Guido van Rossum843d1531992-08-18 14:16:12 +0000124
125def process(filename):
Guido van Rossum78aab861992-08-20 11:52:42 +0000126 try:
127 vin = VFile.VinFile().init(filename)
128 except IOError, msg:
129 sys.stderr.write(filename + ': I/O error: ' + `msg` + '\n')
Guido van Rossume755aa51992-08-21 12:34:55 +0000130 return 1
Guido van Rossum78aab861992-08-20 11:52:42 +0000131 except VFile.Error, msg:
132 sys.stderr.write(msg + '\n')
Guido van Rossume755aa51992-08-21 12:34:55 +0000133 return 1
Guido van Rossum78aab861992-08-20 11:52:42 +0000134 except EOFError:
135 sys.stderr.write(filename + ': EOF in video header\n')
Guido van Rossume755aa51992-08-21 12:34:55 +0000136 return 1
Guido van Rossum78aab861992-08-20 11:52:42 +0000137
138 if not quiet:
Guido van Rossume1783321992-09-07 09:35:23 +0000139 vin.printinfo()
Guido van Rossum843d1531992-08-18 14:16:12 +0000140
141 gl.foreground()
Guido van Rossume755aa51992-08-21 12:34:55 +0000142
Guido van Rossume0be2b31992-09-01 14:45:57 +0000143 width, height = int(vin.width * magnify), int(vin.height * magnify)
Guido van Rossume755aa51992-08-21 12:34:55 +0000144 if xoff <> None and yoff <> None:
145 scrheight = gl.getgdesc(GL.GD_YPMAX)
146 gl.prefposition(xoff, xoff+width-1, \
147 scrheight-yoff-height, scrheight-yoff-1)
148 else:
149 gl.prefsize(width, height)
150
Guido van Rossum78aab861992-08-20 11:52:42 +0000151 win = gl.winopen(filename)
Guido van Rossume755aa51992-08-21 12:34:55 +0000152 gl.clear()
153
154 if quiet: vin.quiet = 1
Guido van Rossum843d1531992-08-18 14:16:12 +0000155 vin.initcolormap()
156
157 gl.qdevice(ESCKEY)
158 gl.qdevice(WINSHUT)
159 gl.qdevice(WINQUIT)
Guido van Rossume755aa51992-08-21 12:34:55 +0000160 gl.qdevice(LEFTMOUSE)
Guido van Rossum843d1531992-08-18 14:16:12 +0000161
Guido van Rossume755aa51992-08-21 12:34:55 +0000162 stop = 0
Guido van Rossum78aab861992-08-20 11:52:42 +0000163
164 while not stop:
Guido van Rossume755aa51992-08-21 12:34:55 +0000165 gl.wintitle(filename)
166 stop = (playonce(vin) or nowait)
167 gl.wintitle('(done) ' + filename)
168 if not looping:
169 while not stop:
170 dev, val = gl.qread()
Guido van Rossum2de9b681992-09-07 15:11:30 +0000171 if dev == REDRAW:
172 vin.clear()
Guido van Rossume755aa51992-08-21 12:34:55 +0000173 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]'