blob: 5ab623d5966529396f913bf2611747f0962a09f7 [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)'
18 print '-q : quiet, no informative messages'
19 print '-r delta : regenerate input time base delta msec apart'
20 print '-s speed : speed change factor (default 1.0)'
21 print '-t : use a 2nd thread for read-ahead'
22 print '-x left : window offset from left of screen'
23 print '-y top : window offset from top of screen'
24 print 'file ... : file(s) to play; default film.video'
25 print
26 print 'User interface:'
27 print 'Press the left mouse button to stop or restart the movie.'
28 print 'Press ESC or use the window manager Close or Quit command'
29 print 'to close the window and play the next file (if any).'
Guido van Rossum82534fd1992-08-18 17:01:02 +000030
31
Guido van Rossume755aa51992-08-21 12:34:55 +000032# Imported modules
Guido van Rossum82534fd1992-08-18 17:01:02 +000033
Guido van Rossum843d1531992-08-18 14:16:12 +000034import sys
Guido van Rossume755aa51992-08-21 12:34:55 +000035sys.path.append('/ufs/guido/src/video') # Increase chance of finding VFile
Guido van Rossum843d1531992-08-18 14:16:12 +000036import VFile
37import time
38import gl, GL
Guido van Rossume755aa51992-08-21 12:34:55 +000039from DEVICE import REDRAW, ESCKEY, LEFTMOUSE, WINSHUT, WINQUIT
Guido van Rossum82534fd1992-08-18 17:01:02 +000040import getopt
41import string
42
43
44# Global options
45
Guido van Rossume755aa51992-08-21 12:34:55 +000046debug = 0
Guido van Rossum82534fd1992-08-18 17:01:02 +000047looping = 0
Guido van Rossume755aa51992-08-21 12:34:55 +000048magnify = 1
Guido van Rossum78aab861992-08-20 11:52:42 +000049mindelta = 0
Guido van Rossume755aa51992-08-21 12:34:55 +000050nowait = 0
Guido van Rossum78aab861992-08-20 11:52:42 +000051quiet = 0
52regen = None
Guido van Rossume755aa51992-08-21 12:34:55 +000053speed = 1.0
54threading = 0
55xoff = yoff = None
Guido van Rossum82534fd1992-08-18 17:01:02 +000056
57
58# Main program -- mostly command line parsing
Guido van Rossum843d1531992-08-18 14:16:12 +000059
60def main():
Guido van Rossume755aa51992-08-21 12:34:55 +000061 global debug, looping, magnify, mindelta, nowait, quiet, regen, speed
62 global threading, xoff, yoff
63
64 # Parse command line
65 try:
66 opts, args = getopt.getopt(sys.argv[1:], 'M:dlm:nqr:s:tx:y:')
67 except getopt.error, msg:
68 sys.stdout = sys.stderr
69 print 'Error:', msg, '\n'
70 help()
71 sys.exit(2)
72
73 # Interpret options
74 try:
75 for opt, arg in opts:
76 if opt == '-M': magnify = string.atoi(arg)
77 if opt == '-d': debug = debug + 1
78 if opt == '-l': looping = 1
79 if opt == '-m': mindelta = string.atoi(arg)
80 if opt == '-n': nowait = 1
81 if opt == '-q': quiet = 1
82 if opt == '-r': regen = string.atoi(arg)
83 if opt == '-s':
84 try:
85 speed = float(eval(arg))
86 except:
87 sys.stdout = sys.stderr
88 print 'Option -s needs float argument'
89 sys.exit(2)
90 if opt == '-t':
91 try:
92 import thread
93 threading = 1
94 except ImportError:
95 print 'Sorry, this version of Python',
96 print 'does not support threads:',
97 print '-t ignored'
98 if opt == '-x': xoff = string.atoi(arg)
99 if opt == '-y': yoff = string.atoi(arg)
100 except string.atoi_error:
101 sys.stdout = sys.stderr
102 print 'Option', opt, 'require integer argument'
103 sys.exit(2)
104
105 # Check validity of certain options combinations
106 if nowait and looping:
107 print 'Warning: -n and -l are mutually exclusive; -n ignored'
108 nowait = 0
109 if xoff <> None and yoff == None:
110 print 'Warning: -x without -y ignored'
111 if xoff == None and yoff <> None:
112 print 'Warning: -y without -x ignored'
113
114 # Process all files
115 if not args: args = ['film.video']
116 sts = 0
Guido van Rossum82534fd1992-08-18 17:01:02 +0000117 for filename in args:
Guido van Rossume755aa51992-08-21 12:34:55 +0000118 sts = (process(filename) or sts)
119
120 # Exit with proper exit status
121 sys.exit(sts)
Guido van Rossum82534fd1992-08-18 17:01:02 +0000122
123
Guido van Rossum78aab861992-08-20 11:52:42 +0000124# Process one movie file
Guido van Rossum843d1531992-08-18 14:16:12 +0000125
126def process(filename):
Guido van Rossum78aab861992-08-20 11:52:42 +0000127 try:
128 vin = VFile.VinFile().init(filename)
129 except IOError, msg:
130 sys.stderr.write(filename + ': I/O error: ' + `msg` + '\n')
Guido van Rossume755aa51992-08-21 12:34:55 +0000131 return 1
Guido van Rossum78aab861992-08-20 11:52:42 +0000132 except VFile.Error, msg:
133 sys.stderr.write(msg + '\n')
Guido van Rossume755aa51992-08-21 12:34:55 +0000134 return 1
Guido van Rossum78aab861992-08-20 11:52:42 +0000135 except EOFError:
136 sys.stderr.write(filename + ': EOF in video header\n')
Guido van Rossume755aa51992-08-21 12:34:55 +0000137 return 1
Guido van Rossum78aab861992-08-20 11:52:42 +0000138
139 if not quiet:
140 print 'File: ', filename
141 print 'Version: ', vin.version
142 print 'Size: ', vin.width, 'x', vin.height
143 print 'Pack: ', vin.packfactor, '; chrom:', vin.chrompack
144 print 'Bits: ', vin.c0bits, vin.c1bits, vin.c2bits
145 print 'Format: ', vin.format
146 print 'Offset: ', vin.offset
Guido van Rossum843d1531992-08-18 14:16:12 +0000147
148 gl.foreground()
Guido van Rossume755aa51992-08-21 12:34:55 +0000149
150 width, height = vin.width * magnify, vin.height * magnify
151 if xoff <> None and yoff <> None:
152 scrheight = gl.getgdesc(GL.GD_YPMAX)
153 gl.prefposition(xoff, xoff+width-1, \
154 scrheight-yoff-height, scrheight-yoff-1)
155 else:
156 gl.prefsize(width, height)
157
Guido van Rossum78aab861992-08-20 11:52:42 +0000158 win = gl.winopen(filename)
Guido van Rossume755aa51992-08-21 12:34:55 +0000159 gl.clear()
160
161 if quiet: vin.quiet = 1
Guido van Rossum843d1531992-08-18 14:16:12 +0000162 vin.initcolormap()
163
164 gl.qdevice(ESCKEY)
165 gl.qdevice(WINSHUT)
166 gl.qdevice(WINQUIT)
Guido van Rossume755aa51992-08-21 12:34:55 +0000167 gl.qdevice(LEFTMOUSE)
Guido van Rossum843d1531992-08-18 14:16:12 +0000168
Guido van Rossume755aa51992-08-21 12:34:55 +0000169 stop = 0
Guido van Rossum78aab861992-08-20 11:52:42 +0000170
171 while not stop:
Guido van Rossume755aa51992-08-21 12:34:55 +0000172 gl.wintitle(filename)
173 stop = (playonce(vin) or nowait)
174 gl.wintitle('(done) ' + filename)
175 if not looping:
176 while not stop:
177 dev, val = gl.qread()
178 if dev == LEFTMOUSE and val == 1:
179 break # Continue outer loop
180 if dev == ESCKEY and val == 1 or \
181 dev in (WINSHUT, WINQUIT):
182 stop = 1
Guido van Rossum78aab861992-08-20 11:52:42 +0000183
Guido van Rossume755aa51992-08-21 12:34:55 +0000184 # Set xoff, yoff for the next window from the current window
185 global xoff, yoff
186 xoff, yoff = gl.getorigin()
187 width, height = gl.getsize()
188 scrheight = gl.getgdesc(GL.GD_YPMAX)
189 yoff = scrheight - yoff - height
Guido van Rossum78aab861992-08-20 11:52:42 +0000190 gl.winclose(win)
191
Guido van Rossume755aa51992-08-21 12:34:55 +0000192 return 0
193
Guido van Rossum78aab861992-08-20 11:52:42 +0000194
195# Play a movie once; return 1 if user wants to stop, 0 if not
196
197def playonce(vin):
Guido van Rossume755aa51992-08-21 12:34:55 +0000198 vin.rewind()
Guido van Rossum78aab861992-08-20 11:52:42 +0000199 vin.colormapinited = 1
200 vin.magnify = magnify
201
Guido van Rossume755aa51992-08-21 12:34:55 +0000202 if threading:
203 import thread
204 queue = []
205 stop = []
206 thread.start_new_thread(read_ahead, (vin, queue, stop))
207 # Get the read-ahead thread going
208 while len(queue) < 5 and None not in queue:
209 time.millisleep(10)
210
Guido van Rossum78aab861992-08-20 11:52:42 +0000211 tin = 0
212 told = 0
213 nin = 0
214 nout = 0
Guido van Rossume755aa51992-08-21 12:34:55 +0000215 nlate = 0
Guido van Rossum78aab861992-08-20 11:52:42 +0000216 nskipped = 0
Guido van Rossume755aa51992-08-21 12:34:55 +0000217 data = None
Guido van Rossum78aab861992-08-20 11:52:42 +0000218
Guido van Rossume755aa51992-08-21 12:34:55 +0000219 tlast = t0 = time.millitimer()
Guido van Rossum78aab861992-08-20 11:52:42 +0000220
221 while 1:
Guido van Rossum78aab861992-08-20 11:52:42 +0000222 if gl.qtest():
Guido van Rossum843d1531992-08-18 14:16:12 +0000223 dev, val = gl.qread()
Guido van Rossume755aa51992-08-21 12:34:55 +0000224 if dev == ESCKEY and val == 1 or \
225 dev in (WINSHUT, WINQUIT) or \
226 dev == LEFTMOUSE and val == 1:
227 if debug: sys.stderr.write('\n')
228 if threading:
229 stop.append(None)
230 while len(stop) < 2:
231 time.millisleep(10)
232 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:
237 if not queue:
238 if debug: sys.stderr.write('.')
239 time.millisleep(10)
240 continue
241 q0 = queue[0]
242 if q0 == None: break
243 del queue[0]
244 tin, data, cdata = q0
245 else:
246 try:
247 tin, size, csize = vin.getnextframeheader()
248 except EOFError:
249 break
250 nin = nin+1
251 if regen: tout = nin * regen
252 else: tout = tin
253 tout = int(tout / speed)
254 if tout - told < mindelta:
255 nskipped = nskipped + 1
256 else:
257 if not threading:
258 try:
259 data, cdata = \
260 vin.getnextframedata(size, csize)
261 except EOFError:
262 if not quiet:
263 print '[incomplete last frame]'
264 break
265 now = time.millitimer()
266 dt = (tout-told) - (now-tlast)
267 told = tout
268 if debug: sys.stderr.write(`dt/10` + ' ')
269 if dt < 0: nlate = nlate + 1
270 if dt > 0:
271 time.millisleep(dt)
272 now = now + dt
273 tlast = now
274 vin.showframe(data, cdata)
275 nout = nout + 1
Guido van Rossum78aab861992-08-20 11:52:42 +0000276
277 t1 = time.millitimer()
278
Guido van Rossume755aa51992-08-21 12:34:55 +0000279 if debug: sys.stderr.write('\n')
280
281 if quiet: return 0
Guido van Rossum78aab861992-08-20 11:52:42 +0000282
283 print 'Recorded:', nin, 'frames in', tin*0.001, 'sec.',
284 if tin: print '-- average', int(nin*10000.0/tin)*0.1, 'frames/sec',
285 print
286
Guido van Rossume755aa51992-08-21 12:34:55 +0000287 if nskipped: print 'Skipped', nskipped, 'frames'
Guido van Rossum78aab861992-08-20 11:52:42 +0000288
289 tout = t1-t0
290 print 'Played:', nout,
291 print 'frames in', tout*0.001, 'sec.',
292 if tout: print '-- average', int(nout*10000.0/tout)*0.1, 'frames/sec',
293 print
294
Guido van Rossume755aa51992-08-21 12:34:55 +0000295 if nlate: print 'There were', nlate, 'late frames'
Guido van Rossum78aab861992-08-20 11:52:42 +0000296
297 return 0
Guido van Rossum843d1531992-08-18 14:16:12 +0000298
Guido van Rossum82534fd1992-08-18 17:01:02 +0000299
Guido van Rossume755aa51992-08-21 12:34:55 +0000300# Read-ahead thread
301
302def read_ahead(vin, queue, stop):
303 try:
304 while not stop: queue.append(vin.getnextframe())
305 except EOFError:
306 queue.append(None)
307 stop.append(None)
308
309
310
Guido van Rossum82534fd1992-08-18 17:01:02 +0000311# Don't forget to call the main program
312
Guido van Rossume755aa51992-08-21 12:34:55 +0000313try:
314 main()
315except KeyboardInterrupt:
316 print '[Interrupt]'