mirror of https://github.com/python/cpython.git
Added mono, grey2 and grey4 formats
This commit is contained in:
parent
d7b67f261e
commit
6bc8c7f3e2
|
@ -43,10 +43,10 @@ def init(self, pktmax, vw, vh, type):
|
|||
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 @@ def getnextpacket(self):
|
|||
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
|
||||
|
|
|
@ -18,8 +18,8 @@ def init(self, wid, vw, vh, type):
|
|||
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 @@ def putnextpacket(self, pos, data):
|
|||
# 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 @@ def putnextpacket(self, pos, data):
|
|||
|
||||
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)
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
import gl
|
||||
import GL
|
||||
import colorsys
|
||||
import imageop
|
||||
|
||||
|
||||
# Exception raised for various occasions
|
||||
|
@ -50,6 +51,12 @@
|
|||
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 @@ def init(self):
|
|||
# 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 @@ def printinfo(self):
|
|||
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 @@ def init(self):
|
|||
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 @@ def showframe(self, data, chromdata):
|
|||
|
||||
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 @@ def showpartframe(self, data, chromdata, (x,y,w,h)):
|
|||
#
|
||||
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 @@ def clearto(self, r, g, b):
|
|||
# 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 @@ def grabframe(self):
|
|||
|
||||
|
||||
# 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 @@ def initfp(self, fp, filename):
|
|||
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 @@ def close(self):
|
|||
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)
|
||||
|
|
|
@ -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 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()
|
||||
|
|
|
@ -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]'
|
Loading…
Reference in New Issue