Guido van Rossum | e755aa5 | 1992-08-21 12:34:55 +0000 | [diff] [blame] | 1 | #! /ufs/guido/bin/sgi/python-405 |
| 2 | #! /ufs/guido/bin/sgi/python |
Guido van Rossum | 82534fd | 1992-08-18 17:01:02 +0000 | [diff] [blame] | 3 | #! /usr/local/python |
| 4 | |
| 5 | # Play CMIF movie files |
| 6 | |
| 7 | |
Guido van Rossum | e755aa5 | 1992-08-21 12:34:55 +0000 | [diff] [blame] | 8 | # Help function |
| 9 | |
| 10 | def 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 Rossum | 82534fd | 1992-08-18 17:01:02 +0000 | [diff] [blame] | 30 | |
| 31 | |
Guido van Rossum | e755aa5 | 1992-08-21 12:34:55 +0000 | [diff] [blame] | 32 | # Imported modules |
Guido van Rossum | 82534fd | 1992-08-18 17:01:02 +0000 | [diff] [blame] | 33 | |
Guido van Rossum | 843d153 | 1992-08-18 14:16:12 +0000 | [diff] [blame] | 34 | import sys |
Guido van Rossum | e755aa5 | 1992-08-21 12:34:55 +0000 | [diff] [blame] | 35 | sys.path.append('/ufs/guido/src/video') # Increase chance of finding VFile |
Guido van Rossum | 843d153 | 1992-08-18 14:16:12 +0000 | [diff] [blame] | 36 | import VFile |
| 37 | import time |
| 38 | import gl, GL |
Guido van Rossum | e755aa5 | 1992-08-21 12:34:55 +0000 | [diff] [blame] | 39 | from DEVICE import REDRAW, ESCKEY, LEFTMOUSE, WINSHUT, WINQUIT |
Guido van Rossum | 82534fd | 1992-08-18 17:01:02 +0000 | [diff] [blame] | 40 | import getopt |
| 41 | import string |
| 42 | |
| 43 | |
| 44 | # Global options |
| 45 | |
Guido van Rossum | e755aa5 | 1992-08-21 12:34:55 +0000 | [diff] [blame] | 46 | debug = 0 |
Guido van Rossum | 82534fd | 1992-08-18 17:01:02 +0000 | [diff] [blame] | 47 | looping = 0 |
Guido van Rossum | e755aa5 | 1992-08-21 12:34:55 +0000 | [diff] [blame] | 48 | magnify = 1 |
Guido van Rossum | 78aab86 | 1992-08-20 11:52:42 +0000 | [diff] [blame] | 49 | mindelta = 0 |
Guido van Rossum | e755aa5 | 1992-08-21 12:34:55 +0000 | [diff] [blame] | 50 | nowait = 0 |
Guido van Rossum | 78aab86 | 1992-08-20 11:52:42 +0000 | [diff] [blame] | 51 | quiet = 0 |
| 52 | regen = None |
Guido van Rossum | e755aa5 | 1992-08-21 12:34:55 +0000 | [diff] [blame] | 53 | speed = 1.0 |
| 54 | threading = 0 |
| 55 | xoff = yoff = None |
Guido van Rossum | 82534fd | 1992-08-18 17:01:02 +0000 | [diff] [blame] | 56 | |
| 57 | |
| 58 | # Main program -- mostly command line parsing |
Guido van Rossum | 843d153 | 1992-08-18 14:16:12 +0000 | [diff] [blame] | 59 | |
| 60 | def main(): |
Guido van Rossum | e755aa5 | 1992-08-21 12:34:55 +0000 | [diff] [blame] | 61 | 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 Rossum | 82534fd | 1992-08-18 17:01:02 +0000 | [diff] [blame] | 117 | for filename in args: |
Guido van Rossum | e755aa5 | 1992-08-21 12:34:55 +0000 | [diff] [blame] | 118 | sts = (process(filename) or sts) |
| 119 | |
| 120 | # Exit with proper exit status |
| 121 | sys.exit(sts) |
Guido van Rossum | 82534fd | 1992-08-18 17:01:02 +0000 | [diff] [blame] | 122 | |
| 123 | |
Guido van Rossum | 78aab86 | 1992-08-20 11:52:42 +0000 | [diff] [blame] | 124 | # Process one movie file |
Guido van Rossum | 843d153 | 1992-08-18 14:16:12 +0000 | [diff] [blame] | 125 | |
| 126 | def process(filename): |
Guido van Rossum | 78aab86 | 1992-08-20 11:52:42 +0000 | [diff] [blame] | 127 | try: |
| 128 | vin = VFile.VinFile().init(filename) |
| 129 | except IOError, msg: |
| 130 | sys.stderr.write(filename + ': I/O error: ' + `msg` + '\n') |
Guido van Rossum | e755aa5 | 1992-08-21 12:34:55 +0000 | [diff] [blame] | 131 | return 1 |
Guido van Rossum | 78aab86 | 1992-08-20 11:52:42 +0000 | [diff] [blame] | 132 | except VFile.Error, msg: |
| 133 | sys.stderr.write(msg + '\n') |
Guido van Rossum | e755aa5 | 1992-08-21 12:34:55 +0000 | [diff] [blame] | 134 | return 1 |
Guido van Rossum | 78aab86 | 1992-08-20 11:52:42 +0000 | [diff] [blame] | 135 | except EOFError: |
| 136 | sys.stderr.write(filename + ': EOF in video header\n') |
Guido van Rossum | e755aa5 | 1992-08-21 12:34:55 +0000 | [diff] [blame] | 137 | return 1 |
Guido van Rossum | 78aab86 | 1992-08-20 11:52:42 +0000 | [diff] [blame] | 138 | |
| 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 Rossum | 843d153 | 1992-08-18 14:16:12 +0000 | [diff] [blame] | 147 | |
| 148 | gl.foreground() |
Guido van Rossum | e755aa5 | 1992-08-21 12:34:55 +0000 | [diff] [blame] | 149 | |
| 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 Rossum | 78aab86 | 1992-08-20 11:52:42 +0000 | [diff] [blame] | 158 | win = gl.winopen(filename) |
Guido van Rossum | e755aa5 | 1992-08-21 12:34:55 +0000 | [diff] [blame] | 159 | gl.clear() |
| 160 | |
| 161 | if quiet: vin.quiet = 1 |
Guido van Rossum | 843d153 | 1992-08-18 14:16:12 +0000 | [diff] [blame] | 162 | vin.initcolormap() |
| 163 | |
| 164 | gl.qdevice(ESCKEY) |
| 165 | gl.qdevice(WINSHUT) |
| 166 | gl.qdevice(WINQUIT) |
Guido van Rossum | e755aa5 | 1992-08-21 12:34:55 +0000 | [diff] [blame] | 167 | gl.qdevice(LEFTMOUSE) |
Guido van Rossum | 843d153 | 1992-08-18 14:16:12 +0000 | [diff] [blame] | 168 | |
Guido van Rossum | e755aa5 | 1992-08-21 12:34:55 +0000 | [diff] [blame] | 169 | stop = 0 |
Guido van Rossum | 78aab86 | 1992-08-20 11:52:42 +0000 | [diff] [blame] | 170 | |
| 171 | while not stop: |
Guido van Rossum | e755aa5 | 1992-08-21 12:34:55 +0000 | [diff] [blame] | 172 | 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 Rossum | 78aab86 | 1992-08-20 11:52:42 +0000 | [diff] [blame] | 183 | |
Guido van Rossum | e755aa5 | 1992-08-21 12:34:55 +0000 | [diff] [blame] | 184 | # 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 Rossum | 78aab86 | 1992-08-20 11:52:42 +0000 | [diff] [blame] | 190 | gl.winclose(win) |
| 191 | |
Guido van Rossum | e755aa5 | 1992-08-21 12:34:55 +0000 | [diff] [blame] | 192 | return 0 |
| 193 | |
Guido van Rossum | 78aab86 | 1992-08-20 11:52:42 +0000 | [diff] [blame] | 194 | |
| 195 | # Play a movie once; return 1 if user wants to stop, 0 if not |
| 196 | |
| 197 | def playonce(vin): |
Guido van Rossum | e755aa5 | 1992-08-21 12:34:55 +0000 | [diff] [blame] | 198 | vin.rewind() |
Guido van Rossum | 78aab86 | 1992-08-20 11:52:42 +0000 | [diff] [blame] | 199 | vin.colormapinited = 1 |
| 200 | vin.magnify = magnify |
| 201 | |
Guido van Rossum | e755aa5 | 1992-08-21 12:34:55 +0000 | [diff] [blame] | 202 | 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 Rossum | 78aab86 | 1992-08-20 11:52:42 +0000 | [diff] [blame] | 211 | tin = 0 |
| 212 | told = 0 |
| 213 | nin = 0 |
| 214 | nout = 0 |
Guido van Rossum | e755aa5 | 1992-08-21 12:34:55 +0000 | [diff] [blame] | 215 | nlate = 0 |
Guido van Rossum | 78aab86 | 1992-08-20 11:52:42 +0000 | [diff] [blame] | 216 | nskipped = 0 |
Guido van Rossum | e755aa5 | 1992-08-21 12:34:55 +0000 | [diff] [blame] | 217 | data = None |
Guido van Rossum | 78aab86 | 1992-08-20 11:52:42 +0000 | [diff] [blame] | 218 | |
Guido van Rossum | e755aa5 | 1992-08-21 12:34:55 +0000 | [diff] [blame] | 219 | tlast = t0 = time.millitimer() |
Guido van Rossum | 78aab86 | 1992-08-20 11:52:42 +0000 | [diff] [blame] | 220 | |
| 221 | while 1: |
Guido van Rossum | 78aab86 | 1992-08-20 11:52:42 +0000 | [diff] [blame] | 222 | if gl.qtest(): |
Guido van Rossum | 843d153 | 1992-08-18 14:16:12 +0000 | [diff] [blame] | 223 | dev, val = gl.qread() |
Guido van Rossum | e755aa5 | 1992-08-21 12:34:55 +0000 | [diff] [blame] | 224 | 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 Rossum | 843d153 | 1992-08-18 14:16:12 +0000 | [diff] [blame] | 233 | if dev == REDRAW: |
| 234 | gl.reshapeviewport() |
Guido van Rossum | e755aa5 | 1992-08-21 12:34:55 +0000 | [diff] [blame] | 235 | 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 Rossum | 78aab86 | 1992-08-20 11:52:42 +0000 | [diff] [blame] | 276 | |
| 277 | t1 = time.millitimer() |
| 278 | |
Guido van Rossum | e755aa5 | 1992-08-21 12:34:55 +0000 | [diff] [blame] | 279 | if debug: sys.stderr.write('\n') |
| 280 | |
| 281 | if quiet: return 0 |
Guido van Rossum | 78aab86 | 1992-08-20 11:52:42 +0000 | [diff] [blame] | 282 | |
| 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 Rossum | e755aa5 | 1992-08-21 12:34:55 +0000 | [diff] [blame] | 287 | if nskipped: print 'Skipped', nskipped, 'frames' |
Guido van Rossum | 78aab86 | 1992-08-20 11:52:42 +0000 | [diff] [blame] | 288 | |
| 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 Rossum | e755aa5 | 1992-08-21 12:34:55 +0000 | [diff] [blame] | 295 | if nlate: print 'There were', nlate, 'late frames' |
Guido van Rossum | 78aab86 | 1992-08-20 11:52:42 +0000 | [diff] [blame] | 296 | |
| 297 | return 0 |
Guido van Rossum | 843d153 | 1992-08-18 14:16:12 +0000 | [diff] [blame] | 298 | |
Guido van Rossum | 82534fd | 1992-08-18 17:01:02 +0000 | [diff] [blame] | 299 | |
Guido van Rossum | e755aa5 | 1992-08-21 12:34:55 +0000 | [diff] [blame] | 300 | # Read-ahead thread |
| 301 | |
| 302 | def 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 Rossum | 82534fd | 1992-08-18 17:01:02 +0000 | [diff] [blame] | 311 | # Don't forget to call the main program |
| 312 | |
Guido van Rossum | e755aa5 | 1992-08-21 12:34:55 +0000 | [diff] [blame] | 313 | try: |
| 314 | main() |
| 315 | except KeyboardInterrupt: |
| 316 | print '[Interrupt]' |