| #! /ufs/guido/bin/sgi/python-405 |
| #! /ufs/guido/bin/sgi/python |
| |
| # Capture a continuous CMIF movie using the Indigo video library and board |
| |
| |
| # Usage: |
| # |
| # makemovie [-r rate] [-w width] [moviefile] |
| |
| |
| # Options: |
| # |
| # -r rate : capture 1 out of every 'rate' frames (default 1) |
| # -w width : initial window width (default interactive placement) |
| # -d : drop fields if needed |
| # -g bits : greyscale (2, 4 or 8 bits) |
| # -G : 2-bit greyscale dithered |
| # -m : monochrome dithered |
| # -M value : monochrome tresholded with value |
| # -f : Capture fields (in stead of frames) |
| # -n number : Capture 'number' fields (default 60) |
| # |
| # moviefile : here goes the movie data (default film.video); |
| # the format is documented in cmif-film.ms |
| |
| |
| # User interface: |
| # |
| # Start the application. Resize the window to the desired movie size. |
| # Press the left mouse button to start recording, release it to end |
| # recording. You can record as many times as you wish, but each time |
| # you overwrite the output file(s), so only the last recording is |
| # kept. |
| # |
| # Press ESC or select the window manager Quit or Close window option |
| # to quit. If you quit before recording anything, the output file(s) |
| # are not touched. |
| |
| |
| import sys |
| sys.path.append('/ufs/guido/src/video') |
| import sv, SV |
| import VFile |
| import gl, GL, DEVICE |
| import al, AL |
| import time |
| import posix |
| import getopt |
| import string |
| import imageop |
| import sgi |
| |
| # Main program |
| |
| def main(): |
| format = SV.RGB8_FRAMES |
| rate = 1 |
| width = 0 |
| drop = 0 |
| mono = 0 |
| grey = 0 |
| greybits = 0 |
| monotreshold = -1 |
| fields = 0 |
| number = 60 |
| |
| opts, args = getopt.getopt(sys.argv[1:], 'r:w:dg:mM:Gfn:') |
| for opt, arg in opts: |
| if opt == '-r': |
| rate = string.atoi(arg) |
| if rate < 2: |
| sys.stderr.write('-r rate must be >= 2\n') |
| sys.exit(2) |
| elif opt == '-w': |
| width = string.atoi(arg) |
| elif opt == '-d': |
| drop = 1 |
| elif opt == '-g': |
| grey = 1 |
| greybits = string.atoi(arg) |
| if not greybits in (2,4,8): |
| print 'Only 2, 4 or 8 bit greyscale supported' |
| elif opt == '-G': |
| grey = 1 |
| greybits = -2 |
| elif opt == '-m': |
| mono = 1 |
| elif opt == '-M': |
| mono = 1 |
| monotreshold = string.atoi(arg) |
| elif opt == '-f': |
| fields = 1 |
| elif opt == '-n': |
| number = string.atoi(arg) |
| |
| if args[2:]: |
| sys.stderr.write('usage: Vrec [options] [file]\n') |
| sys.exit(2) |
| |
| if args: |
| filename = args[0] |
| else: |
| filename = 'film.video' |
| |
| v = sv.OpenVideo() |
| # Determine maximum window size based on signal standard |
| param = [SV.BROADCAST, 0] |
| v.GetParam(param) |
| if param[1] == SV.PAL: |
| x = SV.PAL_XMAX |
| y = SV.PAL_YMAX |
| elif param[1] == SV.NTSC: |
| x = SV.NTSC_XMAX |
| y = SV.NTSC_YMAX |
| else: |
| print 'Unknown video standard', param[1] |
| sys.exit(1) |
| |
| gl.foreground() |
| gl.maxsize(x, y) |
| gl.keepaspect(x, y) |
| gl.stepunit(8, 6) |
| if width: |
| gl.prefsize(width, width*3/4) |
| win = gl.winopen(filename) |
| if width: |
| gl.maxsize(x, y) |
| gl.keepaspect(x, y) |
| gl.stepunit(8, 6) |
| gl.winconstraints() |
| x, y = gl.getsize() |
| print x, 'x', y |
| |
| v.SetSize(x, y) |
| |
| if drop: |
| param = [SV.FIELDDROP, 1, SV.GENLOCK, SV.GENLOCK_OFF] |
| else: |
| param = [SV.FIELDDROP, 0, SV.GENLOCK, SV.GENLOCK_ON] |
| if mono or grey: |
| param = param+[SV.COLOR, SV.MONO, SV.INPUT_BYPASS, 1] |
| else: |
| param = param+[SV.COLOR, SV.DEFAULT_COLOR, SV.INPUT_BYPASS, 0] |
| v.SetParam(param) |
| |
| v.BindGLWindow(win, SV.IN_REPLACE) |
| |
| gl.qdevice(DEVICE.LEFTMOUSE) |
| gl.qdevice(DEVICE.WINQUIT) |
| gl.qdevice(DEVICE.WINSHUT) |
| gl.qdevice(DEVICE.ESCKEY) |
| |
| print 'Press left mouse to start recording' |
| |
| while 1: |
| dev, val = gl.qread() |
| if dev == DEVICE.LEFTMOUSE: |
| if val == 1: |
| info = format, x, y, number, rate |
| record(v, info, filename, mono, grey, \ |
| greybits, monotreshold, fields) |
| elif dev == DEVICE.REDRAW: |
| # Window resize (or move) |
| x, y = gl.getsize() |
| print x, 'x', y |
| v.SetSize(x, y) |
| v.BindGLWindow(win, SV.IN_REPLACE) |
| elif dev in (DEVICE.ESCKEY, DEVICE.WINQUIT, DEVICE.WINSHUT): |
| # Quit |
| v.CloseVideo() |
| gl.winclose(win) |
| break |
| |
| |
| # Record until the mouse is released (or any other GL event) |
| # XXX audio not yet supported |
| |
| def record(v, info, filename, mono, grey, greybits, monotreshold, fields): |
| import thread |
| format, x, y, number, rate = info |
| fps = 59.64 # Fields per second |
| # XXX (Strange: need fps of Indigo monitor, not of PAL or NTSC!) |
| tpf = 1000.0 / fps # Time per field in msec |
| # |
| # Go grab |
| # |
| gl.wintitle('(rec) ' + filename) |
| try: |
| ninfo, data, bitvec = v.CaptureBurst(info) |
| except sv.error, arg: |
| print 'CaptureBurst failed:', arg |
| print 'info:', info |
| gl.wintitle(filename) |
| return |
| gl.wintitle('(save) '+ filename) |
| # |
| # Check results |
| # |
| if info <> ninfo: |
| print 'Sorry, format changed.' |
| print 'Wanted:',info |
| print 'Got :',ninfo |
| gl.wintitle(filename) |
| return |
| # print bitvec |
| if x*y*number <> len(data): |
| print 'Funny data length: wanted',x,'*',y,'*', number,'=',\ |
| x*y*number,'got',len(data) |
| gl.wintitle(filename) |
| return |
| # |
| # Save |
| # |
| if filename: |
| # |
| # Construct header and write it |
| # |
| vout = VFile.VoutFile().init(filename) |
| if mono: |
| vout.format = 'mono' |
| elif grey and greybits == 8: |
| vout.format = 'grey' |
| elif grey: |
| vout.format = 'grey'+`abs(greybits)` |
| else: |
| vout.format = 'rgb8' |
| vout.width = x |
| vout.height = y |
| if fields: |
| vout.packfactor = (1,-2) |
| else: |
| print 'Sorry, can only save fields at the moment' |
| gl.wintitle(filename) |
| return |
| vout.writeheader() |
| # |
| # Compute convertor, if needed |
| # |
| convertor = None |
| if grey: |
| if greybits == 2: |
| convertor = imageop.grey2grey2 |
| elif greybits == 4: |
| convertor = imageop.grey2grey4 |
| elif greybits == -2: |
| convertor = imageop.dither2grey2 |
| fieldsize = x*y/2 |
| nskipped = 0 |
| realframeno = 0 |
| tpf = 1000 / 50.0 #XXXX |
| for frameno in range(0, number*2): |
| if frameno <> 0 and \ |
| bitvec[frameno] == bitvec[frameno-1]: |
| nskipped = nskipped + 1 |
| continue |
| # |
| # Save field. |
| # XXXX Works only for fields and top-to-bottom |
| # |
| start = frameno*fieldsize |
| field = data[start:start+fieldsize] |
| if convertor: |
| field = convertor(field, x, y) |
| elif mono and monotreshold >= 0: |
| field = imageop.grey2mono(field, x, y, \ |
| 1, monotreshold) |
| elif mono: |
| field = imageop.dither2mono(field, x, y) |
| vout.writeframe(int(realframeno*tpf), field, None) |
| print 'Skipped',nskipped,'duplicate frames' |
| vout.close() |
| |
| gl.wintitle('(done) ' + filename) |
| |
| # Don't forget to call the main program |
| |
| try: |
| main() |
| except KeyboardInterrupt: |
| print '[Interrupt]' |