home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / pyos2bin.zip / Demo / sgi / video / Vplay.py < prev    next >
Text File  |  1996-11-27  |  8KB  |  356 lines

  1. #! /usr/bin/env python
  2.  
  3. # Play CMIF movie files
  4.  
  5.  
  6. # Help function
  7.  
  8. def 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 seconds (default 0.)'
  16.     print '-n         : don\'t wait after each file'
  17.     print '-q         : quiet, no informative messages'
  18.     print '-r delta   : regenerate input time base delta seconds 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 '-w width   : window width'
  24.     print '-h height  : window height'
  25.     print '-b color   : background color (white,black or (r,g,b))'
  26.     print 'file ...   : file(s) to play; default film.video'
  27.     print
  28.     print 'User interface:'
  29.     print 'Press the left mouse button to stop or restart the movie.'
  30.     print 'Press ESC or use the window manager Close or Quit command'
  31.     print 'to close the window and play the next file (if any).'
  32.  
  33.  
  34. # Imported modules
  35.  
  36. import sys
  37. sys.path.append('/ufs/guido/src/video') # Increase chance of finding VFile
  38. import VFile
  39. import time
  40. import gl, GL
  41. from DEVICE import REDRAW, ESCKEY, LEFTMOUSE, WINSHUT, WINQUIT
  42. import getopt
  43. import string
  44.  
  45.  
  46. # Global options
  47.  
  48. debug = 0
  49. looping = 0
  50. magnify = 1
  51. mindelta = 0
  52. nowait = 0
  53. quiet = 0
  54. regen = None
  55. speed = 1.0
  56. threading = 0
  57. xoff = yoff = None
  58. xwsiz = ywsiz = None
  59. bgcolor = None
  60.  
  61.  
  62. # Main program -- mostly command line parsing
  63.  
  64. def main():
  65.     global debug, looping, magnify, mindelta, nowait, quiet, regen, speed
  66.     global threading, xoff, yoff, xwsiz, ywsiz, bgcolor
  67.  
  68.     # Parse command line
  69.     try:
  70.         opts, args = getopt.getopt(sys.argv[1:], \
  71.               'M:dlm:nqr:s:tx:y:w:h:b:')
  72.     except getopt.error, msg:
  73.         sys.stdout = sys.stderr
  74.         print 'Error:', msg, '\n'
  75.         help()
  76.         sys.exit(2)
  77.  
  78.     # Interpret options
  79.     try:
  80.         for opt, arg in opts:
  81.             if opt == '-M': magnify = float(eval(arg))
  82.             if opt == '-d': debug = debug + 1
  83.             if opt == '-l': looping = 1
  84.             if opt == '-m': mindelta = float(eval(arg))
  85.             if opt == '-n': nowait = 1
  86.             if opt == '-q': quiet = 1
  87.             if opt == '-r': regen = float(eval(arg))
  88.             if opt == '-s':
  89.                 try:
  90.                     speed = float(eval(arg))
  91.                 except:
  92.                     sys.stdout = sys.stderr
  93.                     print 'Option -s needs float argument'
  94.                     sys.exit(2)
  95.             if opt == '-t':
  96.                 try:
  97.                     import thread
  98.                     threading = 1
  99.                 except ImportError:
  100.                     print 'Sorry, this version of Python',
  101.                     print 'does not support threads:',
  102.                     print '-t ignored'
  103.             if opt == '-x': xoff = string.atoi(arg)
  104.             if opt == '-y': yoff = string.atoi(arg)
  105.             if opt == '-w': xwsiz = string.atoi(arg)
  106.             if opt == '-h': ywsiz = string.atoi(arg)
  107.             if opt == '-b':
  108.                 if arg == 'black':
  109.                     bgcolor = (0,0,0)
  110.                 elif arg == 'white':
  111.                     bgcolor = (255,255,255)
  112.                 else:
  113.                     try:
  114.                         bgcolor = eval(arg)
  115.                         xxr, xxg, xxb = bgcolor
  116.                     except:
  117.                         print '-b needs (r,g,b) tuple'
  118.                         sys.exit(2)
  119.     except string.atoi_error:
  120.         sys.stdout = sys.stderr
  121.         print 'Option', opt, 'requires integer argument'
  122.         sys.exit(2)
  123.  
  124.     # Check validity of certain options combinations
  125.     if nowait and looping:
  126.         print 'Warning: -n and -l are mutually exclusive; -n ignored'
  127.         nowait = 0
  128.     if xoff <> None and yoff == None:
  129.         print 'Warning: -x without -y ignored'
  130.     if xoff == None and yoff <> None:
  131.         print 'Warning: -y without -x ignored'
  132.  
  133.     # Process all files
  134.     if not args: args = ['film.video']
  135.     sts = 0
  136.     for filename in args:
  137.         sts = (process(filename) or sts)
  138.  
  139.     # Exit with proper exit status
  140.     sys.exit(sts)
  141.  
  142.  
  143. # Process one movie file
  144.  
  145. def process(filename):
  146.     try:
  147.         vin = VFile.VinFile(filename)
  148.     except IOError, msg:
  149.         sys.stderr.write(filename + ': I/O error: ' + `msg` + '\n')
  150.         return 1
  151.     except VFile.Error, msg:
  152.         sys.stderr.write(msg + '\n')
  153.         return 1
  154.     except EOFError:
  155.         sys.stderr.write(filename + ': EOF in video header\n')
  156.         return 1
  157.  
  158.     if not quiet:
  159.         vin.printinfo()
  160.     
  161.     gl.foreground()
  162.  
  163.     width, height = int(vin.width * magnify), int(vin.height * magnify)
  164.     xborder = yborder = 0
  165.     if xwsiz:
  166.         vin.xorigin = (xwsiz - width)/2
  167.         width = xwsiz
  168.     if ywsiz:
  169.         vin.yorigin = (ywsiz - height)/2
  170.         height = ywsiz
  171.     if xoff <> None and yoff <> None:
  172.         scrheight = gl.getgdesc(GL.GD_YPMAX)
  173.         gl.prefposition(xoff, xoff+width-1, \
  174.             scrheight-yoff-height, scrheight-yoff-1)
  175.     else:
  176.         gl.prefsize(width, height)
  177.  
  178.     win = gl.winopen(filename)
  179.     gl.clear()
  180.  
  181.     if quiet: vin.quiet = 1
  182.     vin.initcolormap()
  183.  
  184.     if bgcolor:
  185.         r, g, b = bgcolor
  186.         vin.clearto(r,g,b)
  187.  
  188.     gl.qdevice(ESCKEY)
  189.     gl.qdevice(WINSHUT)
  190.     gl.qdevice(WINQUIT)
  191.     gl.qdevice(LEFTMOUSE)
  192.  
  193.     stop = 0
  194.  
  195.     while not stop:
  196.         gl.wintitle(filename)
  197.         stop = (playonce(vin) or nowait)
  198.         gl.wintitle('(done) ' + filename)
  199.         if not looping:
  200.             while not stop:
  201.                 dev, val = gl.qread()
  202.                 if dev == REDRAW:
  203.                     if bgcolor:
  204.                         r,g,b = bgcolor
  205.                         vin.clearto(r,g,b)
  206.                     else:
  207.                         vin.clear()
  208.                 if dev == LEFTMOUSE and val == 1:
  209.                     break # Continue outer loop
  210.                 if dev == ESCKEY and val == 1 or \
  211.                         dev in (WINSHUT, WINQUIT):
  212.                     stop = 1
  213.  
  214.     # Set xoff, yoff for the next window from the current window
  215.     global xoff, yoff
  216.     xoff, yoff = gl.getorigin()
  217.     width, height = gl.getsize()
  218.     scrheight = gl.getgdesc(GL.GD_YPMAX)
  219.     yoff = scrheight - yoff - height
  220.     gl.winclose(win)
  221.  
  222.     return 0
  223.  
  224.  
  225. # Play a movie once; return 1 if user wants to stop, 0 if not
  226.  
  227. def playonce(vin):
  228.     vin.rewind()
  229.     vin.colormapinited = 1
  230.     vin.magnify = magnify
  231.  
  232.     if threading:
  233.         MAXSIZE = 20 # Don't read ahead too much
  234.         import thread
  235.         import Queue
  236.         queue = Queue.Queue(MAXSIZE)
  237.         stop = []
  238.         thread.start_new_thread(read_ahead, (vin, queue, stop))
  239.         # Get the read-ahead thread going
  240.         while queue.qsize() < MAXSIZE/2 and not stop:
  241.             time.sleep(0.100)
  242.  
  243.     tin = 0
  244.     toffset = 0
  245.     oldtin = 0
  246.     told = 0
  247.     nin = 0
  248.     nout = 0
  249.     nlate = 0
  250.     nskipped = 0
  251.     data = None
  252.  
  253.     tlast = t0 = time.time()
  254.  
  255.     while 1:
  256.         if gl.qtest():
  257.             dev, val = gl.qread()
  258.             if dev == ESCKEY and val == 1 or \
  259.                     dev in (WINSHUT, WINQUIT) or \
  260.                     dev == LEFTMOUSE and val == 1:
  261.                 if debug: sys.stderr.write('\n')
  262.                 if threading:
  263.                     stop.append(None)
  264.                     while 1:
  265.                         item = queue.get()
  266.                         if item == None: break
  267.                 return (dev != LEFTMOUSE)
  268.             if dev == REDRAW:
  269.                 gl.reshapeviewport()
  270.                 if data: vin.showframe(data, cdata)
  271.         if threading:
  272.             if debug and queue.empty(): sys.stderr.write('.')
  273.             item = queue.get()
  274.             if item == None: break
  275.             tin, data, cdata = item
  276.         else:
  277.             try:
  278.                 tin, size, csize = vin.getnextframeheader()
  279.             except EOFError:
  280.                 break
  281.         tin = tin*0.001
  282.         nin = nin+1
  283.         if tin+toffset < oldtin:
  284.             print 'Fix reversed time:', oldtin, 'to', tin
  285.             toffset = oldtin - tin
  286.         tin = tin + toffset
  287.         oldtin = tin
  288.         if regen: tout = nin * regen
  289.         else: tout = tin
  290.         tout = tout / speed
  291.         if tout - told < mindelta:
  292.             nskipped = nskipped + 1
  293.             if not threading:
  294.                 vin.skipnextframedata(size, csize)
  295.         else:
  296.             if not threading:
  297.                 try:
  298.                     data, cdata = \
  299.                       vin.getnextframedata(size, csize)
  300.                 except EOFError:
  301.                     if not quiet:
  302.                         print '[incomplete last frame]'
  303.                     break
  304.             now = time.time()
  305.             dt = (tout-told) - (now-tlast)
  306.             told = tout
  307.             if debug: sys.stderr.write(`round(dt, 3)` + ' ')
  308.             if dt < 0: nlate = nlate + 1
  309.             if dt > 0:
  310.                 time.sleep(dt)
  311.                 now = time.time()
  312.             tlast = now
  313.             vin.showframe(data, cdata)
  314.             nout = nout + 1
  315.  
  316.     t1 = time.time()
  317.  
  318.     if debug: sys.stderr.write('\n')
  319.  
  320.     if quiet: return 0
  321.  
  322.     print 'Recorded:', nin, 'frames in', round(tin, 3), 'sec.',
  323.     if tin: print '-- average', round(nin/tin, 1), 'frames/sec',
  324.     print
  325.  
  326.     if nskipped: print 'Skipped', nskipped, 'frames'
  327.  
  328.     tout = t1-t0
  329.     print 'Played:', nout,
  330.     print 'frames in', round(tout, 3), 'sec.',
  331.     if tout: print '-- average', round(nout/tout, 1), 'frames/sec',
  332.     print
  333.  
  334.     if nlate: print 'There were', nlate, 'late frames'
  335.  
  336.     return 0
  337.  
  338.  
  339. # Read-ahead thread
  340.  
  341. def read_ahead(vin, queue, stop):
  342.     try:
  343.         while not stop: queue.put(vin.getnextframe())
  344.     except EOFError:
  345.         pass
  346.     queue.put(None)
  347.     stop.append(None)
  348.  
  349.  
  350. # Don't forget to call the main program
  351.  
  352. try:
  353.     main()
  354. except KeyboardInterrupt:
  355.     print '[Interrupt]'
  356.