blob: 7e88a24167c4b47ce8e98b8a0d7fc536e0d5b352 [file] [log] [blame]
Guido van Rossum180924d1992-08-20 11:46:28 +00001#! /ufs/guido/bin/sgi/python-405
2#! /ufs/guido/bin/sgi/python
3
4# Capture a CMIF movie using the Indigo video library and board
5
6
7# Usage:
8#
Guido van Rossum32517f91992-09-04 13:26:59 +00009# makemovie [-a] [-q queuesize] [-r rate] [-w width] [moviefile [audiofile]]
Guido van Rossum180924d1992-08-20 11:46:28 +000010
11
12# Options:
13#
14# -a : record audio as well
Guido van Rossum62f6bc81992-09-03 16:56:04 +000015# -q queuesize : set the capture queue size (default 2)
Guido van Rossum32517f91992-09-04 13:26:59 +000016# -r rate : capture 1 out of every 'rate' frames (default and min 2)
17# -w width : initial window width (default interactive placement)
Jack Jansen3b253711992-12-14 12:25:21 +000018# -n : Don't write to file, only timing info
19# -d : drop fields if needed
20# -g : greyscale
21# -m : monochrome dithered
22# -M value : monochrome tresholded with value
Guido van Rossum180924d1992-08-20 11:46:28 +000023#
24# moviefile : here goes the movie data (default film.video);
25# the format is documented in cmif-film.ms
26# audiofile : with -a, here goes the audio data (default film.aiff);
27# audio data is recorded in AIFF format, using the
28# input sampling rate, source and volume set by the
29# audio panel, in mono, 8 bits/sample
30
31
32# User interface:
33#
34# Start the application. Resize the window to the desired movie size.
35# Press the left mouse button to start recording, release it to end
Guido van Rossum62f6bc81992-09-03 16:56:04 +000036# recording. You can record as many times as you wish, but each time
37# you overwrite the output file(s), so only the last recording is
38# kept.
Guido van Rossum180924d1992-08-20 11:46:28 +000039#
40# Press ESC or select the window manager Quit or Close window option
Guido van Rossum62f6bc81992-09-03 16:56:04 +000041# to quit. If you quit before recording anything, the output file(s)
42# are not touched.
Guido van Rossum180924d1992-08-20 11:46:28 +000043
44
45import sys
46sys.path.append('/ufs/guido/src/video')
47import sv, SV
48import VFile
49import gl, GL, DEVICE
50import al, AL
51import time
52import posix
53import getopt
54import string
Jack Jansen3b253711992-12-14 12:25:21 +000055import imageop
Guido van Rossum180924d1992-08-20 11:46:28 +000056
57# Main program
58
59def main():
Guido van Rossum62f6bc81992-09-03 16:56:04 +000060 format = SV.RGB8_FRAMES
61 qsize = 2
Guido van Rossum180924d1992-08-20 11:46:28 +000062 audio = 0
Guido van Rossum62f6bc81992-09-03 16:56:04 +000063 rate = 2
Guido van Rossum32517f91992-09-04 13:26:59 +000064 width = 0
Jack Jansen3b253711992-12-14 12:25:21 +000065 norecord = 0
66 drop = 0
67 mono = 0
68 grey = 0
69 monotreshold = -1
Guido van Rossum180924d1992-08-20 11:46:28 +000070
Jack Jansen3b253711992-12-14 12:25:21 +000071 opts, args = getopt.getopt(sys.argv[1:], 'aq:r:w:ndgmM:')
Guido van Rossum180924d1992-08-20 11:46:28 +000072 for opt, arg in opts:
73 if opt == '-a':
74 audio = 1
75 elif opt == '-q':
Guido van Rossum62f6bc81992-09-03 16:56:04 +000076 qsize = string.atoi(arg)
Guido van Rossum180924d1992-08-20 11:46:28 +000077 elif opt == '-r':
Guido van Rossum62f6bc81992-09-03 16:56:04 +000078 rate = string.atoi(arg)
79 if rate < 2:
80 sys.stderr.write('-r rate must be >= 2\n')
81 sys.exit(2)
Guido van Rossum32517f91992-09-04 13:26:59 +000082 elif opt == '-w':
83 width = string.atoi(arg)
Jack Jansen3b253711992-12-14 12:25:21 +000084 elif opt == '-n':
85 norecord = 1
86 elif opt == '-d':
87 drop = 1
88 elif opt == '-g':
89 grey = 1
90 elif opt == '-m':
91 mono = 1
92 elif opt == '-M':
93 mono = 1
94 monotreshold = string.atoi(arg)
Guido van Rossum180924d1992-08-20 11:46:28 +000095
Guido van Rossum8a861be1992-08-20 14:46:46 +000096 if args[2:]:
97 sys.stderr.write('usage: Vrec [options] [file [audiofile]]\n')
98 sys.exit(2)
99
Guido van Rossum180924d1992-08-20 11:46:28 +0000100 if args:
101 filename = args[0]
102 else:
103 filename = 'film.video'
104
Guido van Rossum8a861be1992-08-20 14:46:46 +0000105 if args[1:] and not audio:
106 sys.stderr.write('-a turned on by appearance of 2nd file\n')
107 audio = 1
108
Guido van Rossum180924d1992-08-20 11:46:28 +0000109 if audio:
110 if args[1:]:
111 audiofilename = args[1]
112 else:
113 audiofilename = 'film.aiff'
114 else:
115 audiofilename = None
116
Jack Jansen3b253711992-12-14 12:25:21 +0000117 if norecord:
118 filename = audiofilename = ''
Guido van Rossum32517f91992-09-04 13:26:59 +0000119 v = sv.OpenVideo()
120 # Determine maximum window size based on signal standard
121 param = [SV.BROADCAST, 0]
122 v.GetParam(param)
123 if param[1] == SV.PAL:
124 x = SV.PAL_XMAX
125 y = SV.PAL_YMAX
126 elif param[1] == SV.NTSC:
127 x = SV.NTSC_XMAX
128 y = SV.NTSC_YMAX
129 else:
130 print 'Unknown video standard', param[1]
131 sys.exit(1)
132
Guido van Rossum180924d1992-08-20 11:46:28 +0000133 gl.foreground()
Guido van Rossum32517f91992-09-04 13:26:59 +0000134 gl.maxsize(x, y)
135 gl.keepaspect(x, y)
Guido van Rossum180924d1992-08-20 11:46:28 +0000136 gl.stepunit(8, 6)
Guido van Rossum32517f91992-09-04 13:26:59 +0000137 if width:
138 gl.prefsize(width, width*3/4)
Guido van Rossum180924d1992-08-20 11:46:28 +0000139 win = gl.winopen(filename)
Guido van Rossum32517f91992-09-04 13:26:59 +0000140 if width:
141 gl.maxsize(x, y)
142 gl.keepaspect(x, y)
143 gl.stepunit(8, 6)
144 gl.winconstraints()
Guido van Rossum180924d1992-08-20 11:46:28 +0000145 x, y = gl.getsize()
146 print x, 'x', y
147
Guido van Rossum180924d1992-08-20 11:46:28 +0000148 v.SetSize(x, y)
Jack Jansen3b253711992-12-14 12:25:21 +0000149<<<<<<< Vrec.py
150
151 if drop:
152 param = [SV.FIELDDROP, 1, SV.GENLOCK, SV.GENLOCK_OFF]
153 else:
154 param = [SV.FIELDDROP, 0, SV.GENLOCK, SV.GENLOCK_ON]
155 if mono or grey:
156 param = param+[SV.COLOR, SV.MONO, SV.INPUT_BYPASS, 1]
157 else:
158 param = param+[SV.COLOR, SV.DEFAULT_COLOR, SV.INPUT_BYPASS, 0]
159 v.SetParam(param)
160
161=======
Guido van Rossumff3da051992-12-09 22:16:35 +0000162
163 # VERY IMPORTANT (for PAL at least): don't drop fields!
164 param = [SV.FIELDDROP, 0]
165 v.SetParam(param)
166
Jack Jansen3b253711992-12-14 12:25:21 +0000167>>>>>>> 1.7
Guido van Rossum180924d1992-08-20 11:46:28 +0000168 v.BindGLWindow(win, SV.IN_REPLACE)
169
Guido van Rossum180924d1992-08-20 11:46:28 +0000170 gl.qdevice(DEVICE.LEFTMOUSE)
171 gl.qdevice(DEVICE.WINQUIT)
172 gl.qdevice(DEVICE.WINSHUT)
173 gl.qdevice(DEVICE.ESCKEY)
174
175 print 'Press left mouse to start recording, release it to stop'
176
Guido van Rossum180924d1992-08-20 11:46:28 +0000177 while 1:
178 dev, val = gl.qread()
179 if dev == DEVICE.LEFTMOUSE:
180 if val == 1:
Guido van Rossum62f6bc81992-09-03 16:56:04 +0000181 info = format, x, y, qsize, rate
Jack Jansen3b253711992-12-14 12:25:21 +0000182 record(v, info, filename, audiofilename,\
183 mono, grey, monotreshold)
Guido van Rossum180924d1992-08-20 11:46:28 +0000184 elif dev == DEVICE.REDRAW:
185 # Window resize (or move)
Guido van Rossum62f6bc81992-09-03 16:56:04 +0000186 x, y = gl.getsize()
187 print x, 'x', y
188 v.SetSize(x, y)
189 v.BindGLWindow(win, SV.IN_REPLACE)
Guido van Rossum180924d1992-08-20 11:46:28 +0000190 elif dev in (DEVICE.ESCKEY, DEVICE.WINQUIT, DEVICE.WINSHUT):
191 # Quit
Guido van Rossum180924d1992-08-20 11:46:28 +0000192 v.CloseVideo()
193 gl.winclose(win)
194 break
195
196
197# Record until the mouse is released (or any other GL event)
198# XXX audio not yet supported
199
Jack Jansen3b253711992-12-14 12:25:21 +0000200def record(v, info, filename, audiofilename, mono, grey, monotreshold):
Guido van Rossum180924d1992-08-20 11:46:28 +0000201 import thread
Guido van Rossum62f6bc81992-09-03 16:56:04 +0000202 format, x, y, qsize, rate = info
203 fps = 59.64 # Fields per second
204 # XXX (Strange: need fps of Indigo monitor, not of PAL or NTSC!)
205 tpf = 1000.0 / fps # Time per field in msec
Jack Jansen3b253711992-12-14 12:25:21 +0000206 if filename:
207 vout = VFile.VoutFile().init(filename)
208 if mono:
209 vout.format = 'mono'
210 elif grey:
211 vout.format = 'grey'
212 else:
213 vout.format = 'rgb8'
214 vout.width = x
215 vout.height = y
216 vout.writeheader()
217 MAXSIZE = 20 # XXX should be a user option
218 import Queue
219 queue = Queue.Queue().init(MAXSIZE)
220 done = thread.allocate_lock()
221 done.acquire_lock()
222 thread.start_new_thread(saveframes, \
223 (vout, queue, done, mono, monotreshold))
224 if audiofilename:
225 audiodone = thread.allocate_lock()
226 audiodone.acquire_lock()
227 audiostop = []
228 initaudio(audiofilename, audiostop, audiodone)
Guido van Rossum180924d1992-08-20 11:46:28 +0000229 gl.wintitle('(rec) ' + filename)
Guido van Rossum62f6bc81992-09-03 16:56:04 +0000230 lastid = 0
Guido van Rossum180924d1992-08-20 11:46:28 +0000231 t0 = time.millitimer()
Jack Jansen3b253711992-12-14 12:25:21 +0000232 count = 0
233 timestamps = []
234 ids = []
Guido van Rossum62f6bc81992-09-03 16:56:04 +0000235 v.InitContinuousCapture(info)
Guido van Rossum180924d1992-08-20 11:46:28 +0000236 while not gl.qtest():
Guido van Rossum62f6bc81992-09-03 16:56:04 +0000237 try:
238 cd, id = v.GetCaptureData()
Guido van Rossum42e07af1992-09-22 15:01:43 +0000239 except sv.error:
Guido van Rossum62f6bc81992-09-03 16:56:04 +0000240 time.millisleep(10) # XXX is this necessary?
241 continue
Jack Jansen3b253711992-12-14 12:25:21 +0000242 timestamps.append(time.millitimer())
243 ids.append(id)
244
Guido van Rossum62f6bc81992-09-03 16:56:04 +0000245 id = id + 2*rate
246## if id <> lastid + 2*rate:
247## print lastid, id
248 lastid = id
249 data = cd.InterleaveFields(1)
Guido van Rossum180924d1992-08-20 11:46:28 +0000250 cd.UnlockCaptureData()
Jack Jansen3b253711992-12-14 12:25:21 +0000251 count = count+1
252 if filename:
253 queue.put(data, int(id*tpf))
Guido van Rossum62f6bc81992-09-03 16:56:04 +0000254 t1 = time.millitimer()
255 gl.wintitle('(busy) ' + filename)
256 print lastid, 'fields in', t1-t0, 'msec',
257 print '--', 0.1 * int(lastid * 10000.0 / (t1-t0)), 'fields/sec'
Jack Jansen3b253711992-12-14 12:25:21 +0000258 print 'Captured',count*2, 'fields,', 0.1*int(count*20000.0/(t1-t0)), 'f/s',
259 print count*200.0/lastid, '%,',
260 print count*rate*200.0/lastid, '% of wanted rate'
261 t0 = timestamps[0]
262 del timestamps[0]
263 print 'Times:',
264 for t1 in timestamps:
265 print t1-t0,
266 t0 = t1
267 print
268 print 'Ids:',
269 t0 = ids[0]
270 del ids[0]
271 for t1 in ids:
272 print t1-t0,
273 t0 = t1
274 print
275 if filename and audiofilename:
Guido van Rossum62f6bc81992-09-03 16:56:04 +0000276 audiostop.append(None)
277 audiodone.acquire_lock()
278 v.EndContinuousCapture()
Jack Jansen3b253711992-12-14 12:25:21 +0000279 if filename:
280 queue.put(None) # Sentinel
281 done.acquire_lock()
Guido van Rossum180924d1992-08-20 11:46:28 +0000282 gl.wintitle('(done) ' + filename)
283
284
285# Thread to save the frames to the file
286
Jack Jansen3b253711992-12-14 12:25:21 +0000287def saveframes(vout, queue, done, mono, monotreshold):
Guido van Rossum180924d1992-08-20 11:46:28 +0000288 while 1:
Guido van Rossum62f6bc81992-09-03 16:56:04 +0000289 x = queue.get()
290 if not x:
291 break
292 data, t = x
Jack Jansen3b253711992-12-14 12:25:21 +0000293 if mono and monotreshold >= 0:
294 data = imageop.grey2mono(data, len(data), 1,\
295 monotreshold)
296 elif mono:
297 data = imageop.dither2mono(data, len(data), 1)
Guido van Rossum62f6bc81992-09-03 16:56:04 +0000298 vout.writeframe(t, data, None)
299 del data
300 sys.stderr.write('Done writing video\n')
Guido van Rossum180924d1992-08-20 11:46:28 +0000301 vout.close()
Guido van Rossum62f6bc81992-09-03 16:56:04 +0000302 done.release_lock()
Guido van Rossum180924d1992-08-20 11:46:28 +0000303
304
Guido van Rossum8a861be1992-08-20 14:46:46 +0000305# Initialize audio recording
306
Guido van Rossum62f6bc81992-09-03 16:56:04 +0000307AQSIZE = 8000 # XXX should be a user option
Guido van Rossum8a861be1992-08-20 14:46:46 +0000308
Guido van Rossum62f6bc81992-09-03 16:56:04 +0000309def initaudio(filename, stop, done):
Guido van Rossum8a861be1992-08-20 14:46:46 +0000310 import thread, aiff
311 afile = aiff.Aiff().init(filename, 'w')
312 afile.nchannels = AL.MONO
313 afile.sampwidth = AL.SAMPLE_8
314 params = [AL.INPUT_RATE, 0]
315 al.getparams(AL.DEFAULT_DEVICE, params)
316 print 'audio sampling rate =', params[1]
317 afile.samprate = params[1]
318 c = al.newconfig()
319 c.setchannels(AL.MONO)
320 c.setqueuesize(AQSIZE)
321 c.setwidth(AL.SAMPLE_8)
322 aport = al.openport(filename, 'r', c)
Guido van Rossum62f6bc81992-09-03 16:56:04 +0000323 thread.start_new_thread(audiorecord, (afile, aport, stop, done))
Guido van Rossum8a861be1992-08-20 14:46:46 +0000324
325
326# Thread to record audio samples
327
328# XXX should use writesampsraw for efficiency, but then destroy doesn't
329# XXX seem to set the #samples in the header correctly
330
Guido van Rossum62f6bc81992-09-03 16:56:04 +0000331def audiorecord(afile, aport, stop, done):
332 while not stop:
Guido van Rossum8a861be1992-08-20 14:46:46 +0000333 data = aport.readsamps(AQSIZE/2)
334## afile.writesampsraw(data)
335 afile.writesamps(data)
336 del data
337 afile.destroy()
338 print 'Done writing audio'
Guido van Rossum62f6bc81992-09-03 16:56:04 +0000339 done.release_lock()
Guido van Rossum8a861be1992-08-20 14:46:46 +0000340
341
Guido van Rossum180924d1992-08-20 11:46:28 +0000342# Don't forget to call the main program
343
Guido van Rossume0be2b31992-09-01 14:45:57 +0000344try:
345 main()
346except KeyboardInterrupt:
347 print '[Interrupt]'