mirror of
https://github.com/python/cpython.git
synced 2025-08-03 08:34:29 +00:00
Changes for supporting monochrome and greyscale video (not yet fully
functional)
This commit is contained in:
parent
cf5dd9cbfd
commit
3b25371ef1
7 changed files with 185 additions and 46 deletions
|
@ -33,7 +33,7 @@ class LiveVideoIn:
|
|||
# Note that the data has to be cropped unless vw and vh are
|
||||
# just right for the video board (vw:vh == 4:3 and vh even).
|
||||
|
||||
def init(self, pktmax, vw, vh):
|
||||
def init(self, pktmax, vw, vh, type):
|
||||
if not have_video:
|
||||
raise RuntimeError, 'no video available'
|
||||
if vw % 4 != 0:
|
||||
|
@ -43,6 +43,14 @@ 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'
|
||||
self.type = type
|
||||
if type in ('grey', 'mono'):
|
||||
v.SetParam([SV.COLOR, SV.MONO, SV.INPUT_BYPASS, 1])
|
||||
else:
|
||||
v.SetParam([SV.COLOR, SV.DEFAULT_COLOR, \
|
||||
SV.INPUT_BYPASS, 0])
|
||||
# Initialize capture
|
||||
(mode, self.realwidth, self.realheight, qsize, rate) = \
|
||||
v.InitContinuousCapture(SV.RGB8_FRAMES, \
|
||||
|
@ -70,7 +78,7 @@ class LiveVideoIn:
|
|||
|
||||
def resizevideo(self, vw, vh):
|
||||
self.close()
|
||||
self = self.init(self.pktmax, vw, vh)
|
||||
self = self.init(self.pktmax, vw, vh, self.type)
|
||||
|
||||
# Remove an instance.
|
||||
# This turns off continuous capture.
|
||||
|
@ -105,8 +113,14 @@ class LiveVideoIn:
|
|||
self.x1, self.y1)
|
||||
self.lpos = 0
|
||||
self.dataoffset = 0
|
||||
if self.type == 'mono':
|
||||
self.data = imageop.dither2mono(self.data, \
|
||||
self.width, self.height)
|
||||
data = self.data[self.dataoffset:self.dataoffset+self.pktsize]
|
||||
lpos = self.lpos
|
||||
self.dataoffset = self.dataoffset + self.pktsize
|
||||
self.lpos = self.lpos + self.lpp
|
||||
if self.type == 'mono':
|
||||
self.lpos = self.lpos + self.lpp*8
|
||||
else:
|
||||
self.lpos = self.lpos + self.lpp
|
||||
return lpos, data
|
||||
|
|
|
@ -12,13 +12,15 @@ class LiveVideoOut:
|
|||
# wid: the window id where the video is to be displayed (centered)
|
||||
# vw, vh: size of the video image to be displayed
|
||||
|
||||
def init(self, wid, vw, vh):
|
||||
def init(self, wid, vw, vh, type):
|
||||
##print 'Init', wid, xywh
|
||||
##print 'video', vw, vw
|
||||
self.vw = vw
|
||||
self.vh = vh
|
||||
self.disp = Displayer().init()
|
||||
info = ('rgb8', vw, vh, 1, 8, 0, 0, 0, 0)
|
||||
if not type in ('rgb8', 'grey', 'mono'):
|
||||
raise 'Incorrent live video output type'
|
||||
info = (type, vw, vh, 1, 8, 0, 0, 0, 0)
|
||||
self.disp.setinfo(info)
|
||||
self.wid = wid
|
||||
oldwid = gl.winget()
|
||||
|
@ -56,10 +58,15 @@ class LiveVideoOut:
|
|||
# LiveVideoIn.getnextpacket()).
|
||||
|
||||
def putnextpacket(self, pos, data):
|
||||
nline = len(data)/self.vw
|
||||
if nline*self.vw <> len(data):
|
||||
print 'Incorrect-sized video fragment ignored'
|
||||
return
|
||||
if self.disp.format == 'mono':
|
||||
# Unfortunately size-check is difficult for
|
||||
# packed video
|
||||
nline = (len(data)*8)/self.vw
|
||||
else:
|
||||
nline = len(data)/self.vw
|
||||
if nline*self.vw <> len(data):
|
||||
print 'Incorrect-sized video fragment ignored'
|
||||
return
|
||||
oldwid = gl.winget()
|
||||
gl.winset(self.wid)
|
||||
self.disp.showpartframe(data, None, (0, pos, self.vw, nline))
|
||||
|
|
|
@ -73,6 +73,7 @@ def conv_jpeg(r, g, b):
|
|||
raise Error, 'Attempt to make RGB colormap (jpeg)'
|
||||
|
||||
conv_jpeggrey = conv_grey
|
||||
conv_mono = conv_grey
|
||||
|
||||
|
||||
# Choose one of the above based upon a color system name
|
||||
|
@ -213,7 +214,8 @@ class VideoParams:
|
|||
def init(self):
|
||||
# Essential parameters
|
||||
self.format = 'grey' # color system used
|
||||
# Choose from: grey, rgb, rgb8, hsv, yiq, hls, jpeg, jpeggrey
|
||||
# Choose from: grey, rgb, rgb8, hsv, yiq, hls, jpeg, jpeggrey,
|
||||
# mono
|
||||
self.width = 0 # width of frame
|
||||
self.height = 0 # height of frame
|
||||
self.packfactor = 1 # expansion using rectzoom
|
||||
|
@ -315,6 +317,9 @@ class Displayer(VideoParams):
|
|||
p = pf
|
||||
if (width, height, bytes) <> (w/p, h/p, b):
|
||||
raise Error, 'jpeg data has wrong size'
|
||||
elif self.format == 'mono':
|
||||
import imageop
|
||||
data = imageop.mono2grey(data, w, h, 0x20, 0xdf)
|
||||
if not self.colormapinited:
|
||||
self.initcolormap()
|
||||
if self.fixcolor0:
|
||||
|
@ -544,7 +549,7 @@ def readfileheader(fp, filename):
|
|||
c0bits = c1bits = c2bits = 0
|
||||
chrompack = 0
|
||||
offset = 0
|
||||
elif format in ('grey', 'jpeggrey'):
|
||||
elif format in ('grey', 'jpeggrey', 'mono'):
|
||||
c0bits = rest
|
||||
c1bits = c2bits = 0
|
||||
chrompack = 0
|
||||
|
@ -642,7 +647,7 @@ def writefileheader(fp, values):
|
|||
#
|
||||
if format in ('rgb', 'jpeg'):
|
||||
data = (format, 0)
|
||||
elif format in ('grey', 'jpeggrey'):
|
||||
elif format in ('grey', 'jpeggrey', 'mono'):
|
||||
data = (format, c0bits)
|
||||
else:
|
||||
data = (format, (c0bits, c1bits, c2bits, chrompack, offset))
|
||||
|
|
|
@ -15,6 +15,11 @@
|
|||
# -q queuesize : set the capture queue size (default 2)
|
||||
# -r rate : capture 1 out of every 'rate' frames (default and min 2)
|
||||
# -w width : initial window width (default interactive placement)
|
||||
# -n : Don't write to file, only timing info
|
||||
# -d : drop fields if needed
|
||||
# -g : greyscale
|
||||
# -m : monochrome dithered
|
||||
# -M value : monochrome tresholded with value
|
||||
#
|
||||
# moviefile : here goes the movie data (default film.video);
|
||||
# the format is documented in cmif-film.ms
|
||||
|
@ -47,7 +52,7 @@ import time
|
|||
import posix
|
||||
import getopt
|
||||
import string
|
||||
|
||||
import imageop
|
||||
|
||||
# Main program
|
||||
|
||||
|
@ -57,8 +62,13 @@ def main():
|
|||
audio = 0
|
||||
rate = 2
|
||||
width = 0
|
||||
norecord = 0
|
||||
drop = 0
|
||||
mono = 0
|
||||
grey = 0
|
||||
monotreshold = -1
|
||||
|
||||
opts, args = getopt.getopt(sys.argv[1:], 'aq:r:w:')
|
||||
opts, args = getopt.getopt(sys.argv[1:], 'aq:r:w:ndgmM:')
|
||||
for opt, arg in opts:
|
||||
if opt == '-a':
|
||||
audio = 1
|
||||
|
@ -71,6 +81,17 @@ def main():
|
|||
sys.exit(2)
|
||||
elif opt == '-w':
|
||||
width = string.atoi(arg)
|
||||
elif opt == '-n':
|
||||
norecord = 1
|
||||
elif opt == '-d':
|
||||
drop = 1
|
||||
elif opt == '-g':
|
||||
grey = 1
|
||||
elif opt == '-m':
|
||||
mono = 1
|
||||
elif opt == '-M':
|
||||
mono = 1
|
||||
monotreshold = string.atoi(arg)
|
||||
|
||||
if args[2:]:
|
||||
sys.stderr.write('usage: Vrec [options] [file [audiofile]]\n')
|
||||
|
@ -93,6 +114,8 @@ def main():
|
|||
else:
|
||||
audiofilename = None
|
||||
|
||||
if norecord:
|
||||
filename = audiofilename = ''
|
||||
v = sv.OpenVideo()
|
||||
# Determine maximum window size based on signal standard
|
||||
param = [SV.BROADCAST, 0]
|
||||
|
@ -123,11 +146,25 @@ def main():
|
|||
print x, 'x', y
|
||||
|
||||
v.SetSize(x, y)
|
||||
<<<<<<< Vrec.py
|
||||
|
||||
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)
|
||||
|
||||
=======
|
||||
|
||||
# VERY IMPORTANT (for PAL at least): don't drop fields!
|
||||
param = [SV.FIELDDROP, 0]
|
||||
v.SetParam(param)
|
||||
|
||||
>>>>>>> 1.7
|
||||
v.BindGLWindow(win, SV.IN_REPLACE)
|
||||
|
||||
gl.qdevice(DEVICE.LEFTMOUSE)
|
||||
|
@ -142,7 +179,8 @@ def main():
|
|||
if dev == DEVICE.LEFTMOUSE:
|
||||
if val == 1:
|
||||
info = format, x, y, qsize, rate
|
||||
record(v, info, filename, audiofilename)
|
||||
record(v, info, filename, audiofilename,\
|
||||
mono, grey, monotreshold)
|
||||
elif dev == DEVICE.REDRAW:
|
||||
# Window resize (or move)
|
||||
x, y = gl.getsize()
|
||||
|
@ -159,31 +197,41 @@ def main():
|
|||
# Record until the mouse is released (or any other GL event)
|
||||
# XXX audio not yet supported
|
||||
|
||||
def record(v, info, filename, audiofilename):
|
||||
def record(v, info, filename, audiofilename, mono, grey, monotreshold):
|
||||
import thread
|
||||
format, x, y, qsize, 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
|
||||
vout = VFile.VoutFile().init(filename)
|
||||
vout.format = 'rgb8'
|
||||
vout.width = x
|
||||
vout.height = y
|
||||
vout.writeheader()
|
||||
MAXSIZE = 20 # XXX should be a user option
|
||||
import Queue
|
||||
queue = Queue.Queue().init(MAXSIZE)
|
||||
done = thread.allocate_lock()
|
||||
done.acquire_lock()
|
||||
thread.start_new_thread(saveframes, (vout, queue, done))
|
||||
if audiofilename:
|
||||
audiodone = thread.allocate_lock()
|
||||
audiodone.acquire_lock()
|
||||
audiostop = []
|
||||
initaudio(audiofilename, audiostop, audiodone)
|
||||
if filename:
|
||||
vout = VFile.VoutFile().init(filename)
|
||||
if mono:
|
||||
vout.format = 'mono'
|
||||
elif grey:
|
||||
vout.format = 'grey'
|
||||
else:
|
||||
vout.format = 'rgb8'
|
||||
vout.width = x
|
||||
vout.height = y
|
||||
vout.writeheader()
|
||||
MAXSIZE = 20 # XXX should be a user option
|
||||
import Queue
|
||||
queue = Queue.Queue().init(MAXSIZE)
|
||||
done = thread.allocate_lock()
|
||||
done.acquire_lock()
|
||||
thread.start_new_thread(saveframes, \
|
||||
(vout, queue, done, mono, monotreshold))
|
||||
if audiofilename:
|
||||
audiodone = thread.allocate_lock()
|
||||
audiodone.acquire_lock()
|
||||
audiostop = []
|
||||
initaudio(audiofilename, audiostop, audiodone)
|
||||
gl.wintitle('(rec) ' + filename)
|
||||
lastid = 0
|
||||
t0 = time.millitimer()
|
||||
count = 0
|
||||
timestamps = []
|
||||
ids = []
|
||||
v.InitContinuousCapture(info)
|
||||
while not gl.qtest():
|
||||
try:
|
||||
|
@ -191,34 +239,62 @@ def record(v, info, filename, audiofilename):
|
|||
except sv.error:
|
||||
time.millisleep(10) # XXX is this necessary?
|
||||
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()
|
||||
queue.put(data, int(id*tpf))
|
||||
count = count+1
|
||||
if filename:
|
||||
queue.put(data, int(id*tpf))
|
||||
t1 = time.millitimer()
|
||||
gl.wintitle('(busy) ' + filename)
|
||||
print lastid, 'fields in', t1-t0, 'msec',
|
||||
print '--', 0.1 * int(lastid * 10000.0 / (t1-t0)), 'fields/sec'
|
||||
if audiofilename:
|
||||
print 'Captured',count*2, 'fields,', 0.1*int(count*20000.0/(t1-t0)), 'f/s',
|
||||
print count*200.0/lastid, '%,',
|
||||
print count*rate*200.0/lastid, '% of wanted rate'
|
||||
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]
|
||||
for t1 in ids:
|
||||
print t1-t0,
|
||||
t0 = t1
|
||||
print
|
||||
if filename and audiofilename:
|
||||
audiostop.append(None)
|
||||
audiodone.acquire_lock()
|
||||
v.EndContinuousCapture()
|
||||
queue.put(None) # Sentinel
|
||||
done.acquire_lock()
|
||||
if filename:
|
||||
queue.put(None) # Sentinel
|
||||
done.acquire_lock()
|
||||
gl.wintitle('(done) ' + filename)
|
||||
|
||||
|
||||
# Thread to save the frames to the file
|
||||
|
||||
def saveframes(vout, queue, done):
|
||||
def saveframes(vout, queue, done, mono, monotreshold):
|
||||
while 1:
|
||||
x = queue.get()
|
||||
if not x:
|
||||
break
|
||||
data, t = x
|
||||
if 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')
|
||||
|
|
|
@ -23,9 +23,10 @@ from senddefs import *
|
|||
|
||||
def usage(msg):
|
||||
print msg
|
||||
print 'usage: Vreceive [-m mcastgrp] [-p port]'
|
||||
print 'usage: Vreceive [-m mcastgrp] [-p port] [-c type]'
|
||||
print '-m mcastgrp: multicast group (default ' + `DEFMCAST` + ')'
|
||||
print '-p port : port (default ' + `DEFPORT` + ')'
|
||||
print '-c type : signal type: rgb8, grey or mono (default rgb8)'
|
||||
sys.exit(2)
|
||||
|
||||
|
||||
|
@ -39,9 +40,10 @@ def main():
|
|||
port = DEFPORT
|
||||
width = DEFWIDTH
|
||||
height = DEFHEIGHT
|
||||
vtype = 'rgb8'
|
||||
|
||||
try:
|
||||
opts, args = getopt.getopt(sys.argv[1:], 'm:p:')
|
||||
opts, args = getopt.getopt(sys.argv[1:], 'm:p:c:')
|
||||
except getopt.error, msg:
|
||||
usage(msg)
|
||||
|
||||
|
@ -51,6 +53,8 @@ def main():
|
|||
port = string.atoi(optarg)
|
||||
if opt == '-m':
|
||||
group = gethostbyname(optarg)
|
||||
if opt == '-c':
|
||||
vtype = optarg
|
||||
except string.atoi_error, msg:
|
||||
usage('bad integer: ' + msg)
|
||||
|
||||
|
@ -64,7 +68,7 @@ def main():
|
|||
gl.qdevice(DEVICE.WINSHUT)
|
||||
gl.qdevice(DEVICE.WINQUIT)
|
||||
|
||||
lvo = LiveVideoOut.LiveVideoOut().init(wid, width, height)
|
||||
lvo = LiveVideoOut.LiveVideoOut().init(wid, width, height, vtype)
|
||||
|
||||
ifdlist = [gl.qgetfd(), s.fileno()]
|
||||
ofdlist = []
|
||||
|
|
|
@ -22,7 +22,7 @@ from senddefs import *
|
|||
|
||||
def usage(msg):
|
||||
print msg
|
||||
print 'usage: Vsend [-b] [-h height] [-p port] [-s size] [-t ttl]',
|
||||
print 'usage: Vsend [-b] [-h height] [-p port] [-s size] [-t ttl] [-c type] [-m]',
|
||||
print '[-w width] [host] ...'
|
||||
print '-b : broadcast on local net'
|
||||
print '-h height : window height (default ' + `DEFHEIGHT` + ')'
|
||||
|
@ -30,6 +30,7 @@ def usage(msg):
|
|||
print '-t ttl : time-to-live (multicast only; default 1)'
|
||||
print '-s size : max packet size (default ' + `DEFPKTMAX` + ')'
|
||||
print '-w width : window width (default ' + `DEFWIDTH` + ')'
|
||||
print '-c type : Type: rgb8, mono or grey (default rgb8)'
|
||||
print '[host] ...: host(s) to send to (default multicast to ' + \
|
||||
DEFMCAST + ')'
|
||||
sys.exit(2)
|
||||
|
@ -44,9 +45,10 @@ def main():
|
|||
pktmax = DEFPKTMAX
|
||||
width = DEFWIDTH
|
||||
height = DEFHEIGHT
|
||||
vtype = 'rgb8'
|
||||
|
||||
try:
|
||||
opts, args = getopt.getopt(sys.argv[1:], 'bh:p:s:t:w:')
|
||||
opts, args = getopt.getopt(sys.argv[1:], 'bh:p:s:t:w:c:')
|
||||
except getopt.error, msg:
|
||||
usage(msg)
|
||||
|
||||
|
@ -64,6 +66,8 @@ def main():
|
|||
width = string.atoi(optarg)
|
||||
if opt == '-h':
|
||||
height = string.atoi(optarg)
|
||||
if opt == '-c':
|
||||
vtype = optarg
|
||||
except string.atoi_error, msg:
|
||||
usage('bad integer: ' + msg)
|
||||
|
||||
|
@ -92,9 +96,9 @@ def main():
|
|||
gl.qdevice(DEVICE.WINTHAW)
|
||||
width, height = gl.getsize()
|
||||
|
||||
lvo = LiveVideoOut.LiveVideoOut().init(wid, width, height)
|
||||
lvo = LiveVideoOut.LiveVideoOut().init(wid, width, height, vtype)
|
||||
|
||||
lvi = LiveVideoIn.LiveVideoIn().init(pktmax, width, height)
|
||||
lvi = LiveVideoIn.LiveVideoIn().init(pktmax, width, height, vtype)
|
||||
|
||||
s = socket(AF_INET, SOCK_DGRAM)
|
||||
s.setsockopt(SOL_SOCKET, SO_BROADCAST, 1)
|
||||
|
|
|
@ -5,12 +5,18 @@ import getopt
|
|||
from gl import *
|
||||
from DEVICE import *
|
||||
import VFile
|
||||
import string
|
||||
import imageop
|
||||
|
||||
def report(time, iframe):
|
||||
print 'Frame', iframe, ': t =', time
|
||||
|
||||
def usage():
|
||||
sys.stderr.write('usage: vcopy infile outfile\n')
|
||||
sys.stderr.write('usage: vcopy [-t type] [-m treshold] [-a] infile outfile\n')
|
||||
sys.stderr.write('-t Convert to other type\n')
|
||||
sys.stderr.write('-a Automatic\n')
|
||||
sys.stderr.write('-m Convert grey to mono with treshold\n')
|
||||
sys.stderr.write('-d Convert grey to mono with dithering\n')
|
||||
sys.exit(2)
|
||||
|
||||
def help():
|
||||
|
@ -20,7 +26,7 @@ def help():
|
|||
|
||||
def main():
|
||||
foreground()
|
||||
opts, args = getopt.getopt(sys.argv[1:], 't:a')
|
||||
opts, args = getopt.getopt(sys.argv[1:], 't:am:d')
|
||||
if len(args) <> 2:
|
||||
usage()
|
||||
[ifile, ofile] = args
|
||||
|
@ -33,12 +39,28 @@ def main():
|
|||
|
||||
use_grabber = 0
|
||||
continuous = 0
|
||||
tomono = 0
|
||||
tomonodither = 0
|
||||
for o, a in opts:
|
||||
if o == '-t':
|
||||
ofilm.format = a
|
||||
use_grabber = 1
|
||||
if o == '-a':
|
||||
continuous = 1
|
||||
if o == '-m':
|
||||
if ifilm.format <> 'grey':
|
||||
print '-m only supported for greyscale'
|
||||
sys.exit(1)
|
||||
tomono = 1
|
||||
treshold = string.atoi(a)
|
||||
ofilm.format = 'mono'
|
||||
if o == '-d':
|
||||
if ifilm.format <> 'grey':
|
||||
print '-m only supported for greyscale'
|
||||
sys.exit(1)
|
||||
tomonodither = 1
|
||||
ofilm.format = 'mono'
|
||||
|
||||
ofilm.writeheader()
|
||||
#
|
||||
prefsize(ifilm.width, ifilm.height)
|
||||
|
@ -83,6 +105,13 @@ def main():
|
|||
if c == 'w' or continuous:
|
||||
if use_grabber:
|
||||
data, cdata = ofilm.grabframe()
|
||||
if tomono:
|
||||
data = imageop.grey2mono(data, \
|
||||
ifilm.width, ifilm.height, \
|
||||
treshold)
|
||||
if tomonodither:
|
||||
data = imageop.dither2mono(data, \
|
||||
ifilm.width, ifilm.height)
|
||||
ofilm.writeframe(time, data, cdata)
|
||||
print 'Frame', iframe, 'written.'
|
||||
if c == 'n' or continuous:
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue