From 6bc8c7f3e2cdc9fa0f1c71ba27d613776a64abdb Mon Sep 17 00:00:00 2001 From: Jack Jansen Date: Wed, 23 Dec 1992 15:37:20 +0000 Subject: Added mono, grey2 and grey4 formats --- Demo/sgi/video/LiveVideoIn.py | 16 ++- Demo/sgi/video/LiveVideoOut.py | 21 ++- Demo/sgi/video/VFile.py | 153 +++++++++++++++++----- Demo/sgi/video/Vrec.py | 81 ++++++++---- Demo/sgi/video/Vrecc.py | 281 +++++++++++++++++++++++++++++++++++++++++ 5 files changed, 491 insertions(+), 61 deletions(-) create mode 100755 Demo/sgi/video/Vrecc.py diff --git a/Demo/sgi/video/LiveVideoIn.py b/Demo/sgi/video/LiveVideoIn.py index d0ea858..47fae67 100755 --- a/Demo/sgi/video/LiveVideoIn.py +++ b/Demo/sgi/video/LiveVideoIn.py @@ -43,10 +43,10 @@ class LiveVideoIn: if realvw < vw: realvw = vw self.realwidth, self.realheight = v.QuerySize(realvw, vh) - if not type in ('rgb8', 'grey', 'mono'): - raise 'Incorrent video data type' + if not type in ('rgb8', 'grey', 'mono', 'grey2', 'grey4'): + raise 'Incorrent video data type', type self.type = type - if type in ('grey', 'mono'): + if type in ('grey', 'grey4', 'grey2', 'mono'): v.SetParam([SV.COLOR, SV.MONO, SV.INPUT_BYPASS, 1]) else: v.SetParam([SV.COLOR, SV.DEFAULT_COLOR, \ @@ -116,11 +116,21 @@ class LiveVideoIn: if self.type == 'mono': self.data = imageop.dither2mono(self.data, \ self.width, self.height) + elif self.type == 'grey2': + self.data = imageop.dither2grey2(self.data, \ + self.width, self.height) + elif self.type == 'grey4': + self.data = imageop.grey2grey4(self.data, \ + self.width, self.height) data = self.data[self.dataoffset:self.dataoffset+self.pktsize] lpos = self.lpos self.dataoffset = self.dataoffset + self.pktsize if self.type == 'mono': self.lpos = self.lpos + self.lpp*8 + elif self.type == 'grey2': + self.lpos = self.lpos + self.lpp*4 + elif self.type == 'grey4': + self.lpos = self.lpos + self.lpp*2 else: self.lpos = self.lpos + self.lpp return lpos, data diff --git a/Demo/sgi/video/LiveVideoOut.py b/Demo/sgi/video/LiveVideoOut.py index 23d03da..0ac64d2 100755 --- a/Demo/sgi/video/LiveVideoOut.py +++ b/Demo/sgi/video/LiveVideoOut.py @@ -18,8 +18,8 @@ class LiveVideoOut: self.vw = vw self.vh = vh self.disp = Displayer().init() - if not type in ('rgb8', 'grey', 'mono'): - raise 'Incorrent live video output type' + if not type in ('rgb8', 'grey', 'mono', 'grey2', 'grey4'): + raise 'Incorrent live video output type', type info = (type, vw, vh, 1, 8, 0, 0, 0, 0) self.disp.setinfo(info) self.wid = wid @@ -62,6 +62,10 @@ class LiveVideoOut: # Unfortunately size-check is difficult for # packed video nline = (len(data)*8)/self.vw + elif self.disp.format == 'grey2': + nline = (len(data)*4)/self.vw + elif self.disp.format == 'grey4': + nline = (len(data)*2)/self.vw else: nline = len(data)/self.vw if nline*self.vw <> len(data): @@ -76,3 +80,16 @@ class LiveVideoOut: def close(self): pass + + # Call this to set optional mirroring of video + def setmirror(self, mirrored): + f, w, h, pf, c0, c1, c2, o, cp = self.disp.getinfo() + if type(pf) == type(()): + xpf, ypf = pf + else: + xpf = ypf = pf + xpf = abs(xpf) + if mirrored: + xpf = -xpf + info = (f, w, h, (xpf, ypf), c0, c1, c2, o, cp) + self.disp.setinfo(inf0) diff --git a/Demo/sgi/video/VFile.py b/Demo/sgi/video/VFile.py index 5c05ed0..3d2bd8c 100755 --- a/Demo/sgi/video/VFile.py +++ b/Demo/sgi/video/VFile.py @@ -22,6 +22,7 @@ import sys import gl import GL import colorsys +import imageop # Exception raised for various occasions @@ -50,6 +51,12 @@ MAXMAP = 4096 - 256 def conv_grey(l, x, y): return colorsys.yiq_to_rgb(l, 0, 0) +def conv_grey4(l, x, y): + return colorsys.yiq_to_rgb(l*17, 0, 0) + +def conv_mono(l, x, y): + return colorsys.yiq_to_rgb(l*255, 0, 0) + def conv_yiq(y, i, q): return colorsys.yiq_to_rgb(y, (i-0.5)*1.2, q-0.5) @@ -73,7 +80,7 @@ def conv_jpeg(r, g, b): raise Error, 'Attempt to make RGB colormap (jpeg)' conv_jpeggrey = conv_grey -conv_mono = conv_grey +conv_grey2 = conv_grey # Choose one of the above based upon a color system name @@ -144,6 +151,15 @@ def is_entry_indigo(): b = gl.getgdesc(GL.GD_BITS_NORM_SNG_BLUE) return (r, g, b) == (3, 3, 2) +# +# Predicate function to see whether this machine supports pixmode(PM_SIZE) +# with values 1 or 4. +# +# XXX Temporarily disabled, since it is unclear which machines support +# XXX which pixelsizes. +# +def support_packed_pixels(): + return 0 # To be architecture-dependent # Routines to grab data, per color system (only a few really supported). # (These functions are used via eval with a constructed argument!) @@ -215,7 +231,7 @@ class VideoParams: # Essential parameters self.format = 'grey' # color system used # Choose from: grey, rgb, rgb8, hsv, yiq, hls, jpeg, jpeggrey, - # mono + # mono, grey2, grey4 self.width = 0 # width of frame self.height = 0 # height of frame self.packfactor = 1 # expansion using rectzoom @@ -264,6 +280,26 @@ class VideoParams: print 'Bits: ', self.c0bits, self.c1bits, self.c2bits print 'Offset: ', self.offset + # Calculate data size, if possible + def calcframesize(self): + if self.format == 'rgb': + return self.width*self.height*4 + if self.format in ('jpeg', 'jpeggrey'): + raise CallError + if type(self.packfactor) == type(()): + xpf, ypf = self.packfactor + else: + xpf = ypf = self.packfactor + if ypf < 0: ypf = -ypf + size = (self.width/xpf)*(self.height/ypf) + if self.format == 'grey4': + size = (size+1)/2 + elif self.format == 'grey2': + size = (size+3)/4 + elif self.format == 'mono': + size = (size+7)/8 + return size + # Class to display video frames in a window. # It is the caller's responsibility to ensure that the correct window @@ -287,6 +323,7 @@ class Displayer(VideoParams): self.skipchrom = 0 # don't skip chrominance data self.color0 = None # magic, used by clearto() self.fixcolor0 = 0 # don't need to fix color0 + self.mustunpack = (not support_packed_pixels()) return self # setinfo() must reset some internal flags @@ -306,34 +343,65 @@ class Displayer(VideoParams): def showpartframe(self, data, chromdata, (x,y,w,h)): pf = self.packfactor + pmsize = 8 + if pf: + if type(pf) == type(()): + xpf, ypf = pf + else: + xpf = ypf = pf + if ypf < 0: + gl.pixmode(GL.PM_TTOB, 1) + ypf = -ypf + if xpf < 0: + gl.pixmode(GL.PM_RTOL, 1) + xpf = -xpf + else: + xpf = ypf = 1 if self.format in ('jpeg', 'jpeggrey'): import jpeg data, width, height, bytes = jpeg.decompress(data) if self.format == 'jpeg': b = 4 - p = 1 + xp = yp = 1 else: b = 1 - p = pf - if (width, height, bytes) <> (w/p, h/p, b): + xp = xpf + yp = ypf + if (width, height, bytes) <> (w/xp, h/yp, b): raise Error, 'jpeg data has wrong size' - elif self.format == 'mono': - import imageop - data = imageop.mono2grey(data, w, h, 0x20, 0xdf) + elif self.format in ('mono', 'grey4'): + if self.mustunpack: + if self.format == 'mono': + data = imageop.mono2grey(data, \ + w/xpf, h/ypf, 0x20, 0xdf) + elif self.format == 'grey4': + data = imageop.grey42grey(data, \ + w/xpf, h/ypf) + else: + # We don't need to unpack, the hardware + # can do it. + if self.format == 'mono': + pmsize = 1 + else: + pmsize = 4 + elif self.format == 'grey2': + data = imageop.grey22grey(data, w/xpf, h/ypf) if not self.colormapinited: self.initcolormap() if self.fixcolor0: gl.mapcolor(self.color0) self.fixcolor0 = 0 - factor = self.magnify - if pf: factor = factor * pf + xfactor = yfactor = self.magnify + if pf: + xfactor = xfactor * xpf + yfactor = yfactor * ypf if chromdata and not self.skipchrom: cp = self.chrompack - cx = int(x*factor*cp) + self.xorigin - cy = int(y*factor*cp) + self.yorigin + cx = int(x*xfactor*cp) + self.xorigin + cy = int(y*yfactor*cp) + self.yorigin cw = (w+cp-1)/cp ch = (h+cp-1)/cp - gl.rectzoom(factor*cp, factor*cp) + gl.rectzoom(xfactor*cp, yfactor*cp) gl.pixmode(GL.PM_SIZE, 16) gl.writemask(self.mask - ((1 << self.c0bits) - 1)) gl.lrectwrite(cx, cy, cx + cw - 1, cy + ch - 1, \ @@ -341,14 +409,14 @@ class Displayer(VideoParams): # if pf: gl.writemask((1 << self.c0bits) - 1) - gl.pixmode(GL.PM_SIZE, 8) - w = w/pf - h = h/pf - x = x/pf - y = y/pf - gl.rectzoom(factor, factor) - x = int(x*factor)+self.xorigin - y = int(y*factor)+self.yorigin + gl.pixmode(GL.PM_SIZE, pmsize) + w = w/xpf + h = h/ypf + x = x/xpf + y = y/ypf + gl.rectzoom(xfactor, yfactor) + x = int(x*xfactor)+self.xorigin + y = int(y*yfactor)+self.yorigin gl.lrectwrite(x, y, x + w - 1, y + h - 1, data) gl.gflush() @@ -422,7 +490,10 @@ class Displayer(VideoParams): # by clear() and clearto() def _initcmap(self): - convcolor = choose_conversion(self.format) + if self.format in ('mono', 'grey4') and self.mustunpack: + convcolor = conv_grey + else: + convcolor = choose_conversion(self.format) maxbits = gl.getgdesc(GL.GD_BITS_NORM_SNG_CMODE) if maxbits > 11: maxbits = 11 @@ -496,7 +567,7 @@ class Grabber(VideoParams): # Read a CMIF video file header. -# Return (version, values) where version is 0.0, 1.0, 2.0 or 3.0, +# Return (version, values) where version is 0.0, 1.0, 2.0 or 3.[01], # and values is ready for setinfo(). # Raise Error if there is an error in the info @@ -513,6 +584,8 @@ def readfileheader(fp, filename): version = 2.0 elif line == 'CMIF video 3.0\n': version = 3.0 + elif line == 'CMIF video 3.1\n': + version = 3.1 else: # XXX Could be version 0.0 without identifying header raise Error, \ @@ -537,19 +610,19 @@ def readfileheader(fp, filename): else: format = 'grey' offset = 0 - elif version == 3.0: + elif version in (3.0, 3.1): line = fp.readline() try: format, rest = eval(line[:-1]) except: - raise Error, filename + ': Bad 3.0 color info' + raise Error, filename + ': Bad 3.[01] color info' if format == 'xrgb8': format = 'rgb8' # rgb8 upside-down, for X if format in ('rgb', 'jpeg'): c0bits = c1bits = c2bits = 0 chrompack = 0 offset = 0 - elif format in ('grey', 'jpeggrey', 'mono'): + elif format in ('grey', 'jpeggrey', 'mono', 'grey2', 'grey4'): c0bits = rest c1bits = c2bits = 0 chrompack = 0 @@ -559,7 +632,7 @@ def readfileheader(fp, filename): try: c0bits, c1bits, c2bits, chrompack, offset = rest except: - raise Error, filename + ': Bad 3.0 color info' + raise Error, filename + ': Bad 3.[01] color info' # # Get frame geometry info # @@ -580,7 +653,13 @@ def readfileheader(fp, filename): packfactor = 2 else: raise Error, filename + ': Bad (w,h,pf) info' - if packfactor > 1: + if type(packfactor) == type(()): + xpf, ypf = packfactor + xpf = abs(xpf) + ypf = abs(ypf) + width = (width/xpf) * xpf + height = (height/ypf) * ypf + elif packfactor > 1: width = (width / packfactor) * packfactor height = (height / packfactor) * packfactor # @@ -629,11 +708,11 @@ def readv3frameheader(fp): try: t, datasize, chromdatasize = x = eval(line[:-1]) except: - raise Error, 'Bad 3.0 frame header' + raise Error, 'Bad 3.[01] frame header' return x -# Write a CMIF video file header (always version 3.0) +# Write a CMIF video file header (always version 3.1) def writefileheader(fp, values): (format, width, height, packfactor, \ @@ -641,13 +720,13 @@ def writefileheader(fp, values): # # Write identifying header # - fp.write('CMIF video 3.0\n') + fp.write('CMIF video 3.1\n') # # Write color encoding info # if format in ('rgb', 'jpeg'): data = (format, 0) - elif format in ('grey', 'jpeggrey', 'mono'): + elif format in ('grey', 'jpeggrey', 'mono', 'grey2', 'grey4'): data = (format, c0bits) else: data = (format, (c0bits, c1bits, c2bits, chrompack, offset)) @@ -691,7 +770,7 @@ class BasicVinFile(VideoParams): self._readframeheader = readv1frameheader elif self.version == 2.0: self._readframeheader = readv2frameheader - elif self.version == 3.0: + elif self.version in (3.0, 3.1): self._readframeheader = readv3frameheader else: raise Error, \ @@ -950,6 +1029,14 @@ class BasicVoutFile(VideoParams): self.fp.close() del self.fp + def prealloc(self, nframes): + if not self.headerwritten: raise CallError + data = '\xff' * self.calcframesize() + pos = self.fp.tell() + for i in range(nframes): + self.fp.write(data) + self.fp.seek(pos) + def setinfo(self, values): if self.headerwritten: raise CallError VideoParams.setinfo(self, values) diff --git a/Demo/sgi/video/Vrec.py b/Demo/sgi/video/Vrec.py index f6814cd..689e8cf 100755 --- a/Demo/sgi/video/Vrec.py +++ b/Demo/sgi/video/Vrec.py @@ -17,9 +17,12 @@ # -w width : initial window width (default interactive placement) # -n : Don't write to file, only timing info # -d : drop fields if needed -# -g : greyscale +# -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) +# -P frames : preallocate space for 'frames' frames # # moviefile : here goes the movie data (default film.video); # the format is documented in cmif-film.ms @@ -53,6 +56,7 @@ import posix import getopt import string import imageop +import sgi # Main program @@ -66,9 +70,12 @@ def main(): drop = 0 mono = 0 grey = 0 + greybits = 0 monotreshold = -1 + fields = 0 + preallocspace = 0 - opts, args = getopt.getopt(sys.argv[1:], 'aq:r:w:ndgmM:') + opts, args = getopt.getopt(sys.argv[1:], 'aq:r:w:ndg:mM:GfP:') for opt, arg in opts: if opt == '-a': audio = 1 @@ -87,11 +94,21 @@ def main(): 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 == '-P': + preallocspace = string.atoi(arg) if args[2:]: sys.stderr.write('usage: Vrec [options] [file [audiofile]]\n') @@ -172,7 +189,8 @@ def main(): if val == 1: info = format, x, y, qsize, rate record(v, info, filename, audiofilename,\ - mono, grey, monotreshold) + mono, grey, greybits, monotreshold, \ + fields, preallocspace) elif dev == DEVICE.REDRAW: # Window resize (or move) x, y = gl.getsize() @@ -189,7 +207,8 @@ def main(): # Record until the mouse is released (or any other GL event) # XXX audio not yet supported -def record(v, info, filename, audiofilename, mono, grey, monotreshold): +def record(v, info, filename, audiofilename, mono, grey, greybits, \ + monotreshold, fields, preallocspace): import thread format, x, y, qsize, rate = info fps = 59.64 # Fields per second @@ -199,20 +218,36 @@ def record(v, info, filename, audiofilename, mono, grey, monotreshold): vout = VFile.VoutFile().init(filename) if mono: vout.format = 'mono' - elif grey: + 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) vout.writeheader() + if preallocspace: + print 'Preallocating space...' + vout.prealloc(preallocspace) + print 'done.' MAXSIZE = 20 # XXX should be a user option import Queue queue = Queue.Queue().init(MAXSIZE) done = thread.allocate_lock() done.acquire_lock() + convertor = None + if grey: + if greybits == 2: + convertor = imageop.grey2grey2 + elif greybits == 4: + convertor = imageop.grey2grey4 + elif greybits == -2: + convertor = imageop.dither2grey2 thread.start_new_thread(saveframes, \ - (vout, queue, done, mono, monotreshold)) + (vout, queue, done, mono, monotreshold, convertor)) if audiofilename: audiodone = thread.allocate_lock() audiodone.acquire_lock() @@ -222,27 +257,33 @@ def record(v, info, filename, audiofilename, mono, grey, monotreshold): lastid = 0 t0 = time.millitimer() count = 0 - timestamps = [] ids = [] v.InitContinuousCapture(info) while not gl.qtest(): try: cd, id = v.GetCaptureData() except sv.error: - time.millisleep(10) # XXX is this necessary? + #time.millisleep(10) # XXX is this necessary? + sgi.nap(1) # XXX Try by Jack continue - timestamps.append(time.millitimer()) ids.append(id) id = id + 2*rate ## if id <> lastid + 2*rate: ## print lastid, id lastid = id - data = cd.InterleaveFields(1) - cd.UnlockCaptureData() count = count+1 - if filename: - queue.put((data, int(id*tpf))) + if fields: + data1, data2 = cd.GetFields() + cd.UnlockCaptureData() + if filename: + queue.put((data1, int(id*tpf))) + queue.put((data2, int((id+1)*tpf))) + else: + data = cd.InterleaveFields(1) + cd.UnlockCaptureData() + if filename: + queue.put((data, int(id*tpf))) t1 = time.millitimer() gl.wintitle('(busy) ' + filename) print lastid, 'fields in', t1-t0, 'msec', @@ -253,13 +294,6 @@ def record(v, info, filename, audiofilename, mono, grey, monotreshold): print count*200.0/lastid, '%,', print count*rate*200.0/lastid, '% of wanted rate', print - t0 = timestamps[0] - del timestamps[0] - print 'Times:', - for t1 in timestamps: - print t1-t0, - t0 = t1 - print print 'Ids:', t0 = ids[0] del ids[0] @@ -279,19 +313,20 @@ def record(v, info, filename, audiofilename, mono, grey, monotreshold): # Thread to save the frames to the file -def saveframes(vout, queue, done, mono, monotreshold): +def saveframes(vout, queue, done, mono, monotreshold, convertor): while 1: x = queue.get() if not x: break data, t = x - if mono and monotreshold >= 0: + if convertor: + data = convertor(data, len(data), 1) + elif mono and monotreshold >= 0: data = imageop.grey2mono(data, len(data), 1,\ monotreshold) elif mono: data = imageop.dither2mono(data, len(data), 1) vout.writeframe(t, data, None) - del data sys.stderr.write('Done writing video\n') vout.close() done.release_lock() diff --git a/Demo/sgi/video/Vrecc.py b/Demo/sgi/video/Vrecc.py new file mode 100755 index 0000000..6a539f8 --- /dev/null +++ b/Demo/sgi/video/Vrecc.py @@ -0,0 +1,281 @@ +#! /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]' -- cgit v0.12