summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJack Jansen <jack.jansen@cwi.nl>1992-12-23 15:37:20 (GMT)
committerJack Jansen <jack.jansen@cwi.nl>1992-12-23 15:37:20 (GMT)
commit6bc8c7f3e2cdc9fa0f1c71ba27d613776a64abdb (patch)
treece5cd4c2966f6af3b184eb4231d118239e473dfb
parentd7b67f261ee90728e41e6e56992246ccb1c71b78 (diff)
downloadcpython-6bc8c7f3e2cdc9fa0f1c71ba27d613776a64abdb.zip
cpython-6bc8c7f3e2cdc9fa0f1c71ba27d613776a64abdb.tar.gz
cpython-6bc8c7f3e2cdc9fa0f1c71ba27d613776a64abdb.tar.bz2
Added mono, grey2 and grey4 formats
-rwxr-xr-xDemo/sgi/video/LiveVideoIn.py16
-rwxr-xr-xDemo/sgi/video/LiveVideoOut.py21
-rwxr-xr-xDemo/sgi/video/VFile.py153
-rwxr-xr-xDemo/sgi/video/Vrec.py81
-rwxr-xr-xDemo/sgi/video/Vrecc.py281
5 files changed, 491 insertions, 61 deletions
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]'