blob: 160ef3d433093831a236ce8026479b387e898e11 [file] [log] [blame]
Guido van Rossumb7e3cc11993-05-06 16:06:44 +00001#! /ufs/guido/bin/sgi/python
2
Guido van Rossum9f42f4f1993-05-10 15:07:20 +00003# Video bag of tricks: record video(+audio) in various formats and modes
Guido van Rossumb7e3cc11993-05-06 16:06:44 +00004
Guido van Rossumc5a14331993-05-07 11:20:07 +00005# XXX To do:
6# - audio
Guido van Rossumc5a14331993-05-07 11:20:07 +00007# - improve user interface
8# - help button?
9# - command line options to set initial settings
10# - save settings in a file
11# - ...?
Guido van Rossumbc6d3c31993-05-07 09:37:42 +000012
Guido van Rossumb7e3cc11993-05-06 16:06:44 +000013import sys
Guido van Rossum9f42f4f1993-05-10 15:07:20 +000014import time
Guido van Rossumb7e3cc11993-05-06 16:06:44 +000015import getopt
16import string
17import os
Guido van Rossumc5a14331993-05-07 11:20:07 +000018sts = os.system('makemap') # Must be before "import fl" to work
Guido van Rossumb7e3cc11993-05-06 16:06:44 +000019import sgi
20import gl
21import GL
22import DEVICE
23import fl
24import FL
25import flp
26import watchcursor
27import sv
28import SV
29import VFile
30import VGrabber
31import imageop
Guido van Rossum9f42f4f1993-05-10 15:07:20 +000032sys.path.append('/ufs/jack/src/av/vcr')
Guido van Rossumf6d80321993-06-10 13:40:51 +000033import VCR
Guido van Rossumb7e3cc11993-05-06 16:06:44 +000034
35ARROW = 0
36WATCH = 1
37watchcursor.defwatch(WATCH)
38
39def main():
Guido van Rossumc5a14331993-05-07 11:20:07 +000040## fl.set_graphics_mode(0, 1)
Guido van Rossumb7e3cc11993-05-06 16:06:44 +000041 vb = VideoBagOfTricks().init()
42 while 1:
43 dummy = fl.do_forms()
44 [dummy]
45
46StopCapture = 'StopCapture'
47
Guido van Rossum9f42f4f1993-05-10 15:07:20 +000048VideoFormatLabels = ['Video off', 'rgb8', 'grey8', 'grey4', 'grey2', \
Jack Jansen672754a1993-06-08 12:52:41 +000049 'grey2 dith', 'mono dith', 'mono thresh', 'rgb24', 'rgb24-jpeg']
Guido van Rossum9f42f4f1993-05-10 15:07:20 +000050VideoFormats = ['', 'rgb8', 'grey', 'grey4', 'grey2', \
Jack Jansen672754a1993-06-08 12:52:41 +000051 'grey2', 'mono', 'mono', 'rgb', 'jpeg']
Guido van Rossum9f42f4f1993-05-10 15:07:20 +000052
53VideoModeLabels = ['Continuous', 'Burst', 'Single frame', 'VCR sync']
54[VM_CONT, VM_BURST, VM_SINGLE, VM_VCR] = range(1, 5)
55
56AudioFormatLabels = ['Audio off', \
57 '16 bit mono', '16 bit stereo', '8 bit mono', '8 bit stereo']
58[A_OFF, A_16_MONO, A_16_STEREO, A_8_MONO, A_8_STEREO] = range(1, 6)
Guido van Rossumb7e3cc11993-05-06 16:06:44 +000059
Jack Jansen672754a1993-06-08 12:52:41 +000060VcrSpeedLabels = ['normal', '1/3', '1/5', '1/10', '1/30', 'single-step']
61VcrSpeeds = [None, 5, 4, 3, 2, 1, 0]
62
63RgbSizeLabels = ['full', 'quarter', 'sixteenth']
64
Guido van Rossumb7e3cc11993-05-06 16:06:44 +000065class VideoBagOfTricks:
66
Guido van Rossum9f42f4f1993-05-10 15:07:20 +000067 # Init/close stuff
68
Guido van Rossumb7e3cc11993-05-06 16:06:44 +000069 def init(self):
Jack Jansen672754a1993-06-08 12:52:41 +000070 self.window = None
Guido van Rossumb7e3cc11993-05-06 16:06:44 +000071 formdef = flp.parse_form('VbForm', 'form')
72 flp.create_full_form(self, formdef)
Guido van Rossum9f42f4f1993-05-10 15:07:20 +000073 self.g_cont.hide_object()
Guido van Rossumc5a14331993-05-07 11:20:07 +000074 self.g_burst.hide_object()
Guido van Rossum9f42f4f1993-05-10 15:07:20 +000075 self.g_single.hide_object()
76 self.g_vcr.hide_object()
Guido van Rossumb7e3cc11993-05-06 16:06:44 +000077 self.setdefaults()
78 self.openvideo()
79 self.makewindow()
80 self.bindvideo()
Guido van Rossumc5a14331993-05-07 11:20:07 +000081 self.showform()
Guido van Rossumb7e3cc11993-05-06 16:06:44 +000082 fl.set_event_call_back(self.do_event)
83 return self
84
Guido van Rossum9f42f4f1993-05-10 15:07:20 +000085 def close(self):
86 self.close_video()
87 self.close_audio()
88 raise SystemExit, 0
89
Guido van Rossumc5a14331993-05-07 11:20:07 +000090 def showform(self):
91 # Get position of video window
92 gl.winset(self.window)
93 x, y = gl.getorigin()
94 width, height = gl.getsize()
95 # Calculate position of form window
96 x1 = x + width + 10
97 x2 = x1 + int(self.form.w) - 1
98 y2 = y + height - 1
99 y1 = y2 - int(self.form.h) + 1
100 # Position and show form window
101 gl.prefposition(x1, x2, y1, y2)
102 self.form.show_form(FL.PLACE_FREE, FL.TRUE, \
103 'Video Bag Of Tricks')
104
Guido van Rossumb7e3cc11993-05-06 16:06:44 +0000105 def setdefaults(self):
Guido van Rossum9f42f4f1993-05-10 15:07:20 +0000106 self.vcr = None
107 self.vout = None
108 self.capturing = 0
109 # Video defaults
110 self.vfile = 'film.video'
111 self.vmode = VM_CONT
Guido van Rossumbc6d3c31993-05-07 09:37:42 +0000112 self.mono_thresh = 128
Guido van Rossum9f42f4f1993-05-10 15:07:20 +0000113 self.vformat = 'rgb8'
114 self.c_vformat.clear_choice()
115 for label in VideoFormatLabels:
116 self.c_vformat.addto_choice(label)
117 self.c_vformat.set_choice(1 + VideoFormats.index(self.vformat))
118 self.c_vmode.clear_choice()
119 for label in VideoModeLabels:
120 self.c_vmode.addto_choice(label)
121 self.c_vmode.set_choice(self.vmode)
122 self.get_vformat()
Guido van Rossumb7e3cc11993-05-06 16:06:44 +0000123 self.b_drop.set_button(1)
Guido van Rossumb7e3cc11993-05-06 16:06:44 +0000124 self.in_rate.set_input('2')
125 self.in_maxmem.set_input('1.0')
126 self.in_nframes.set_input('0')
Guido van Rossum9f42f4f1993-05-10 15:07:20 +0000127 self.in_nframes_vcr.set_input('1')
Guido van Rossumad4fcd41993-05-11 18:36:54 +0000128 self.in_rate_vcr.set_input('1')
Jack Jansen672754a1993-06-08 12:52:41 +0000129 self.c_vcrspeed.clear_choice()
130 for label in VcrSpeedLabels:
131 self.c_vcrspeed.addto_choice(label)
132 self.c_vcrspeed.set_choice(4)
133 self.c_rgb24_size.clear_choice()
134 for label in RgbSizeLabels:
135 self.c_rgb24_size.addto_choice(label)
136 self.c_rgb24_size.set_choice(1)
137 self.rgb24_size = 1
Guido van Rossum9f42f4f1993-05-10 15:07:20 +0000138 # Audio defaults
139 self.aout = None
140 self.aport = None
141 self.afile = 'film.aiff'
142 self.aformat = A_OFF
143 self.c_aformat.clear_choice()
144 for label in AudioFormatLabels:
145 self.c_aformat.addto_choice(label)
146 self.c_aformat.set_choice(self.aformat)
147 self.get_aformat()
Guido van Rossumb7e3cc11993-05-06 16:06:44 +0000148
149 def openvideo(self):
Guido van Rossumbc6d3c31993-05-07 09:37:42 +0000150 try:
151 self.video = sv.OpenVideo()
152 except sv.error, msg:
153 print 'Error opening video:', msg
154 self.video = None
Guido van Rossumbc6d3c31993-05-07 09:37:42 +0000155 param = [SV.BROADCAST, SV.PAL]
156 if self.video: self.video.GetParam(param)
Guido van Rossumb7e3cc11993-05-06 16:06:44 +0000157 if param[1] == SV.PAL:
158 x = SV.PAL_XMAX
159 y = SV.PAL_YMAX
160 elif param[1] == SV.NTSC:
161 x = SV.NTSC_XMAX
162 y = SV.NTSC_YMAX
163 else:
164 print 'Unknown video standard:', param[1]
165 sys.exit(1)
166 self.maxx, self.maxy = x, y
167
168 def makewindow(self):
169 x, y = self.maxx, self.maxy
170 gl.foreground()
171 gl.maxsize(x, y)
172 gl.keepaspect(x, y)
173 gl.stepunit(8, 6)
174 width = 256 # XXX
175 if width:
176 height = width*3/4
177 x1 = 150
178 x2 = x1 + width-1
179 y2 = 768-150
180 y1 = y2-height+1
181 gl.prefposition(x1, x2, y1, y2)
182 self.window = gl.winopen('Vb: initializing')
183 self.settitle()
184 if width:
185 gl.maxsize(x, y)
186 gl.keepaspect(x, y)
187 gl.stepunit(8, 6)
188 gl.winconstraints()
189 gl.qdevice(DEVICE.LEFTMOUSE)
190 gl.qdevice(DEVICE.WINQUIT)
191 gl.qdevice(DEVICE.WINSHUT)
192
Jack Jansen672754a1993-06-08 12:52:41 +0000193 def optfullsizewindow(self):
194 if not self.window:
195 return
196 gl.winset(self.window)
197 if not self.use_24:
198 gl.winconstraints()
199 return
200 gl.prefsize(self.maxx, self.maxy)
201 gl.winconstraints()
202 self.bindvideo()
203
Guido van Rossumb7e3cc11993-05-06 16:06:44 +0000204 def bindvideo(self):
Guido van Rossumbc6d3c31993-05-07 09:37:42 +0000205 if not self.video: return
Guido van Rossumb7e3cc11993-05-06 16:06:44 +0000206 x, y = gl.getsize()
207 self.video.SetSize(x, y)
208 drop = self.b_drop.get_button()
209 if drop:
210 param = [SV.FIELDDROP, 1, SV.GENLOCK, SV.GENLOCK_OFF]
211 else:
212 param = [SV.FIELDDROP, 0, SV.GENLOCK, SV.GENLOCK_ON]
Guido van Rossumbc6d3c31993-05-07 09:37:42 +0000213 if self.rgb:
Guido van Rossumb7e3cc11993-05-06 16:06:44 +0000214 param = param+[SV.COLOR, SV.DEFAULT_COLOR, \
215 SV.DITHER, 1, \
216 SV.INPUT_BYPASS, 0]
217 else:
218 param = param+[SV.COLOR, SV.MONO, SV.DITHER, 0, \
219 SV.INPUT_BYPASS, 1]
220 self.video.BindGLWindow(self.window, SV.IN_REPLACE)
221 self.video.SetParam(param)
222
223 def rebindvideo(self):
224 gl.winset(self.window)
225 self.bindvideo()
226
Guido van Rossum9f42f4f1993-05-10 15:07:20 +0000227 def reset(self):
228 self.close_video()
229 self.close_audio()
Guido van Rossumad4fcd41993-05-11 18:36:54 +0000230 if self.vcr:
231 try:
232 ok = self.vcr.still()
233 except VCR.error:
234 pass
235 self.vcr = None
236 self.b_capture.set_button(0)
Guido van Rossum9f42f4f1993-05-10 15:07:20 +0000237
238 # Event handler (catches resize of video window)
239
Guido van Rossumb7e3cc11993-05-06 16:06:44 +0000240 def do_event(self, dev, val):
241 #print 'Event:', dev, val
242 if dev in (DEVICE.WINSHUT, DEVICE.WINQUIT):
Guido van Rossum9f42f4f1993-05-10 15:07:20 +0000243 self.close()
Guido van Rossumb7e3cc11993-05-06 16:06:44 +0000244 if dev == DEVICE.REDRAW and val == self.window:
245 self.rebindvideo()
246 self.settitle()
247
Guido van Rossum9f42f4f1993-05-10 15:07:20 +0000248 # Video controls: format, mode, file
249
250 def cb_vformat(self, *args):
251 self.reset()
252 self.get_vformat()
Guido van Rossumbc6d3c31993-05-07 09:37:42 +0000253 if self.mono_use_thresh:
Guido van Rossumb7e3cc11993-05-06 16:06:44 +0000254 s = `self.mono_thresh`
255 s = fl.show_input('Please enter mono threshold', s)
256 if s:
257 try:
258 self.mono_thresh = string.atoi(s)
259 except string.atoi_error:
Guido van Rossumbc6d3c31993-05-07 09:37:42 +0000260 fl.show_message('Bad input, using', \
261 `self.mono_thresh`, '')
Guido van Rossumb7e3cc11993-05-06 16:06:44 +0000262 self.rebindvideo()
263
Guido van Rossum9f42f4f1993-05-10 15:07:20 +0000264 def cb_vmode(self, *args):
Guido van Rossumc17c84f1993-05-10 15:45:49 +0000265 if self.vcr:
266 self.vcr = None
Guido van Rossum9f42f4f1993-05-10 15:07:20 +0000267 self.vmode = self.c_vmode.get_choice()
268 self.form.freeze_form()
269 self.g_cont.hide_object()
270 self.g_burst.hide_object()
271 self.g_single.hide_object()
272 self.g_vcr.hide_object()
273 if self.vmode == VM_CONT:
274 self.g_cont.show_object()
275 elif self.vmode == VM_BURST:
276 self.g_burst.show_object()
277 elif self.vmode == VM_SINGLE:
278 self.g_single.show_object()
279 elif self.vmode == VM_VCR:
280 self.g_vcr.show_object()
281 self.form.unfreeze_form()
282
283 def cb_vfile(self, *args):
284 filename = self.vfile
285 hd, tl = os.path.split(filename)
286 filename = fl.file_selector('Video save file:', hd, '', tl)
287 if filename:
288 self.reset()
289 hd, tl = os.path.split(filename)
290 if hd == os.getcwd():
291 filename = tl
292 self.vfile = filename
293
294 # Video mode specific video controls
295
Guido van Rossumb7e3cc11993-05-06 16:06:44 +0000296 def cb_rate(self, *args):
297 pass
298
299 def cb_drop(self, *args):
300 self.rebindvideo()
301
Guido van Rossumb7e3cc11993-05-06 16:06:44 +0000302 def cb_maxmem(self, *args):
303 pass
304
305 def cb_nframes(self, *args):
306 pass
307
Guido van Rossum9f42f4f1993-05-10 15:07:20 +0000308 def cb_fps(self, *args):
309 pass
Guido van Rossumb7e3cc11993-05-06 16:06:44 +0000310
Guido van Rossum9f42f4f1993-05-10 15:07:20 +0000311 def cb_nframes_vcr(self, *args):
312 pass
313
Guido van Rossumad4fcd41993-05-11 18:36:54 +0000314 def cb_rate_vcr(self, *args):
Guido van Rossum9f42f4f1993-05-10 15:07:20 +0000315 pass
316
Jack Jansen672754a1993-06-08 12:52:41 +0000317 def cb_vcrspeed(self, *args):
318 pass
319
320 def cb_rgb24_size(self, *args):
321 i = self.c_rgb24_size.get_choice()
322 if i:
323 self.rgb24_size = i
324
Guido van Rossum9f42f4f1993-05-10 15:07:20 +0000325 # Audio controls: format, file
326
327 def cb_aformat(self, *args):
328 self.get_aformat()
329
330 def cb_afile(self, *args):
331 filename = self.afile
Guido van Rossumb7e3cc11993-05-06 16:06:44 +0000332 hd, tl = os.path.split(filename)
Guido van Rossum9f42f4f1993-05-10 15:07:20 +0000333 filename = fl.file_selector('Audio save file:', hd, '', tl)
Guido van Rossumb7e3cc11993-05-06 16:06:44 +0000334 if filename:
Guido van Rossum9f42f4f1993-05-10 15:07:20 +0000335 self.reset()
Guido van Rossumb7e3cc11993-05-06 16:06:44 +0000336 hd, tl = os.path.split(filename)
337 if hd == os.getcwd():
338 filename = tl
Guido van Rossum9f42f4f1993-05-10 15:07:20 +0000339 self.afile = filename
340
341 # General controls: capture, reset, play, quit
Guido van Rossumb7e3cc11993-05-06 16:06:44 +0000342
Guido van Rossumb7e3cc11993-05-06 16:06:44 +0000343 def cb_capture(self, *args):
Guido van Rossumc5a14331993-05-07 11:20:07 +0000344 if self.capturing:
345 raise StopCapture
Guido van Rossum9f42f4f1993-05-10 15:07:20 +0000346 if not self.b_capture.get_button():
347 return
348 if not self.video or not self.vformat:
349 gl.ringbell()
350 return
351 if self.vmode == VM_CONT:
352 self.cont_capture()
353 elif self.vmode == VM_BURST:
354 self.burst_capture()
355 elif self.vmode == VM_SINGLE:
Jack Jansen672754a1993-06-08 12:52:41 +0000356 self.single_capture(None, None)
Guido van Rossum9f42f4f1993-05-10 15:07:20 +0000357 elif self.vmode == VM_VCR:
358 self.vcr_capture()
359
360 def cb_reset(self, *args):
361 self.reset()
Guido van Rossumc5a14331993-05-07 11:20:07 +0000362
363 def cb_play(self, *args):
Guido van Rossumad4fcd41993-05-11 18:36:54 +0000364 self.reset()
Guido van Rossum9f42f4f1993-05-10 15:07:20 +0000365 sts = os.system('Vplay -q ' + self.vfile + ' &')
Guido van Rossumc5a14331993-05-07 11:20:07 +0000366
367 def cb_quit(self, *args):
Guido van Rossum9f42f4f1993-05-10 15:07:20 +0000368 self.close()
369
370 # Capture routines
Guido van Rossumc5a14331993-05-07 11:20:07 +0000371
Guido van Rossumbc6d3c31993-05-07 09:37:42 +0000372 def burst_capture(self):
Guido van Rossumb7e3cc11993-05-06 16:06:44 +0000373 self.setwatch()
Guido van Rossumb7e3cc11993-05-06 16:06:44 +0000374 gl.winset(self.window)
375 x, y = gl.getsize()
Jack Jansen672754a1993-06-08 12:52:41 +0000376 if self.use_24:
377 fl.show_message('Sorry, no 24 bit continuous capture yet', '', '')
378 return
Guido van Rossumb7e3cc11993-05-06 16:06:44 +0000379 vformat = SV.RGB8_FRAMES
Guido van Rossum9f42f4f1993-05-10 15:07:20 +0000380 nframes = self.getint(self.in_nframes, 0)
Guido van Rossumbc6d3c31993-05-07 09:37:42 +0000381 if nframes == 0:
Guido van Rossum9f42f4f1993-05-10 15:07:20 +0000382 maxmem = self.getint(self.in_maxmem, 1.0)
Guido van Rossumbc6d3c31993-05-07 09:37:42 +0000383 memsize = int(maxmem * 1024 * 1024)
Guido van Rossum9f42f4f1993-05-10 15:07:20 +0000384 nframes = self.calcnframes()
385 info = (vformat, x, y, nframes, 1)
Guido van Rossumbc6d3c31993-05-07 09:37:42 +0000386 try:
387 info2, data, bitvec = self.video.CaptureBurst(info)
388 except sv.error, msg:
Guido van Rossum9f42f4f1993-05-10 15:07:20 +0000389 self.b_capture.set_button(0)
Guido van Rossumbc6d3c31993-05-07 09:37:42 +0000390 self.setarrow()
Guido van Rossum9f42f4f1993-05-10 15:07:20 +0000391 fl.show_message('Capture error:', str(msg), '')
Guido van Rossumbc6d3c31993-05-07 09:37:42 +0000392 return
Guido van Rossumc5a14331993-05-07 11:20:07 +0000393 if info <> info2: print info, '<>', info2
Guido van Rossumbc6d3c31993-05-07 09:37:42 +0000394 self.save_burst(info2, data, bitvec)
395 self.setarrow()
396
Guido van Rossum9f42f4f1993-05-10 15:07:20 +0000397 def calcnframes(self):
398 gl.winset(self.window)
399 x, y = gl.getsize()
400 pixels = x*y
401 pixels = pixels/2 # XXX always assume fields
402 if self.mono or self.grey:
403 n = memsize/pixels
404 else:
405 n = memsize/(4*pixels)
406 return max(1, n)
407
Guido van Rossumbc6d3c31993-05-07 09:37:42 +0000408 def save_burst(self, info, data, bitvec):
409 (vformat, x, y, nframes, rate) = info
Guido van Rossum9f42f4f1993-05-10 15:07:20 +0000410 self.open_if_closed()
Guido van Rossumbc6d3c31993-05-07 09:37:42 +0000411 fieldsize = x*y/2
412 nskipped = 0
413 realframeno = 0
Guido van Rossum9f42f4f1993-05-10 15:07:20 +0000414 tpf = 1000 / 50.0 # XXX
Guido van Rossumbc6d3c31993-05-07 09:37:42 +0000415 for frameno in range(0, nframes*2):
416 if frameno <> 0 and \
417 bitvec[frameno] == bitvec[frameno-1]:
418 nskipped = nskipped + 1
Guido van Rossumbc6d3c31993-05-07 09:37:42 +0000419 continue
Guido van Rossumbc6d3c31993-05-07 09:37:42 +0000420 #
421 # Save field.
Guido van Rossum9f42f4f1993-05-10 15:07:20 +0000422 # XXX Works only for fields and top-to-bottom
Guido van Rossumbc6d3c31993-05-07 09:37:42 +0000423 #
424 start = frameno*fieldsize
425 field = data[start:start+fieldsize]
426 realframeno = realframeno + 1
427 fn = int(realframeno*tpf)
428 if not self.write_frame(fn, field):
429 break
Guido van Rossumbc6d3c31993-05-07 09:37:42 +0000430
431 def cont_capture(self):
Guido van Rossum9f42f4f1993-05-10 15:07:20 +0000432 saved_label = self.b_capture.label
433 self.b_capture.label = 'Stop\n' + saved_label
434 self.open_if_closed()
435 self.init_cont()
436 fps = 59.64 # Fields per second
Guido van Rossumbc6d3c31993-05-07 09:37:42 +0000437 # XXX (fps of Indigo monitor, not of PAL or NTSC!)
Guido van Rossum9f42f4f1993-05-10 15:07:20 +0000438 tpf = 1000.0 / fps # Time per field in msec
Guido van Rossumb7e3cc11993-05-06 16:06:44 +0000439 self.capturing = 1
Guido van Rossum9f42f4f1993-05-10 15:07:20 +0000440 self.start_audio()
Guido van Rossumb7e3cc11993-05-06 16:06:44 +0000441 while 1:
442 try:
443 void = fl.check_forms()
444 except StopCapture:
Guido van Rossumb7e3cc11993-05-06 16:06:44 +0000445 break
446 try:
447 cd, id = self.video.GetCaptureData()
448 except sv.error:
449 sgi.nap(1)
450 continue
Guido van Rossum9f42f4f1993-05-10 15:07:20 +0000451 id = id + 2*self.rate
Guido van Rossumb7e3cc11993-05-06 16:06:44 +0000452 data = cd.InterleaveFields(1)
453 cd.UnlockCaptureData()
454 t = id*tpf
Guido van Rossumbc6d3c31993-05-07 09:37:42 +0000455 if not self.write_frame(t, data):
Guido van Rossume17c6c31993-05-06 16:27:25 +0000456 break
Guido van Rossum9f42f4f1993-05-10 15:07:20 +0000457 self.stop_audio()
Guido van Rossume17c6c31993-05-06 16:27:25 +0000458 self.capturing = 0
Guido van Rossum9f42f4f1993-05-10 15:07:20 +0000459 self.end_cont()
Guido van Rossumad4fcd41993-05-11 18:36:54 +0000460 if self.aout:
461 # If recording audio, can't capture multiple sequences
462 self.reset()
Guido van Rossum9f42f4f1993-05-10 15:07:20 +0000463 self.b_capture.label = saved_label
Guido van Rossumb7e3cc11993-05-06 16:06:44 +0000464
Jack Jansen672754a1993-06-08 12:52:41 +0000465 def single_capture(self, stepfunc, timecode):
Guido van Rossum9f42f4f1993-05-10 15:07:20 +0000466 self.open_if_closed()
467 self.init_cont()
468 while 1:
469 try:
470 cd, id = self.video.GetCaptureData()
471 break
472 except sv.error:
473 pass
474 sgi.nap(1)
Jack Jansen672754a1993-06-08 12:52:41 +0000475 if stepfunc: # This might step the video
476 d=stepfunc() # to the next frame
477 if not self.use_24:
478 data = cd.InterleaveFields(1)
479 else:
480 x, y = self.vout.getsize()
481 if self.rgb24_size == 1:
482 data = cd.YUVtoRGB(1)
483 elif self.rgb24_size == 2:
484 data = cd.YUVtoRGB_quarter(1)
485 x = x/2
486 y = y/2
487 elif self.rgb24_size == 3:
488 data = cd.YUVtoRGB_sixteenth(1)
489 x = x/4
490 y = y/4
491 else:
492 raise 'Kaboo! Kaboo!'
493 if self.use_jpeg:
494 import jpeg
495 data = jpeg.compress(data, x, y, 4)
Guido van Rossum9f42f4f1993-05-10 15:07:20 +0000496 cd.UnlockCaptureData()
497 self.end_cont()
Jack Jansen672754a1993-06-08 12:52:41 +0000498 if timecode == None:
499 timecode = (self.nframes+1) * (1000/25)
500 return self.write_frame(timecode, data)
Guido van Rossum9f42f4f1993-05-10 15:07:20 +0000501
502 def vcr_capture(self):
503 if not self.vcr:
Guido van Rossum9f42f4f1993-05-10 15:07:20 +0000504 try:
505 self.vcr = VCR.VCR().init()
Guido van Rossumc17c84f1993-05-10 15:45:49 +0000506 self.vcr.wait()
Guido van Rossumad4fcd41993-05-11 18:36:54 +0000507 if not (self.vcr.fmmode('dnr') and \
508 self.vcr.dmcontrol('digital slow')):
509 self.vcr_error('digital slow failed')
510 return
Guido van Rossum9f42f4f1993-05-10 15:07:20 +0000511 except VCR.error, msg:
Guido van Rossumc17c84f1993-05-10 15:45:49 +0000512 self.vcr = None
Guido van Rossumad4fcd41993-05-11 18:36:54 +0000513 self.vcr_error(msg)
Guido van Rossum9f42f4f1993-05-10 15:07:20 +0000514 return
Guido van Rossumad4fcd41993-05-11 18:36:54 +0000515 if not self.vcr.still():
516 self.vcr_error('still failed')
517 return
518 # XXX for some reason calling where() too often hangs the VCR,
519 # XXX so we insert sleep(0.1) before every sense() call.
520 self.open_if_closed()
521 rate = self.getint(self.in_rate_vcr, 1)
522 rate = max(rate, 1)
Jack Jansen672754a1993-06-08 12:52:41 +0000523 vcrspeed = self.c_vcrspeed.get_choice()
524 vcrspeed = VcrSpeeds[vcrspeed]
525 if vcrspeed == 0:
526 stepfunc = self.vcr.step
527 else:
528 stepfunc = None
Guido van Rossumad4fcd41993-05-11 18:36:54 +0000529 self.speed_factor = rate
Jack Jansen672754a1993-06-08 12:52:41 +0000530 addr = start_addr = self.vcr.sense()
531 if not self.single_capture(None, 0):
Guido van Rossumad4fcd41993-05-11 18:36:54 +0000532 return
533 print 'captured %02d:%02d:%02d:%02d' % self.vcr.addr2tc(addr)
534 count = self.getint(self.in_nframes_vcr, 1) - 1
535 if count <= 0:
536 while rate > 0:
537 if not self.vcr.step():
538 self.vcr_error('step failed')
539 here = self.vcr.sense()
540 if here > addr:
541 rate = rate - (here - addr)
542 addr = here
543 return
Jack Jansen672754a1993-06-08 12:52:41 +0000544 if not self.vcr.fwdshuttle(vcrspeed): # one tenth speed
Guido van Rossumad4fcd41993-05-11 18:36:54 +0000545 self.vcr_error('fwd shuttle failed')
546 return
547 cycle = 0
548 while count > 0:
549 time.sleep(0.1)
550 try:
551 here = self.vcr.sense()
552 except VCR.error, msg:
553 self.vcr_error(msg)
Guido van Rossum9f42f4f1993-05-10 15:07:20 +0000554 break
Guido van Rossumad4fcd41993-05-11 18:36:54 +0000555 if here <> addr:
556 if here <> addr+1:
557 print 'Missed', here-addr-1,
558 print 'frame' + 's'*(here-addr-1 <> 1)
559 cycle = (cycle+1) % rate
560 if cycle == 0:
Jack Jansen672754a1993-06-08 12:52:41 +0000561 tc = (here-start_addr)*40
562 if not self.single_capture(stepfunc, \
563 tc):
Guido van Rossumad4fcd41993-05-11 18:36:54 +0000564 break
565 print 'captured %02d:%02d:%02d:%02d' \
566 % self.vcr.addr2tc(here)
567 count = count -1
568 addr = here
569 if self.vcr and not self.vcr.still():
570 self.vcr_error('still failed')
571
572 def vcr_error(self, msg):
573 self.reset()
574 fl.show_message('VCR error:', str(msg), '')
Guido van Rossum9f42f4f1993-05-10 15:07:20 +0000575
576 # Init/end continuous capture mode
577
578 def init_cont(self):
579 qsize = 1
580 if self.vmode == VM_CONT:
581 self.rate = self.getint(self.in_rate, 2)
582 else:
583 self.rate = 2
584 x, y = self.vout.getsize()
Jack Jansen672754a1993-06-08 12:52:41 +0000585 if self.use_24:
586 info = (SV.YUV411_FRAMES, x, y, qsize, self.rate)
587 else:
588 info = (SV.RGB8_FRAMES, x, y, qsize, self.rate)
Guido van Rossum9f42f4f1993-05-10 15:07:20 +0000589 info2 = self.video.InitContinuousCapture(info)
590 if info2 <> info:
591 # XXX This is really only debug info
592 print 'Info mismatch: requested', info, 'got', info2
593
594 def end_cont(self):
595 self.video.EndContinuousCapture()
596
597 # Misc stuff
598
599 def settitle(self):
600 gl.winset(self.window)
601 x, y = gl.getsize()
602 title = 'Vb:' + self.vfile + ' (%dx%d)' % (x, y)
603 gl.wintitle(title)
604
605 def get_vformat(self):
606 i = self.c_vformat.get_choice()
607 label = VideoFormatLabels[i-1]
608 format = VideoFormats[i-1]
609 self.vformat = format
610 if self.vformat == '':
611 self.form.freeze_form()
612 self.g_video.hide_object()
613 self.g_cont.hide_object()
614 self.g_burst.hide_object()
615 self.g_single.hide_object()
616 self.form.unfreeze_form()
617 return
618 else:
619 self.g_video.show_object()
620 if self.vmode == VM_CONT:
621 self.g_cont.show_object()
622 elif self.vmode == VM_BURST:
623 self.g_burst.show_object()
624 elif self.vmode == VM_SINGLE:
625 self.g_single.show_object()
Guido van Rossumc5a14331993-05-07 11:20:07 +0000626 #
627 self.rgb = (format[:3] == 'rgb')
628 self.mono = (format == 'mono')
629 self.grey = (format[:4] == 'grey')
Jack Jansen672754a1993-06-08 12:52:41 +0000630 self.use_24 = (format in ('rgb', 'jpeg'))
631 # Does not work.... if self.use_24:
632 if 0:
633 self.g_rgb24.show_object()
634 else:
635 self.g_rgb24.hide_object()
636 self.use_jpeg = (format == 'jpeg')
Guido van Rossumc5a14331993-05-07 11:20:07 +0000637 self.mono_use_thresh = (label == 'mono thresh')
638 s = format[4:]
639 if s:
640 self.greybits = string.atoi(s)
641 else:
642 self.greybits = 8
643 if label == 'grey2 dith':
644 self.greybits = -2
645 #
646 convertor = None
647 if self.grey:
648 if self.greybits == 2:
649 convertor = imageop.grey2grey2
650 elif self.greybits == 4:
651 convertor = imageop.grey2grey4
652 elif self.greybits == -2:
653 convertor = imageop.dither2grey2
654 self.convertor = convertor
Jack Jansen672754a1993-06-08 12:52:41 +0000655 self.optfullsizewindow()
Guido van Rossumc5a14331993-05-07 11:20:07 +0000656
Guido van Rossum9f42f4f1993-05-10 15:07:20 +0000657 def get_aformat(self):
658 self.reset()
659 self.aformat = self.c_aformat.get_choice()
660 if self.aformat == A_OFF:
661 self.g_audio.hide_object()
662 else:
663 self.g_audio.show_object()
664
665 def open_if_closed(self):
666 if not self.vout:
667 self.open_video()
668 if not self.aout:
669 self.open_audio()
670
671 # File I/O handling
672
673 def open_video(self):
674 self.close_video()
Guido van Rossumbc6d3c31993-05-07 09:37:42 +0000675 gl.winset(self.window)
676 x, y = gl.getsize()
Jack Jansen672754a1993-06-08 12:52:41 +0000677 if self.use_24:
678 if self.rgb24_size == 2:
679 x, y = x/2, y/2
680 elif self.rgb24_size == 4:
681 x, y = x/4, y/4
Guido van Rossum9f42f4f1993-05-10 15:07:20 +0000682 vout = VFile.VoutFile().init(self.vfile)
683 vout.setformat(self.vformat)
Guido van Rossumbc6d3c31993-05-07 09:37:42 +0000684 vout.setsize(x, y)
Guido van Rossum9f42f4f1993-05-10 15:07:20 +0000685 if self.vmode == VM_BURST:
Guido van Rossumbc6d3c31993-05-07 09:37:42 +0000686 vout.setpf((1, -2))
687 vout.writeheader()
688 self.vout = vout
Guido van Rossum9f42f4f1993-05-10 15:07:20 +0000689 self.nframes = 0
Guido van Rossumad4fcd41993-05-11 18:36:54 +0000690 self.speed_factor = 1
Guido van Rossum9f42f4f1993-05-10 15:07:20 +0000691 self.t_nframes.label = `self.nframes`
Guido van Rossumbc6d3c31993-05-07 09:37:42 +0000692
Guido van Rossumbc6d3c31993-05-07 09:37:42 +0000693 def write_frame(self, t, data):
Guido van Rossumad4fcd41993-05-11 18:36:54 +0000694 t = t * self.speed_factor
Guido van Rossum9f42f4f1993-05-10 15:07:20 +0000695 if not self.vout:
696 gl.ringbell()
Guido van Rossumad4fcd41993-05-11 18:36:54 +0000697 return 0
Guido van Rossumbc6d3c31993-05-07 09:37:42 +0000698 if self.convertor:
699 data = self.convertor(data, len(data), 1)
700 elif self.mono:
701 if self.mono_use_thresh:
702 data = imageop.grey2mono(data, \
703 len(data), 1,\
704 self.mono_thresh)
705 else:
706 data = imageop.dither2mono(data, \
707 len(data), 1)
708 try:
Guido van Rossum9f42f4f1993-05-10 15:07:20 +0000709 self.vout.writeframe(int(t), data, None)
Guido van Rossumbc6d3c31993-05-07 09:37:42 +0000710 except IOError, msg:
Guido van Rossumad4fcd41993-05-11 18:36:54 +0000711 self.reset()
Guido van Rossumbc6d3c31993-05-07 09:37:42 +0000712 if msg == (0, 'Error 0'):
713 msg = 'disk full??'
714 fl.show_message('IOError', str(msg), '')
715 return 0
Guido van Rossum9f42f4f1993-05-10 15:07:20 +0000716 self.nframes = self.nframes + 1
717 self.t_nframes.label = `self.nframes`
Guido van Rossumbc6d3c31993-05-07 09:37:42 +0000718 return 1
719
Guido van Rossum9f42f4f1993-05-10 15:07:20 +0000720 def close_video(self):
721 if not self.vout:
722 return
723 self.nframes = 0
724 self.t_nframes.label = ''
Guido van Rossumc5a14331993-05-07 11:20:07 +0000725 try:
726 self.vout.close()
727 except IOError, msg:
728 if msg == (0, 'Error 0'):
729 msg = 'disk full??'
730 fl.show_message('IOError', str(msg), '')
Guido van Rossum9f42f4f1993-05-10 15:07:20 +0000731 self.vout = None
732
733 # Watch cursor handling
Guido van Rossumb7e3cc11993-05-06 16:06:44 +0000734
Guido van Rossumbc6d3c31993-05-07 09:37:42 +0000735 def setwatch(self):
736 gl.winset(self.form.window)
737 gl.setcursor(WATCH, 0, 0)
Guido van Rossum9f42f4f1993-05-10 15:07:20 +0000738 gl.winset(self.window)
739 gl.setcursor(WATCH, 0, 0)
Guido van Rossumbc6d3c31993-05-07 09:37:42 +0000740
741 def setarrow(self):
742 gl.winset(self.form.window)
743 gl.setcursor(ARROW, 0, 0)
Guido van Rossum9f42f4f1993-05-10 15:07:20 +0000744 gl.winset(self.window)
745 gl.setcursor(ARROW, 0, 0)
Guido van Rossumbc6d3c31993-05-07 09:37:42 +0000746
Guido van Rossum9f42f4f1993-05-10 15:07:20 +0000747 # Numeric field handling
748
749 def getint(self, field, default):
750 try:
751 value = string.atoi(field.get_input())
752 except string.atoi_error:
753 value = default
754 field.set_input(`value`)
755 return value
756
757 def getfloat(self, field, default):
758 try:
759 value = float(eval(field.get_input()))
760 except:
761 value = float(default)
Guido van Rossumc17c84f1993-05-10 15:45:49 +0000762 field.set_input(`value`)
Guido van Rossum9f42f4f1993-05-10 15:07:20 +0000763 return value
764
765 # Audio stuff
766
767 def open_audio(self):
768 if self.aformat == A_OFF:
769 return
770 import aifc
771 import al
772 import AL
773 import thread
774 self.close_audio()
775 params = [AL.INPUT_RATE, 0]
776 al.getparams(AL.DEFAULT_DEVICE, params)
777 rate = params[1]
778 self.aout = aifc.open(self.afile, 'w')
779 if self.aformat in (A_16_STEREO, A_8_STEREO):
780 nch = AL.STEREO
781 else:
782 nch = AL.MONO
783 if self.aformat in (A_16_STEREO, A_16_MONO):
784 width = AL.SAMPLE_16
785 else:
786 width = AL.SAMPLE_8
787 self.aout.setnchannels(nch)
788 self.aout.setsampwidth(width)
789 self.aout.setframerate(rate)
Guido van Rossum9f42f4f1993-05-10 15:07:20 +0000790 c = al.newconfig()
791 c.setqueuesize(8000)
792 c.setchannels(nch)
793 c.setwidth(width)
794 self.aport = al.openport('Vb audio record', 'r', c)
795 self.audio_stop = 0
796 self.audio_ok = 0
797 self.audio_busy = 1
798 thread.start_new_thread(self.record_audio, ())
799
800 def start_audio(self):
801 if self.aformat == A_OFF:
802 return
803 self.audio_ok = 1
804
805 def record_audio(self, *args):
806 # This function runs in a separate thread
807 # Currently no semaphores are used
808 while not self.audio_stop:
809 data = self.aport.readsamps(4000)
810 if self.audio_ok:
Guido van Rossumf6d80321993-06-10 13:40:51 +0000811 self.aout.writeframes(data)
Guido van Rossum9f42f4f1993-05-10 15:07:20 +0000812 data = None
813 self.audio_busy = 0
814
815 def stop_audio(self):
816 self.audio_ok = 0
817
818 def close_audio(self):
819 if self.aout:
820 self.audio_ok = 0
821 self.audio_stop = 1
822 while self.audio_busy:
823 time.sleep(0.1)
824 self.aout.close()
825 self.aout = None
826 if self.aport:
827 self.aport.closeport()
828 self.aport = None
829
Guido van Rossumb7e3cc11993-05-06 16:06:44 +0000830
831try:
832 main()
833except KeyboardInterrupt:
834 print '[Interrupt]'
835 sys.exit(1)