diff --git a/Demo/sgi/video/LiveVideoIn.py b/Demo/sgi/video/LiveVideoIn.py new file mode 100755 index 00000000000..65e531774c6 --- /dev/null +++ b/Demo/sgi/video/LiveVideoIn.py @@ -0,0 +1,95 @@ +# Live video input class. +# Note that importing this module attempts to initialize video. + + +# Check if video is available. +# There are three reasons for failure here: +# (1) this version of Python may not have the sv or imageop modules; +# (2) this machine may not have a video board; +# (3) initializing the video board may fail for another reason. +# The global variable have_video is set to true iff we reall do have video. + +try: + import sv + import SV + import imageop + try: + v = sv.OpenVideo() + have_video = 1 + except sv.error: + have_video = 0 +except ImportError: + have_video = 0 + + +# The live video input class. +# Only instantiate this if have_video is true! + +class LiveVideoIn: + + # Initialize an instance. + # Parameters: + # - vw, vh specify the size of the video window. + # This initializes continuous capture. + + def init(self, pktmax, vw, vh): + if not have_video: + raise RuntimeError, 'no video available' + realvw = vh*SV.PAL_XMAX/SV.PAL_YMAX + if realvw < vw: + print 'Funny, image too narrow...' + self.realwidth, self.realheight = v.QuerySize(realvw, vh) + ##print 'Recording video in size', \ + ## self.realwidth, self.realheight + self.width = vw + self.height = vh + self.x0 = (self.realwidth-self.width)/2 + self.x1 = self.x0 + self.width - 1 + self.y0 = (self.realheight-self.height)/2 + self.y1 = self.y0 + self.height - 1 + # Compute # full lines per packet + self.lpp = pktmax / self.width + self.pktsize = self.lpp*self.width + ##print 'lpp =', self.lpp, '; pktsize =', self.pktsize + # Initialize capture + v.SetSize(self.realwidth, self.realheight) + dummy = v.InitContinuousCapture(SV.RGB8_FRAMES, \ + self.realwidth, self.realheight, 2, 5) + self.data = None + self.lpos = 0 + return self + + # Remove an instance. + # This turns off continuous capture. + + def close(self): + v.EndContinuousCapture() + + # Get the next video packet. + # This returns (lpos, data) where: + # - lpos is the line position + # - data is a piece of data + # The dimensions of data are: + # - pixel depth = 1 byte + # - scan line width = self.width (the vw argument to init()) + # - number of scan lines = self.lpp (PKTMAX / vw) + + def getnextpacket(self): + if not self.data: + try: + cd, id = v.GetCaptureData() + except sv.error: + return None + data = cd.InterleaveFields(1) + cd.UnlockCaptureData() + self.data = imageop.crop(data, 1, \ + self.realwidth, \ + self.realheight, \ + self.x0, self.y0, \ + self.x1, self.y1) + self.lpos = 0 + data = self.data[:self.pktsize] + self.data = self.data[self.pktsize:] + lpos = self.lpos + self.lpos = self.lpos + self.lpp + return lpos, data diff --git a/Demo/sgi/video/LiveVideoOut.py b/Demo/sgi/video/LiveVideoOut.py new file mode 100755 index 00000000000..d9c1138e4e2 --- /dev/null +++ b/Demo/sgi/video/LiveVideoOut.py @@ -0,0 +1,56 @@ +# Live video output (display video on the screen, presumably from the net) + +import gl +from VFile import Displayer + + +# Video output (displayer) class. + +class LiveVideoOut: + + def init(self, wid, xywh, vw, vh): + ##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) + self.disp.setinfo(info) + self.wid = wid + oldwid = gl.winget() + gl.winset(wid) + self.disp.initcolormap() + self.resize(xywh) + gl.winset(oldwid) + return self + + def resize(self, (x, y, w, h)): + oldwid = gl.winget() + gl.winset(self.wid) + ##print 'Resize', x, y, w, h + gl.winposition(x, x+w-1, y, y+h-1) + gl.reshapeviewport() + if w < self.vw or h < self.vh: + self.toosmall = 1 + else: + self.disp.xorigin = (w-self.vw)/2 + self.disp.yorigin = (h-self.vh)/2 + self.toosmall = 0 + ##print 'VIDEO OFFSET:', \ + ## self.disp.xorigin, self.disp.yorigin + self.disp.clear() + gl.winset(oldwid) + + def putnextpacket(self, pos, data): + if self.toosmall: + return + oldwid = gl.winget() + gl.winset(self.wid) + nline = len(data)/self.vw + if nline*self.vw <> len(data): + print 'Incorrect-sized video fragment' + self.disp.showpartframe(data, None, (0, pos, self.vw, nline)) + gl.winset(oldwid) + + def close(self): + print 'Done video out' diff --git a/Demo/sgi/video/Vaddcache.py b/Demo/sgi/video/Vaddcache.py index 191d6ea852e..d89a78ab8ef 100755 --- a/Demo/sgi/video/Vaddcache.py +++ b/Demo/sgi/video/Vaddcache.py @@ -10,7 +10,7 @@ # Options: # -# file ... : file(s) to inspect; default film.video +# file ... : file(s) to modify; default film.video import sys diff --git a/Demo/sgi/video/Vreceive.py b/Demo/sgi/video/Vreceive.py new file mode 100755 index 00000000000..8d7150e9ee4 --- /dev/null +++ b/Demo/sgi/video/Vreceive.py @@ -0,0 +1,74 @@ +#!/ufs/guido/bin/sgi/python-405 + +# Receive live video UDP packets. +# Usage: Vreceive [port] + +import sys +import struct +from socket import * +import select +import gl, GL, DEVICE +sys.path.append('/ufs/guido/src/video') +import LiveVideoOut + +PKTMAX = 16*1024 +WIDTH = 400 +HEIGHT = 300 +HOST = '' +PORT = 5555 + +def main(): + + port = PORT + if sys.argv[1:]: + port = eval(sys.argv[1]) + + width, height = WIDTH, HEIGHT + + gl.foreground() + gl.prefsize(width, height) + wid = gl.winopen('Vreceive') + gl.qdevice(DEVICE.ESCKEY) + gl.qdevice(DEVICE.WINSHUT) + gl.qdevice(DEVICE.WINQUIT) + + x, y = gl.getorigin() + lvo = LiveVideoOut.LiveVideoOut().init(wid, (x, y, width, height), \ + width, height) + + s = socket(AF_INET, SOCK_DGRAM) + s.bind(HOST, port) + + ifdlist = [gl.qgetfd(), s.fileno()] + ofdlist = [] + xfdlist = [] + timeout = 1.0 + selectargs = (ifdlist, ofdlist, xfdlist, timeout) + + while 1: + + if gl.qtest(): + dev, val = gl.qread() + if dev in (DEVICE.ESCKEY, \ + DEVICE.WINSHUT, DEVICE.WINQUIT): + break + if dev == DEVICE.REDRAW: + gl.clear() + elif s.avail(): + data = s.recv(16*1024) + pos, w, h = struct.unpack('hhh', data[:6]) + if (w, h) <> (width, height): + x, y = gl.getorigin() + y = y + height - h + width, height = w, h + lvo.close() + lvo = LiveVideoOut.LiveVideoOut() \ + .init(wid, (x, y, width, height), \ + width, height) + lvo.putnextpacket(pos, data[6:]) + else: + x = select.select(selectargs) + + lvo.close() + +main() diff --git a/Demo/sgi/video/Vsend.py b/Demo/sgi/video/Vsend.py new file mode 100755 index 00000000000..32385f0f9c1 --- /dev/null +++ b/Demo/sgi/video/Vsend.py @@ -0,0 +1,94 @@ +#!/ufs/guido/bin/sgi/python-405 + +# Send live video UDP packets. +# Usage: Vsend [host [port]] + +import sys +import time +import struct +from socket import * +import gl, GL, DEVICE +sys.path.append('/ufs/guido/src/video') +import LiveVideoIn +import LiveVideoOut + +PKTMAX_UCAST = 16*1024 - 6 +PKTMAX_BCAST = 1450 +WIDTH = 400 +HEIGHT = 300 +HOST = '' +PORT = 5555 + +def main(): + if not LiveVideoIn.have_video: + print 'Sorry, no video (use python-405 on roos)' + sys.exit(1) + + host = HOST + port = PORT + if sys.argv[1:]: + host = sys.argv[1] + if sys.argv[2:]: + port = eval(sys.argv[2]) + + if host == '': + pktmax = PKTMAX_BCAST + else: + pktmax = PKTMAX_UCAST + + gl.foreground() + gl.prefsize(WIDTH, HEIGHT) + wid = gl.winopen('Vsend') + gl.keepaspect(WIDTH, HEIGHT) + gl.stepunit(8, 6) + gl.winconstraints() + gl.qdevice(DEVICE.ESCKEY) + gl.qdevice(DEVICE.WINSHUT) + gl.qdevice(DEVICE.WINQUIT) + width, height = gl.getsize() + + x, y = gl.getorigin() + lvo = LiveVideoOut.LiveVideoOut().init(wid, (x, y, width, height), \ + width, height) + + lvi = LiveVideoIn.LiveVideoIn().init(pktmax, width, height) + + s = socket(AF_INET, SOCK_DGRAM) + s.allowbroadcast(1) + + while 1: + + if gl.qtest(): + dev, val = gl.qread() + if dev in (DEVICE.ESCKEY, \ + DEVICE.WINSHUT, DEVICE.WINQUIT): + break + if dev == DEVICE.REDRAW: + w, h = gl.getsize() + x, y = gl.getorigin() + if (w, h) <> (width, height): + lvi.close() + width, height = w, h + lvi = LiveVideoIn.LiveVideoIn() \ + .init(pktmax, width, height) + lvo.close() + lvo = LiveVideoOut.LiveVideoOut() \ + .init(wid, \ + (x, y, width, height), \ + width, height) + + rv = lvi.getnextpacket() + if not rv: + time.millisleep(10) + continue + + pos, data = rv + lvo.putnextpacket(pos, data) + + hdr = struct.pack('hhh', pos, width, height) + s.sendto(hdr + data, (host, port)) + + lvi.close() + lvo.close() + +main()