blob: 2dcbe8ea3075e5cc74490a634b4ecd8d55570e1a [file] [log] [blame]
Guido van Rossum6e0e6681992-12-23 15:41:38 +00001#! /ufs/guido/bin/sgi/python-405
2#! /ufs/guido/bin/sgi/python
3
Guido van Rossum3f2ef091993-02-05 15:34:22 +00004# Capture a CMIF movie using the Indigo video library and board in burst mode
Guido van Rossum6e0e6681992-12-23 15:41:38 +00005
6
7# User interface:
8#
9# Start the application. Resize the window to the desired movie size.
10# Press the left mouse button to start recording, release it to end
11# recording. You can record as many times as you wish, but each time
12# you overwrite the output file(s), so only the last recording is
13# kept.
14#
15# Press ESC or select the window manager Quit or Close window option
16# to quit. If you quit before recording anything, the output file(s)
17# are not touched.
18
19
20import sys
21sys.path.append('/ufs/guido/src/video')
22import sv, SV
23import VFile
24import gl, GL, DEVICE
25import al, AL
26import time
27import posix
28import getopt
29import string
30import imageop
31import sgi
32
Guido van Rossum3f2ef091993-02-05 15:34:22 +000033
34# Usage and help functions (keep this up-to-date if you change the program!)
35
36def usage():
37 print 'Usage: Vrecb [options] [moviefile]'
38 print
39 print 'Options:'
40 print '-r rate : capture 1 out of every "rate" frames', \
41 '(default and min 1)'
42 print '-w width : initial window width', \
43 '(default interactive placement)'
44 print '-d : drop fields if needed'
45 print '-g bits : greyscale (2, 4 or 8 bits)'
46 print '-G : 2-bit greyscale dithered'
47 print '-m : monochrome dithered'
48 print '-M value : monochrome tresholded with value'
49 print '-f : Capture fields (instead of frames)'
50 print '-n number : Capture this many frames (default 60)'
51 print 'moviefile : here goes the movie data (default film.video)'
52
53def help():
54 print 'Press the left mouse button to start recording.'
55 print 'Recording time is determined by the -n option.'
56 print 'You can record as many times as you wish, but each'
57 print 'recording overwrites the output file(s) -- only the'
58 print 'last recording is kept.'
59 print
60 print 'Press ESC or use the window manager Quit or Close window option'
61 print 'to quit. If you quit before recording anything, the output'
62 print 'file(s) are not touched.'
63
64
Guido van Rossum6e0e6681992-12-23 15:41:38 +000065# Main program
66
67def main():
68 format = SV.RGB8_FRAMES
69 rate = 1
70 width = 0
71 drop = 0
72 mono = 0
73 grey = 0
74 greybits = 0
75 monotreshold = -1
76 fields = 0
77 number = 60
78
Guido van Rossum3f2ef091993-02-05 15:34:22 +000079 try:
80 opts, args = getopt.getopt(sys.argv[1:], 'r:w:dg:mM:Gfn:')
81 except getopt.error, msg:
82 sys.stdout = sys.stderr
83 print 'Error:', msg, '\n'
84 usage()
85 sys.exit(2)
86
87 try:
88 for opt, arg in opts:
89 if opt == '-r':
90 rate = string.atoi(arg)
91 if rate < 1:
92 sys.stderr.write('-r rate must be >= 1\n')
93 sys.exit(2)
94 elif opt == '-w':
95 width = string.atoi(arg)
96 elif opt == '-d':
97 drop = 1
98 elif opt == '-g':
99 grey = 1
100 greybits = string.atoi(arg)
101 if not greybits in (2,4,8):
102 sys.stderr.write( \
103 'Only 2, 4 or 8 bit greyscale supported\n')
104 sys.exit(2)
105 elif opt == '-G':
106 grey = 1
107 greybits = -2
108 elif opt == '-m':
109 mono = 1
110 elif opt == '-M':
111 mono = 1
112 monotreshold = string.atoi(arg)
113 elif opt == '-f':
114 fields = 1
115 elif opt == '-n':
116 number = string.atoi(arg)
117 except string.atoi_error:
118 sys.stdout = sys.stderr
119 print 'Option', opt, 'requires integer argument'
120 sys.exit(2)
121
122 if not fields:
123 print '-f option assumed until Jack fixes it'
124 fields = 1
Guido van Rossum6e0e6681992-12-23 15:41:38 +0000125
126 if args[2:]:
Guido van Rossum3f2ef091993-02-05 15:34:22 +0000127 sys.stderr.write('usage: Vrecb [options] [file]\n')
Guido van Rossum6e0e6681992-12-23 15:41:38 +0000128 sys.exit(2)
129
130 if args:
131 filename = args[0]
132 else:
133 filename = 'film.video'
134
135 v = sv.OpenVideo()
136 # Determine maximum window size based on signal standard
137 param = [SV.BROADCAST, 0]
138 v.GetParam(param)
139 if param[1] == SV.PAL:
140 x = SV.PAL_XMAX
141 y = SV.PAL_YMAX
142 elif param[1] == SV.NTSC:
143 x = SV.NTSC_XMAX
144 y = SV.NTSC_YMAX
145 else:
146 print 'Unknown video standard', param[1]
147 sys.exit(1)
148
149 gl.foreground()
150 gl.maxsize(x, y)
151 gl.keepaspect(x, y)
152 gl.stepunit(8, 6)
153 if width:
154 gl.prefsize(width, width*3/4)
155 win = gl.winopen(filename)
156 if width:
157 gl.maxsize(x, y)
158 gl.keepaspect(x, y)
159 gl.stepunit(8, 6)
160 gl.winconstraints()
161 x, y = gl.getsize()
162 print x, 'x', y
163
164 v.SetSize(x, y)
165
166 if drop:
167 param = [SV.FIELDDROP, 1, SV.GENLOCK, SV.GENLOCK_OFF]
168 else:
169 param = [SV.FIELDDROP, 0, SV.GENLOCK, SV.GENLOCK_ON]
170 if mono or grey:
171 param = param+[SV.COLOR, SV.MONO, SV.INPUT_BYPASS, 1]
172 else:
173 param = param+[SV.COLOR, SV.DEFAULT_COLOR, SV.INPUT_BYPASS, 0]
174 v.SetParam(param)
175
176 v.BindGLWindow(win, SV.IN_REPLACE)
177
178 gl.qdevice(DEVICE.LEFTMOUSE)
179 gl.qdevice(DEVICE.WINQUIT)
180 gl.qdevice(DEVICE.WINSHUT)
181 gl.qdevice(DEVICE.ESCKEY)
182
Guido van Rossum3f2ef091993-02-05 15:34:22 +0000183 help()
Guido van Rossum6e0e6681992-12-23 15:41:38 +0000184
185 while 1:
186 dev, val = gl.qread()
187 if dev == DEVICE.LEFTMOUSE:
188 if val == 1:
189 info = format, x, y, number, rate
190 record(v, info, filename, mono, grey, \
191 greybits, monotreshold, fields)
192 elif dev == DEVICE.REDRAW:
193 # Window resize (or move)
194 x, y = gl.getsize()
195 print x, 'x', y
196 v.SetSize(x, y)
197 v.BindGLWindow(win, SV.IN_REPLACE)
198 elif dev in (DEVICE.ESCKEY, DEVICE.WINQUIT, DEVICE.WINSHUT):
199 # Quit
200 v.CloseVideo()
201 gl.winclose(win)
202 break
203
204
205# Record until the mouse is released (or any other GL event)
206# XXX audio not yet supported
207
208def record(v, info, filename, mono, grey, greybits, monotreshold, fields):
209 import thread
210 format, x, y, number, rate = info
211 fps = 59.64 # Fields per second
212 # XXX (Strange: need fps of Indigo monitor, not of PAL or NTSC!)
213 tpf = 1000.0 / fps # Time per field in msec
214 #
215 # Go grab
216 #
217 gl.wintitle('(rec) ' + filename)
218 try:
219 ninfo, data, bitvec = v.CaptureBurst(info)
220 except sv.error, arg:
221 print 'CaptureBurst failed:', arg
222 print 'info:', info
223 gl.wintitle(filename)
224 return
225 gl.wintitle('(save) '+ filename)
226 #
227 # Check results
228 #
229 if info <> ninfo:
230 print 'Sorry, format changed.'
231 print 'Wanted:',info
232 print 'Got :',ninfo
233 gl.wintitle(filename)
234 return
235 # print bitvec
236 if x*y*number <> len(data):
237 print 'Funny data length: wanted',x,'*',y,'*', number,'=',\
238 x*y*number,'got',len(data)
239 gl.wintitle(filename)
240 return
241 #
242 # Save
243 #
244 if filename:
245 #
246 # Construct header and write it
247 #
Guido van Rossum852cc221993-02-15 17:33:36 +0000248 try:
249 vout = VFile.VoutFile().init(filename)
250 except IOError, msg:
251 print filename, ':', msg
252 sys.exit(1)
Guido van Rossum6e0e6681992-12-23 15:41:38 +0000253 if mono:
254 vout.format = 'mono'
255 elif grey and greybits == 8:
256 vout.format = 'grey'
257 elif grey:
258 vout.format = 'grey'+`abs(greybits)`
259 else:
260 vout.format = 'rgb8'
261 vout.width = x
262 vout.height = y
263 if fields:
264 vout.packfactor = (1,-2)
265 else:
266 print 'Sorry, can only save fields at the moment'
Guido van Rossum3f2ef091993-02-05 15:34:22 +0000267 print '(i.e. you *must* use the -f option)'
Guido van Rossum6e0e6681992-12-23 15:41:38 +0000268 gl.wintitle(filename)
269 return
270 vout.writeheader()
271 #
272 # Compute convertor, if needed
273 #
274 convertor = None
275 if grey:
276 if greybits == 2:
277 convertor = imageop.grey2grey2
278 elif greybits == 4:
279 convertor = imageop.grey2grey4
280 elif greybits == -2:
281 convertor = imageop.dither2grey2
282 fieldsize = x*y/2
283 nskipped = 0
284 realframeno = 0
285 tpf = 1000 / 50.0 #XXXX
286 for frameno in range(0, number*2):
287 if frameno <> 0 and \
288 bitvec[frameno] == bitvec[frameno-1]:
289 nskipped = nskipped + 1
290 continue
291 #
292 # Save field.
293 # XXXX Works only for fields and top-to-bottom
294 #
295 start = frameno*fieldsize
296 field = data[start:start+fieldsize]
297 if convertor:
Guido van Rossum852cc221993-02-15 17:33:36 +0000298 field = convertor(field, len(field), 1)
Guido van Rossum6e0e6681992-12-23 15:41:38 +0000299 elif mono and monotreshold >= 0:
Guido van Rossum852cc221993-02-15 17:33:36 +0000300 field = imageop.grey2mono( \
301 field, len(field), 1, monotreshold)
Guido van Rossum6e0e6681992-12-23 15:41:38 +0000302 elif mono:
Guido van Rossum852cc221993-02-15 17:33:36 +0000303 field = imageop.dither2mono( \
304 field, len(field), 1)
Guido van Rossum6e0e6681992-12-23 15:41:38 +0000305 vout.writeframe(int(realframeno*tpf), field, None)
Guido van Rossum852cc221993-02-15 17:33:36 +0000306 realframeno = realframeno + 1
Guido van Rossum6e0e6681992-12-23 15:41:38 +0000307 print 'Skipped',nskipped,'duplicate frames'
308 vout.close()
309
310 gl.wintitle('(done) ' + filename)
311
312# Don't forget to call the main program
313
314try:
315 main()
316except KeyboardInterrupt:
317 print '[Interrupt]'