blob: 4fe13c5995ae232d41fc5486a58b7ff3b90a84fb [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()
Guido van Rossum2de9b681992-09-07 15:11:30 +0000173 if dev == REDRAW:
174 vin.clear()
Guido van Rossume755aa51992-08-21 12:34:55 +0000175 if dev == LEFTMOUSE and val == 1:
176 break # Continue outer loop
177 if dev == ESCKEY and val == 1 or \
178 dev in (WINSHUT, WINQUIT):
179 stop = 1
Guido van Rossum78aab861992-08-20 11:52:42 +0000180
Guido van Rossume755aa51992-08-21 12:34:55 +0000181 # Set xoff, yoff for the next window from the current window
182 global xoff, yoff
183 xoff, yoff = gl.getorigin()
184 width, height = gl.getsize()
185 scrheight = gl.getgdesc(GL.GD_YPMAX)
186 yoff = scrheight - yoff - height
Guido van Rossum78aab861992-08-20 11:52:42 +0000187 gl.winclose(win)
188
Guido van Rossume755aa51992-08-21 12:34:55 +0000189 return 0
190
Guido van Rossum78aab861992-08-20 11:52:42 +0000191
192# Play a movie once; return 1 if user wants to stop, 0 if not
193
194def playonce(vin):
Guido van Rossume755aa51992-08-21 12:34:55 +0000195 vin.rewind()
Guido van Rossum78aab861992-08-20 11:52:42 +0000196 vin.colormapinited = 1
197 vin.magnify = magnify
198
Guido van Rossume755aa51992-08-21 12:34:55 +0000199 if threading:
Guido van Rossum9ee7e151992-08-25 12:29:30 +0000200 MAXSIZE = 20 # Don't read ahead too much
Guido van Rossume755aa51992-08-21 12:34:55 +0000201 import thread
Guido van Rossum9ee7e151992-08-25 12:29:30 +0000202 import Queue
203 queue = Queue.Queue().init(MAXSIZE)
Guido van Rossume755aa51992-08-21 12:34:55 +0000204 stop = []
205 thread.start_new_thread(read_ahead, (vin, queue, stop))
206 # Get the read-ahead thread going
Guido van Rossum9ee7e151992-08-25 12:29:30 +0000207 while queue.qsize() < MAXSIZE/2 and not stop:
208 time.millisleep(100)
Guido van Rossume755aa51992-08-21 12:34:55 +0000209
Guido van Rossum78aab861992-08-20 11:52:42 +0000210 tin = 0
Guido van Rossume1783321992-09-07 09:35:23 +0000211 toffset = 0
212 oldtin = 0
Guido van Rossum78aab861992-08-20 11:52:42 +0000213 told = 0
214 nin = 0
215 nout = 0
Guido van Rossume755aa51992-08-21 12:34:55 +0000216 nlate = 0
Guido van Rossum78aab861992-08-20 11:52:42 +0000217 nskipped = 0
Guido van Rossume755aa51992-08-21 12:34:55 +0000218 data = None
Guido van Rossum78aab861992-08-20 11:52:42 +0000219
Guido van Rossume755aa51992-08-21 12:34:55 +0000220 tlast = t0 = time.millitimer()
Guido van Rossum78aab861992-08-20 11:52:42 +0000221
222 while 1:
Guido van Rossum78aab861992-08-20 11:52:42 +0000223 if gl.qtest():
Guido van Rossum843d1531992-08-18 14:16:12 +0000224 dev, val = gl.qread()
Guido van Rossume755aa51992-08-21 12:34:55 +0000225 if dev == ESCKEY and val == 1 or \
226 dev in (WINSHUT, WINQUIT) or \
227 dev == LEFTMOUSE and val == 1:
228 if debug: sys.stderr.write('\n')
229 if threading:
230 stop.append(None)
Guido van Rossum9ee7e151992-08-25 12:29:30 +0000231 while 1:
232 item = queue.get()
233 if item == None: break
Guido van Rossume755aa51992-08-21 12:34:55 +0000234 return (dev != LEFTMOUSE)
Guido van Rossum843d1531992-08-18 14:16:12 +0000235 if dev == REDRAW:
236 gl.reshapeviewport()
Guido van Rossume755aa51992-08-21 12:34:55 +0000237 if data: vin.showframe(data, cdata)
238 if threading:
Guido van Rossum9ee7e151992-08-25 12:29:30 +0000239 if debug and queue.empty(): sys.stderr.write('.')
240 item = queue.get()
241 if item == None: break
242 tin, data, cdata = item
Guido van Rossume755aa51992-08-21 12:34:55 +0000243 else:
244 try:
245 tin, size, csize = vin.getnextframeheader()
246 except EOFError:
247 break
248 nin = nin+1
Guido van Rossume1783321992-09-07 09:35:23 +0000249 if tin+toffset < oldtin:
250 print 'Fix reversed time:', oldtin, 'to', tin
251 toffset = oldtin - tin
252 tin = tin + toffset
253 oldtin = tin
Guido van Rossume755aa51992-08-21 12:34:55 +0000254 if regen: tout = nin * regen
255 else: tout = tin
256 tout = int(tout / speed)
257 if tout - told < mindelta:
258 nskipped = nskipped + 1
Guido van Rossume1783321992-09-07 09:35:23 +0000259 if not threading:
260 vin.skipnextframedata(size, csize)
Guido van Rossume755aa51992-08-21 12:34:55 +0000261 else:
262 if not threading:
263 try:
264 data, cdata = \
265 vin.getnextframedata(size, csize)
266 except EOFError:
267 if not quiet:
268 print '[incomplete last frame]'
269 break
270 now = time.millitimer()
271 dt = (tout-told) - (now-tlast)
272 told = tout
273 if debug: sys.stderr.write(`dt/10` + ' ')
274 if dt < 0: nlate = nlate + 1
275 if dt > 0:
276 time.millisleep(dt)
277 now = now + dt
278 tlast = now
279 vin.showframe(data, cdata)
280 nout = nout + 1
Guido van Rossum78aab861992-08-20 11:52:42 +0000281
282 t1 = time.millitimer()
283
Guido van Rossume755aa51992-08-21 12:34:55 +0000284 if debug: sys.stderr.write('\n')
285
286 if quiet: return 0
Guido van Rossum78aab861992-08-20 11:52:42 +0000287
288 print 'Recorded:', nin, 'frames in', tin*0.001, 'sec.',
289 if tin: print '-- average', int(nin*10000.0/tin)*0.1, 'frames/sec',
290 print
291
Guido van Rossume755aa51992-08-21 12:34:55 +0000292 if nskipped: print 'Skipped', nskipped, 'frames'
Guido van Rossum78aab861992-08-20 11:52:42 +0000293
294 tout = t1-t0
295 print 'Played:', nout,
296 print 'frames in', tout*0.001, 'sec.',
297 if tout: print '-- average', int(nout*10000.0/tout)*0.1, 'frames/sec',
298 print
299
Guido van Rossume755aa51992-08-21 12:34:55 +0000300 if nlate: print 'There were', nlate, 'late frames'
Guido van Rossum78aab861992-08-20 11:52:42 +0000301
302 return 0
Guido van Rossum843d1531992-08-18 14:16:12 +0000303
Guido van Rossum82534fd1992-08-18 17:01:02 +0000304
Guido van Rossume755aa51992-08-21 12:34:55 +0000305# Read-ahead thread
306
307def read_ahead(vin, queue, stop):
308 try:
Guido van Rossum9ee7e151992-08-25 12:29:30 +0000309 while not stop: queue.put(vin.getnextframe())
Guido van Rossume755aa51992-08-21 12:34:55 +0000310 except EOFError:
Guido van Rossum9ee7e151992-08-25 12:29:30 +0000311 pass
312 queue.put(None)
Guido van Rossume755aa51992-08-21 12:34:55 +0000313 stop.append(None)
314
315
Guido van Rossum82534fd1992-08-18 17:01:02 +0000316# Don't forget to call the main program
317
Guido van Rossume755aa51992-08-21 12:34:55 +0000318try:
319 main()
320except KeyboardInterrupt:
321 print '[Interrupt]'