3 # Capture a CMIF movie using the Indigo video library and board in burst mode
8 # Start the application. Resize the window to the desired movie size.
9 # Press the left mouse button to start recording, release it to end
10 # recording. You can record as many times as you wish, but each time
11 # you overwrite the output file(s), so only the last recording is
14 # Press ESC or select the window manager Quit or Close window option
15 # to quit. If you quit before recording anything, the output file(s)
20 sys
.path
.append('/ufs/guido/src/video')
33 # Usage and help functions (keep this up-to-date if you change the program!)
36 print 'Usage: Vrecb [options] [moviefile [audiofile]]'
39 print '-a : record audio as well'
40 print '-r rate : capture 1 out of every "rate" frames', \
42 print '-w width : initial window width', \
43 '(default 256, use 0 for 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 '-N memsize : Capture frames fitting in this many kbytes'
52 print 'moviefile : here goes the movie data (default film.video)'
55 print 'Press the left mouse button to start recording.'
56 print 'Recording time is determined by the -n option.'
57 print 'You can record as many times as you wish, but each'
58 print 'recording overwrites the output file(s) -- only the'
59 print 'last recording is kept.'
61 print 'Press ESC or use the window manager Quit or Close window option'
62 print 'to quit. If you quit before recording anything, the output'
63 print 'file(s) are not touched.'
69 format
= SV
.RGB8_FRAMES
83 opts
, args
= getopt
.getopt(sys
.argv
[1:], 'ar:w:dg:mM:Gfn:N:')
84 except getopt
.error
, msg
:
85 sys
.stdout
= sys
.stderr
86 print 'Error:', msg
, '\n'
95 rate
= string
.atoi(arg
)
97 sys
.stderr
.write('-r rate must be >= 1\n')
100 width
= string
.atoi(arg
)
105 greybits
= string
.atoi(arg
)
106 if not greybits
in (2,4,8):
108 'Only 2, 4 or 8 bit greyscale supported\n')
117 monotreshold
= string
.atoi(arg
)
121 number
= string
.atoi(arg
)
123 memsize
= string
.atoi(arg
)
124 if 0 < memsize
< 1024:
125 memsize
= memsize
* 1024
126 if 0 < memsize
< 1024*1024:
127 memsize
= memsize
* 1024
128 print 'memsize', memsize
129 except string
.atoi_error
:
130 sys
.stdout
= sys
.stderr
131 print 'Option', opt
, 'requires integer argument'
134 if number
<> 0 and memsize
<> 0:
135 sys
.stderr
.write('-n and -N are mutually exclusive\n')
137 if number
== 0 and memsize
== 0:
141 print '-f option assumed until somebody fixes it'
145 sys
.stderr
.write('usage: Vrecb [options] [file [audiofile]]\n')
151 filename
= 'film.video'
153 if args
[1:] and not audio
:
154 sys
.stderr
.write('-a turned on by appearance of 2nd file\n')
159 audiofilename
= args
[1]
161 audiofilename
= 'film.aiff'
166 # Determine maximum window size based on signal standard
167 param
= [SV
.BROADCAST
, 0]
169 if param
[1] == SV
.PAL
:
172 elif param
[1] == SV
.NTSC
:
176 print 'Unknown video standard', param
[1]
189 gl
.prefposition(x1
, x2
, y1
, y2
)
190 win
= gl
.winopen(filename
)
199 number
= calcnumber(x
, y
, grey
or mono
, memsize
)
200 print number
, 'frames'
204 param
= [SV
.FIELDDROP
, 1, SV
.GENLOCK
, SV
.GENLOCK_OFF
]
206 param
= [SV
.FIELDDROP
, 0, SV
.GENLOCK
, SV
.GENLOCK_ON
]
208 param
= param
+[SV
.COLOR
, SV
.MONO
, SV
.DITHER
, 0, \
211 param
= param
+[SV
.COLOR
, SV
.DEFAULT_COLOR
, SV
.INPUT_BYPASS
, 0]
213 v
.BindGLWindow(win
, SV
.IN_REPLACE
)
216 gl
.qdevice(DEVICE
.LEFTMOUSE
)
217 gl
.qdevice(DEVICE
.WINQUIT
)
218 gl
.qdevice(DEVICE
.WINSHUT
)
219 gl
.qdevice(DEVICE
.ESCKEY
)
224 dev
, val
= gl
.qread()
225 if dev
== DEVICE
.LEFTMOUSE
:
227 info
= format
, x
, y
, number
, rate
228 record(v
, info
, filename
, audiofilename
, \
230 greybits
, monotreshold
, fields
)
231 elif dev
== DEVICE
.REDRAW
:
232 # Window resize (or move)
236 number
= calcnumber(x
, y
, grey
or mono
, memsize
)
237 print number
, 'frames'
239 v
.BindGLWindow(win
, SV
.IN_REPLACE
)
240 elif dev
in (DEVICE
.ESCKEY
, DEVICE
.WINQUIT
, DEVICE
.WINSHUT
):
247 def calcnumber(x
, y
, grey
, memsize
):
249 pixels
= pixels
/2 # XXX always assume fields
250 if grey
: n
= memsize
/pixels
251 else: n
= memsize
/(4*pixels
)
255 # Record until the mouse is released (or any other GL event)
256 # XXX audio not yet supported
258 def record(v
, info
, filename
, audiofilename
, \
259 mono
, grey
, greybits
, monotreshold
, fields
):
261 format
, x
, y
, number
, rate
= info
262 fps
= 59.64 # Fields per second
263 # XXX (Strange: need fps of Indigo monitor, not of PAL or NTSC!)
264 tpf
= 1000.0 / fps
# Time per field in msec
269 gl
.wintitle('(start audio) ' + filename
)
270 audiodone
= thread
.allocate_lock()
271 audiodone
.acquire_lock()
272 audiostart
= thread
.allocate_lock()
273 audiostart
.acquire_lock()
275 initaudio(audiofilename
, audiostop
, audiostart
, audiodone
)
276 audiostart
.acquire_lock()
277 gl
.wintitle('(rec) ' + filename
)
279 ninfo
, data
, bitvec
= v
.CaptureBurst(info
)
280 except sv
.error
, arg
:
281 print 'CaptureBurst failed:', arg
283 gl
.wintitle(filename
)
285 gl
.wintitle('(save) '+ filename
)
290 print 'Sorry, format changed.'
293 gl
.wintitle(filename
)
296 if x
*y
*number
<> len(data
):
297 print 'Funny data length: wanted',x
,'*',y
,'*', number
,'=',\
298 x
*y
*number
,'got',len(data
)
299 gl
.wintitle(filename
)
304 if filename
and audiofilename
:
305 audiostop
.append(None)
306 audiodone
.acquire_lock()
309 # Construct header and write it
312 vout
= VFile
.VoutFile(filename
)
314 print filename
, ':', msg
318 elif grey
and greybits
== 8:
321 vout
.format
= 'grey'+`
abs(greybits
)`
327 vout
.packfactor
= (1,-2)
329 print 'Sorry, can only save fields at the moment'
330 print '(i.e. you *must* use the -f option)'
331 gl
.wintitle(filename
)
335 # Compute convertor, if needed
340 convertor
= imageop
.grey2grey2
342 convertor
= imageop
.grey2grey4
344 convertor
= imageop
.dither2grey2
348 tpf
= 1000 / 50.0 #XXXX
349 # Trying to find the pattern in frame skipping
352 for frameno
in range(0, number
*2):
353 if frameno
<> 0 and \
354 bitvec
[frameno
] == bitvec
[frameno
-1]:
355 nskipped
= nskipped
+ 1
357 print okstretch
, 'ok',
359 skipstretch
= skipstretch
+ 1
362 print skipstretch
, 'skipped'
364 okstretch
= okstretch
+ 1
367 # XXXX Works only for fields and top-to-bottom
369 start
= frameno
*fieldsize
370 field
= data
[start
:start
+fieldsize
]
372 field
= convertor(field
, len(field
), 1)
373 elif mono
and monotreshold
>= 0:
374 field
= imageop
.grey2mono( \
375 field
, len(field
), 1, monotreshold
)
377 field
= imageop
.dither2mono( \
378 field
, len(field
), 1)
379 realframeno
= realframeno
+ 1
380 vout
.writeframe(int(realframeno
*tpf
), field
, None)
381 print okstretch
, 'ok',
382 print skipstretch
, 'skipped'
383 print 'Skipped', nskipped
, 'duplicate frames'
386 gl
.wintitle('(done) ' + filename
)
387 # Initialize audio recording
389 AQSIZE
= 8*8000 # XXX should be a user option
391 def initaudio(filename
, stop
, start
, done
):
393 afile
= aifc
.open(filename
, 'w')
394 afile
.setnchannels(AL
.MONO
)
395 afile
.setsampwidth(AL
.SAMPLE_8
)
396 params
= [AL
.INPUT_RATE
, 0]
397 al
.getparams(AL
.DEFAULT_DEVICE
, params
)
398 print 'audio sampling rate =', params
[1]
399 afile
.setframerate(params
[1])
401 c
.setchannels(AL
.MONO
)
402 c
.setqueuesize(AQSIZE
)
403 c
.setwidth(AL
.SAMPLE_8
)
404 aport
= al
.openport(filename
, 'r', c
)
405 thread
.start_new_thread(audiorecord
, (afile
, aport
, stop
, start
, done
))
408 # Thread to record audio samples
410 def audiorecord(afile
, aport
, stop
, start
, done
):
416 data
= aport
.readsamps(AQSIZE
/8)
417 afile
.writesampsraw(data
)
420 print 'Done writing audio'
424 # Don't forget to call the main program
428 except KeyboardInterrupt: