blob: b8d06a1ff399a0212306826894c10f17dfc26741 [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:
Guido van Rossum9ee7e151992-08-25 12:29:30 +0000203 MAXSIZE = 20 # Don't read ahead too much
Guido van Rossume755aa51992-08-21 12:34:55 +0000204 import thread
Guido van Rossum9ee7e151992-08-25 12:29:30 +0000205 import Queue
206 queue = Queue.Queue().init(MAXSIZE)
Guido van Rossume755aa51992-08-21 12:34:55 +0000207 stop = []
208 thread.start_new_thread(read_ahead, (vin, queue, stop))
209 # Get the read-ahead thread going
Guido van Rossum9ee7e151992-08-25 12:29:30 +0000210 while queue.qsize() < MAXSIZE/2 and not stop:
211 time.millisleep(100)
Guido van Rossume755aa51992-08-21 12:34:55 +0000212
Guido van Rossum78aab861992-08-20 11:52:42 +0000213 tin = 0
214 told = 0
215 nin = 0
216 nout = 0
Guido van Rossume755aa51992-08-21 12:34:55 +0000217 nlate = 0
Guido van Rossum78aab861992-08-20 11:52:42 +0000218 nskipped = 0
Guido van Rossume755aa51992-08-21 12:34:55 +0000219 data = None
Guido van Rossum78aab861992-08-20 11:52:42 +0000220
Guido van Rossume755aa51992-08-21 12:34:55 +0000221 tlast = t0 = time.millitimer()
Guido van Rossum78aab861992-08-20 11:52:42 +0000222
223 while 1:
Guido van Rossum78aab861992-08-20 11:52:42 +0000224 if gl.qtest():
Guido van Rossum843d1531992-08-18 14:16:12 +0000225 dev, val = gl.qread()
Guido van Rossume755aa51992-08-21 12:34:55 +0000226 if dev == ESCKEY and val == 1 or \
227 dev in (WINSHUT, WINQUIT) or \
228 dev == LEFTMOUSE and val == 1:
229 if debug: sys.stderr.write('\n')
230 if threading:
231 stop.append(None)
Guido van Rossum9ee7e151992-08-25 12:29:30 +0000232 while 1:
233 item = queue.get()
234 if item == None: break
Guido van Rossume755aa51992-08-21 12:34:55 +0000235 return (dev != LEFTMOUSE)
Guido van Rossum843d1531992-08-18 14:16:12 +0000236 if dev == REDRAW:
237 gl.reshapeviewport()
Guido van Rossume755aa51992-08-21 12:34:55 +0000238 if data: vin.showframe(data, cdata)
239 if threading:
Guido van Rossum9ee7e151992-08-25 12:29:30 +0000240 if debug and queue.empty(): sys.stderr.write('.')
241 item = queue.get()
242 if item == None: break
243 tin, data, cdata = item
Guido van Rossume755aa51992-08-21 12:34:55 +0000244 else:
245 try:
246 tin, size, csize = vin.getnextframeheader()
247 except EOFError:
248 break
249 nin = nin+1
250 if regen: tout = nin * regen
251 else: tout = tin
252 tout = int(tout / speed)
253 if tout - told < mindelta:
254 nskipped = nskipped + 1
255 else:
256 if not threading:
257 try:
258 data, cdata = \
259 vin.getnextframedata(size, csize)
260 except EOFError:
261 if not quiet:
262 print '[incomplete last frame]'
263 break
264 now = time.millitimer()
265 dt = (tout-told) - (now-tlast)
266 told = tout
267 if debug: sys.stderr.write(`dt/10` + ' ')
268 if dt < 0: nlate = nlate + 1
269 if dt > 0:
270 time.millisleep(dt)
271 now = now + dt
272 tlast = now
273 vin.showframe(data, cdata)
274 nout = nout + 1
Guido van Rossum78aab861992-08-20 11:52:42 +0000275
276 t1 = time.millitimer()
277
Guido van Rossume755aa51992-08-21 12:34:55 +0000278 if debug: sys.stderr.write('\n')
279
280 if quiet: return 0
Guido van Rossum78aab861992-08-20 11:52:42 +0000281
282 print 'Recorded:', nin, 'frames in', tin*0.001, 'sec.',
283 if tin: print '-- average', int(nin*10000.0/tin)*0.1, 'frames/sec',
284 print
285
Guido van Rossume755aa51992-08-21 12:34:55 +0000286 if nskipped: print 'Skipped', nskipped, 'frames'
Guido van Rossum78aab861992-08-20 11:52:42 +0000287
288 tout = t1-t0
289 print 'Played:', nout,
290 print 'frames in', tout*0.001, 'sec.',
291 if tout: print '-- average', int(nout*10000.0/tout)*0.1, 'frames/sec',
292 print
293
Guido van Rossume755aa51992-08-21 12:34:55 +0000294 if nlate: print 'There were', nlate, 'late frames'
Guido van Rossum78aab861992-08-20 11:52:42 +0000295
296 return 0
Guido van Rossum843d1531992-08-18 14:16:12 +0000297
Guido van Rossum82534fd1992-08-18 17:01:02 +0000298
Guido van Rossume755aa51992-08-21 12:34:55 +0000299# Read-ahead thread
300
301def read_ahead(vin, queue, stop):
302 try:
Guido van Rossum9ee7e151992-08-25 12:29:30 +0000303 while not stop: queue.put(vin.getnextframe())
Guido van Rossume755aa51992-08-21 12:34:55 +0000304 except EOFError:
Guido van Rossum9ee7e151992-08-25 12:29:30 +0000305 pass
306 queue.put(None)
Guido van Rossume755aa51992-08-21 12:34:55 +0000307 stop.append(None)
308
309
Guido van Rossum82534fd1992-08-18 17:01:02 +0000310# Don't forget to call the main program
311
Guido van Rossume755aa51992-08-21 12:34:55 +0000312try:
313 main()
314except KeyboardInterrupt:
315 print '[Interrupt]'