Apparently the code to forestall Tk eating events was too aggressive (Tk user input...
[python/dscho.git] / Demo / sgi / video / Vrecc.py
blob6a539f8192d9e10200caead1c4a48fa0e5a91888
1 #! /ufs/guido/bin/sgi/python-405
2 #! /ufs/guido/bin/sgi/python
4 # Capture a continuous CMIF movie using the Indigo video library and board
7 # Usage:
9 # makemovie [-r rate] [-w width] [moviefile]
12 # Options:
14 # -r rate : capture 1 out of every 'rate' frames (default 1)
15 # -w width : initial window width (default interactive placement)
16 # -d : drop fields if needed
17 # -g bits : greyscale (2, 4 or 8 bits)
18 # -G : 2-bit greyscale dithered
19 # -m : monochrome dithered
20 # -M value : monochrome tresholded with value
21 # -f : Capture fields (in stead of frames)
22 # -n number : Capture 'number' fields (default 60)
24 # moviefile : here goes the movie data (default film.video);
25 # the format is documented in cmif-film.ms
28 # User interface:
30 # Start the application. Resize the window to the desired movie size.
31 # Press the left mouse button to start recording, release it to end
32 # recording. You can record as many times as you wish, but each time
33 # you overwrite the output file(s), so only the last recording is
34 # kept.
36 # Press ESC or select the window manager Quit or Close window option
37 # to quit. If you quit before recording anything, the output file(s)
38 # are not touched.
41 import sys
42 sys.path.append('/ufs/guido/src/video')
43 import sv, SV
44 import VFile
45 import gl, GL, DEVICE
46 import al, AL
47 import time
48 import posix
49 import getopt
50 import string
51 import imageop
52 import sgi
54 # Main program
56 def main():
57 format = SV.RGB8_FRAMES
58 rate = 1
59 width = 0
60 drop = 0
61 mono = 0
62 grey = 0
63 greybits = 0
64 monotreshold = -1
65 fields = 0
66 number = 60
68 opts, args = getopt.getopt(sys.argv[1:], 'r:w:dg:mM:Gfn:')
69 for opt, arg in opts:
70 if opt == '-r':
71 rate = string.atoi(arg)
72 if rate < 2:
73 sys.stderr.write('-r rate must be >= 2\n')
74 sys.exit(2)
75 elif opt == '-w':
76 width = string.atoi(arg)
77 elif opt == '-d':
78 drop = 1
79 elif opt == '-g':
80 grey = 1
81 greybits = string.atoi(arg)
82 if not greybits in (2,4,8):
83 print 'Only 2, 4 or 8 bit greyscale supported'
84 elif opt == '-G':
85 grey = 1
86 greybits = -2
87 elif opt == '-m':
88 mono = 1
89 elif opt == '-M':
90 mono = 1
91 monotreshold = string.atoi(arg)
92 elif opt == '-f':
93 fields = 1
94 elif opt == '-n':
95 number = string.atoi(arg)
97 if args[2:]:
98 sys.stderr.write('usage: Vrec [options] [file]\n')
99 sys.exit(2)
101 if args:
102 filename = args[0]
103 else:
104 filename = 'film.video'
106 v = sv.OpenVideo()
107 # Determine maximum window size based on signal standard
108 param = [SV.BROADCAST, 0]
109 v.GetParam(param)
110 if param[1] == SV.PAL:
111 x = SV.PAL_XMAX
112 y = SV.PAL_YMAX
113 elif param[1] == SV.NTSC:
114 x = SV.NTSC_XMAX
115 y = SV.NTSC_YMAX
116 else:
117 print 'Unknown video standard', param[1]
118 sys.exit(1)
120 gl.foreground()
121 gl.maxsize(x, y)
122 gl.keepaspect(x, y)
123 gl.stepunit(8, 6)
124 if width:
125 gl.prefsize(width, width*3/4)
126 win = gl.winopen(filename)
127 if width:
128 gl.maxsize(x, y)
129 gl.keepaspect(x, y)
130 gl.stepunit(8, 6)
131 gl.winconstraints()
132 x, y = gl.getsize()
133 print x, 'x', y
135 v.SetSize(x, y)
137 if drop:
138 param = [SV.FIELDDROP, 1, SV.GENLOCK, SV.GENLOCK_OFF]
139 else:
140 param = [SV.FIELDDROP, 0, SV.GENLOCK, SV.GENLOCK_ON]
141 if mono or grey:
142 param = param+[SV.COLOR, SV.MONO, SV.INPUT_BYPASS, 1]
143 else:
144 param = param+[SV.COLOR, SV.DEFAULT_COLOR, SV.INPUT_BYPASS, 0]
145 v.SetParam(param)
147 v.BindGLWindow(win, SV.IN_REPLACE)
149 gl.qdevice(DEVICE.LEFTMOUSE)
150 gl.qdevice(DEVICE.WINQUIT)
151 gl.qdevice(DEVICE.WINSHUT)
152 gl.qdevice(DEVICE.ESCKEY)
154 print 'Press left mouse to start recording'
156 while 1:
157 dev, val = gl.qread()
158 if dev == DEVICE.LEFTMOUSE:
159 if val == 1:
160 info = format, x, y, number, rate
161 record(v, info, filename, mono, grey, \
162 greybits, monotreshold, fields)
163 elif dev == DEVICE.REDRAW:
164 # Window resize (or move)
165 x, y = gl.getsize()
166 print x, 'x', y
167 v.SetSize(x, y)
168 v.BindGLWindow(win, SV.IN_REPLACE)
169 elif dev in (DEVICE.ESCKEY, DEVICE.WINQUIT, DEVICE.WINSHUT):
170 # Quit
171 v.CloseVideo()
172 gl.winclose(win)
173 break
176 # Record until the mouse is released (or any other GL event)
177 # XXX audio not yet supported
179 def record(v, info, filename, mono, grey, greybits, monotreshold, fields):
180 import thread
181 format, x, y, number, rate = info
182 fps = 59.64 # Fields per second
183 # XXX (Strange: need fps of Indigo monitor, not of PAL or NTSC!)
184 tpf = 1000.0 / fps # Time per field in msec
186 # Go grab
188 gl.wintitle('(rec) ' + filename)
189 try:
190 ninfo, data, bitvec = v.CaptureBurst(info)
191 except sv.error, arg:
192 print 'CaptureBurst failed:', arg
193 print 'info:', info
194 gl.wintitle(filename)
195 return
196 gl.wintitle('(save) '+ filename)
198 # Check results
200 if info <> ninfo:
201 print 'Sorry, format changed.'
202 print 'Wanted:',info
203 print 'Got :',ninfo
204 gl.wintitle(filename)
205 return
206 # print bitvec
207 if x*y*number <> len(data):
208 print 'Funny data length: wanted',x,'*',y,'*', number,'=',\
209 x*y*number,'got',len(data)
210 gl.wintitle(filename)
211 return
213 # Save
215 if filename:
217 # Construct header and write it
219 vout = VFile.VoutFile().init(filename)
220 if mono:
221 vout.format = 'mono'
222 elif grey and greybits == 8:
223 vout.format = 'grey'
224 elif grey:
225 vout.format = 'grey'+`abs(greybits)`
226 else:
227 vout.format = 'rgb8'
228 vout.width = x
229 vout.height = y
230 if fields:
231 vout.packfactor = (1,-2)
232 else:
233 print 'Sorry, can only save fields at the moment'
234 gl.wintitle(filename)
235 return
236 vout.writeheader()
238 # Compute convertor, if needed
240 convertor = None
241 if grey:
242 if greybits == 2:
243 convertor = imageop.grey2grey2
244 elif greybits == 4:
245 convertor = imageop.grey2grey4
246 elif greybits == -2:
247 convertor = imageop.dither2grey2
248 fieldsize = x*y/2
249 nskipped = 0
250 realframeno = 0
251 tpf = 1000 / 50.0 #XXXX
252 for frameno in range(0, number*2):
253 if frameno <> 0 and \
254 bitvec[frameno] == bitvec[frameno-1]:
255 nskipped = nskipped + 1
256 continue
258 # Save field.
259 # XXXX Works only for fields and top-to-bottom
261 start = frameno*fieldsize
262 field = data[start:start+fieldsize]
263 if convertor:
264 field = convertor(field, x, y)
265 elif mono and monotreshold >= 0:
266 field = imageop.grey2mono(field, x, y, \
267 1, monotreshold)
268 elif mono:
269 field = imageop.dither2mono(field, x, y)
270 vout.writeframe(int(realframeno*tpf), field, None)
271 print 'Skipped',nskipped,'duplicate frames'
272 vout.close()
274 gl.wintitle('(done) ' + filename)
276 # Don't forget to call the main program
278 try:
279 main()
280 except KeyboardInterrupt:
281 print '[Interrupt]'