mirror of
				https://github.com/python/cpython.git
				synced 2025-11-04 03:44:55 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			962 lines
		
	
	
	
		
			23 KiB
		
	
	
	
		
			Python
		
	
	
		
			Executable file
		
	
	
	
	
			
		
		
	
	
			962 lines
		
	
	
	
		
			23 KiB
		
	
	
	
		
			Python
		
	
	
		
			Executable file
		
	
	
	
	
#! /usr/bin/env python
 | 
						|
 | 
						|
# Video bag of tricks: record video(+audio) in various formats and modes
 | 
						|
 | 
						|
# XXX To do:
 | 
						|
# - audio
 | 
						|
# - improve user interface
 | 
						|
# - help button?
 | 
						|
# - command line options to set initial settings
 | 
						|
# - save settings in a file
 | 
						|
# - ...?
 | 
						|
 | 
						|
import sys
 | 
						|
import time
 | 
						|
import getopt
 | 
						|
import string
 | 
						|
import os
 | 
						|
sts = os.system('makemap')		# Must be before "import fl" to work
 | 
						|
import sgi
 | 
						|
import gl
 | 
						|
import GL
 | 
						|
import DEVICE
 | 
						|
import fl
 | 
						|
import FL
 | 
						|
import flp
 | 
						|
import watchcursor
 | 
						|
import sv
 | 
						|
import SV
 | 
						|
import VFile
 | 
						|
import VGrabber
 | 
						|
import imageop
 | 
						|
sys.path.append('/ufs/jack/src/av/vcr')
 | 
						|
import VCR
 | 
						|
try:
 | 
						|
	import cl
 | 
						|
except ImportError:
 | 
						|
	cl = None
 | 
						|
 | 
						|
ARROW = 0
 | 
						|
WATCH = 1
 | 
						|
watchcursor.defwatch(WATCH)
 | 
						|
 | 
						|
def main():
 | 
						|
##	fl.set_graphics_mode(0, 1)
 | 
						|
	vb = VideoBagOfTricks()
 | 
						|
	while 1:
 | 
						|
		dummy = fl.do_forms()
 | 
						|
		[dummy]
 | 
						|
 | 
						|
StopCapture = 'StopCapture'
 | 
						|
 | 
						|
VideoFormatLabels = ['Video off', 'rgb8', 'grey8', 'grey4', 'grey2', \
 | 
						|
	  'grey2 dith', 'mono dith', 'mono thresh', 'rgb24', 'rgb24-jpeg', \
 | 
						|
	  'compress']
 | 
						|
VideoFormats = ['', 'rgb8', 'grey', 'grey4', 'grey2', \
 | 
						|
	  'grey2', 'mono', 'mono', 'rgb', 'jpeg', 'compress']
 | 
						|
 | 
						|
VideoModeLabels = ['Continuous', 'Burst', 'Single frame', 'VCR sync']
 | 
						|
[VM_CONT, VM_BURST, VM_SINGLE, VM_VCR] = range(1, 5)
 | 
						|
 | 
						|
AudioFormatLabels = ['Audio off', \
 | 
						|
	  '16 bit mono', '16 bit stereo', '8 bit mono', '8 bit stereo']
 | 
						|
[A_OFF, A_16_MONO, A_16_STEREO, A_8_MONO, A_8_STEREO] = range(1, 6)
 | 
						|
 | 
						|
VcrSpeedLabels = ['normal', '1/3', '1/5', '1/10', '1/30', 'single-step']
 | 
						|
VcrSpeeds = [None, 5, 4, 3, 2, 1, 0]
 | 
						|
 | 
						|
RgbSizeLabels = ['full', 'quarter', 'sixteenth']
 | 
						|
 | 
						|
# init file stuff:
 | 
						|
if os.environ.has_key('HOME'):
 | 
						|
	HOME=os.environ['HOME']
 | 
						|
else:
 | 
						|
	HOME='.'
 | 
						|
VB_INIT_FILE=HOME + '/.Vb_init'
 | 
						|
 | 
						|
VB_INIT_KEYS=['vfile', 'vmode', 'mono_thresh', 'vformat', 'comp_scheme', \
 | 
						|
	  'rgb24_size', 'afile', 'aformat']
 | 
						|
 | 
						|
class VideoBagOfTricks:
 | 
						|
 | 
						|
	# Init/close stuff
 | 
						|
 | 
						|
	def __init__(self):
 | 
						|
		self.window = None
 | 
						|
		formdef = flp.parse_form('VbForm', 'form')
 | 
						|
		flp.create_full_form(self, formdef)
 | 
						|
		self.setdefaults()
 | 
						|
		if self.vmode <> VM_CONT:
 | 
						|
			self.g_cont.hide_object()
 | 
						|
		if self.vmode <> VM_BURST:
 | 
						|
			self.g_burst.hide_object()
 | 
						|
		if self.vmode <> VM_SINGLE:
 | 
						|
			self.g_single.hide_object()
 | 
						|
		if self.vmode <> VM_VCR:
 | 
						|
			self.g_vcr.hide_object()
 | 
						|
		if self.vformat <> 'compress':
 | 
						|
			self.g_compress.hide_object()
 | 
						|
 | 
						|
		self.openvideo()
 | 
						|
		self.makewindow()
 | 
						|
		self.bindvideo()
 | 
						|
		if self.use_24:
 | 
						|
			self.optfullsizewindow()
 | 
						|
		self.showform()
 | 
						|
		fl.set_event_call_back(self.do_event)
 | 
						|
 | 
						|
	def close(self):
 | 
						|
		self.close_video()
 | 
						|
		self.close_audio()
 | 
						|
		self.savedefaults()
 | 
						|
		raise SystemExit, 0
 | 
						|
 | 
						|
	def showform(self):
 | 
						|
		# Get position of video window
 | 
						|
		gl.winset(self.window)
 | 
						|
		x, y = gl.getorigin()
 | 
						|
		width, height = gl.getsize()
 | 
						|
		# Calculate position of form window
 | 
						|
		x1 = x + width + 10
 | 
						|
		x2 = x1 + int(self.form.w) - 1
 | 
						|
		y2 = y + height - 1
 | 
						|
		y1 = y2 - int(self.form.h) + 1
 | 
						|
		# Position and show form window
 | 
						|
		gl.prefposition(x1, x2, y1, y2)
 | 
						|
		self.form.show_form(FL.PLACE_FREE, FL.TRUE, 'Vb Control')
 | 
						|
 | 
						|
	def getdefaultdefaults(self):
 | 
						|
		# Video defaults
 | 
						|
		self.vfile = 'film.video'
 | 
						|
		self.vmode = VM_CONT
 | 
						|
		self.mono_thresh = 128
 | 
						|
		self.vformat = 'rgb8'
 | 
						|
		self.comp_scheme = 'Uncompressed'
 | 
						|
		self.rgb24_size = 1
 | 
						|
		# Missing: drop, rate, maxmem, nframes, rate, vcrspeed
 | 
						|
		# Audio defaults:
 | 
						|
		self.afile = 'film.aiff'
 | 
						|
		self.aformat = A_OFF
 | 
						|
 | 
						|
	def getdefaults(self):
 | 
						|
		self.getdefaultdefaults()
 | 
						|
		# XXXX Read defaults file and override.
 | 
						|
		try:
 | 
						|
			fp = open(VB_INIT_FILE, 'r')
 | 
						|
		except IOError:
 | 
						|
			print 'Vb: no init file'
 | 
						|
			self.initcont = {}
 | 
						|
			return
 | 
						|
		data = fp.read(1000000)
 | 
						|
		try:
 | 
						|
			self.initcont = eval(data)
 | 
						|
		except:
 | 
						|
			print 'Vb: Ill-formatted init file'
 | 
						|
			self.initcont = {}
 | 
						|
		for k in self.initcont.keys():
 | 
						|
			if hasattr(self, k):
 | 
						|
				setattr(self, k, self.initcont[k])
 | 
						|
 | 
						|
	def savedefaults(self):
 | 
						|
		newdb = {}
 | 
						|
		for k in VB_INIT_KEYS:
 | 
						|
			newdb[k] = getattr(self, k)
 | 
						|
		if newdb <> self.initcont:
 | 
						|
			try:
 | 
						|
				fp = open(VB_INIT_FILE, 'w')
 | 
						|
			except IOError:
 | 
						|
				print 'Vb: Cannot create', VB_INIT_FILE
 | 
						|
				return
 | 
						|
			fp.write(`newdb`)
 | 
						|
			fp.close()
 | 
						|
			
 | 
						|
	def setdefaults(self):
 | 
						|
		self.getdefaults()
 | 
						|
		self.vcr = None
 | 
						|
		self.vout = None
 | 
						|
		self.capturing = 0
 | 
						|
		self.c_vformat.clear_choice()
 | 
						|
		for label in VideoFormatLabels:
 | 
						|
			self.c_vformat.addto_choice(label)
 | 
						|
		self.c_vformat.set_choice(1 + VideoFormats.index(self.vformat))
 | 
						|
		self.c_vmode.clear_choice()
 | 
						|
		for label in VideoModeLabels:
 | 
						|
			self.c_vmode.addto_choice(label)
 | 
						|
		self.c_vmode.set_choice(self.vmode)
 | 
						|
		self.get_vformat()
 | 
						|
		self.b_drop.set_button(1)
 | 
						|
		self.in_rate.set_input('2')
 | 
						|
		self.in_maxmem.set_input('1.0')
 | 
						|
		self.in_nframes.set_input('0')
 | 
						|
		self.in_nframes_vcr.set_input('1')
 | 
						|
		self.in_rate_vcr.set_input('1')
 | 
						|
		self.c_vcrspeed.clear_choice()
 | 
						|
		for label in VcrSpeedLabels:
 | 
						|
			self.c_vcrspeed.addto_choice(label)
 | 
						|
		self.c_vcrspeed.set_choice(4)
 | 
						|
		self.c_rgb24_size.clear_choice()
 | 
						|
		for label in RgbSizeLabels:
 | 
						|
			self.c_rgb24_size.addto_choice(label)
 | 
						|
		self.c_rgb24_size.set_choice(self.rgb24_size)
 | 
						|
		if cl:
 | 
						|
			algs = cl.QueryAlgorithms(cl.VIDEO)
 | 
						|
			self.all_comp_schemes = []
 | 
						|
			for i in range(0, len(algs), 2):
 | 
						|
				if algs[i+1] in (cl.COMPRESSOR, cl.CODEC):
 | 
						|
					self.all_comp_schemes.append(algs[i])
 | 
						|
			self.c_cformat.clear_choice()
 | 
						|
			for label in self.all_comp_schemes:
 | 
						|
				self.c_cformat.addto_choice(label)
 | 
						|
			i = self.all_comp_schemes.index(self.comp_scheme)
 | 
						|
			self.c_cformat.set_choice(i+1)
 | 
						|
		# Audio defaults
 | 
						|
		self.aout = None
 | 
						|
		self.aport = None
 | 
						|
		self.c_aformat.clear_choice()
 | 
						|
		for label in AudioFormatLabels:
 | 
						|
			self.c_aformat.addto_choice(label)
 | 
						|
		self.c_aformat.set_choice(self.aformat)
 | 
						|
		self.get_aformat()
 | 
						|
 | 
						|
	def openvideo(self):
 | 
						|
		try:
 | 
						|
			self.video = sv.OpenVideo()
 | 
						|
		except sv.error, msg:
 | 
						|
			print 'Error opening video:', msg
 | 
						|
			self.video = None
 | 
						|
		param = [SV.BROADCAST, SV.PAL]
 | 
						|
		if self.video: self.video.GetParam(param)
 | 
						|
		if param[1] == SV.PAL:
 | 
						|
			x = SV.PAL_XMAX
 | 
						|
			y = SV.PAL_YMAX
 | 
						|
		elif param[1] == SV.NTSC:
 | 
						|
			x = SV.NTSC_XMAX
 | 
						|
			y = SV.NTSC_YMAX
 | 
						|
		else:
 | 
						|
			print 'Unknown video standard:', param[1]
 | 
						|
			sys.exit(1)
 | 
						|
		self.maxx, self.maxy = x, y
 | 
						|
		self.curx = 256
 | 
						|
		self.cury = 256*3/4
 | 
						|
 | 
						|
	def makewindow(self):
 | 
						|
		x, y = self.maxx, self.maxy
 | 
						|
		gl.foreground()
 | 
						|
		gl.maxsize(x, y)
 | 
						|
		gl.keepaspect(x, y)
 | 
						|
		gl.stepunit(8, 6)
 | 
						|
		width = self.curx
 | 
						|
		height = self.cury
 | 
						|
		if width and height:
 | 
						|
			# Place the window at (150, 150) from top left
 | 
						|
			# (the video board likes this location...)
 | 
						|
			x1 = 150
 | 
						|
			x2 = x1+width-1
 | 
						|
			SCRHEIGHT = 768
 | 
						|
			y2 = SCRHEIGHT-1-150
 | 
						|
			y1 = y2-height+1
 | 
						|
			gl.prefposition(x1, x2, y1, y2)
 | 
						|
		self.window = gl.winopen('Vb video')
 | 
						|
		self.settitle()
 | 
						|
		if width:
 | 
						|
			gl.maxsize(x, y)
 | 
						|
			gl.keepaspect(x, y)
 | 
						|
			gl.stepunit(8, 6)
 | 
						|
			gl.winconstraints()
 | 
						|
		gl.qdevice(DEVICE.LEFTMOUSE)
 | 
						|
		gl.qdevice(DEVICE.WINQUIT)
 | 
						|
		gl.qdevice(DEVICE.WINSHUT)
 | 
						|
 | 
						|
	def optfullsizewindow(self):
 | 
						|
		if not self.window:
 | 
						|
			return
 | 
						|
		gl.winset(self.window)
 | 
						|
		if self.use_24:
 | 
						|
			x, y = self.maxx, self.maxy
 | 
						|
		else:
 | 
						|
			x, y = self.curx, self.cury
 | 
						|
		left, bottom = gl.getorigin()
 | 
						|
		width, height = gl.getsize()
 | 
						|
		bottom = bottom+height-y
 | 
						|
		gl.prefposition(left, left+x-1, bottom, bottom+y-1)
 | 
						|
		gl.winconstraints()
 | 
						|
		if not self.use_24:
 | 
						|
			gl.keepaspect(x, y)
 | 
						|
			gl.stepunit(8, 6)
 | 
						|
			gl.maxsize(self.maxx, self.maxy)
 | 
						|
			gl.winconstraints()
 | 
						|
		self.bindvideo()
 | 
						|
 | 
						|
	def bindvideo(self):
 | 
						|
		if not self.video: return
 | 
						|
		x, y = gl.getsize()
 | 
						|
		if not self.use_24:
 | 
						|
			self.curx, self.cury = x, y
 | 
						|
		self.video.SetSize(x, y)
 | 
						|
		drop = self.b_drop.get_button()
 | 
						|
		if drop:
 | 
						|
			param = [SV.FIELDDROP, 1, SV.GENLOCK, SV.GENLOCK_OFF]
 | 
						|
		else:
 | 
						|
			param = [SV.FIELDDROP, 0, SV.GENLOCK, SV.GENLOCK_ON]
 | 
						|
		if self.rgb:
 | 
						|
			param = param+[SV.COLOR, SV.DEFAULT_COLOR, \
 | 
						|
				       SV.DITHER, 1, \
 | 
						|
				       SV.INPUT_BYPASS, 0]
 | 
						|
		else:
 | 
						|
			param = param+[SV.COLOR, SV.MONO, SV.DITHER, 0, \
 | 
						|
				       SV.INPUT_BYPASS, 1]
 | 
						|
		self.video.BindGLWindow(self.window, SV.IN_REPLACE)
 | 
						|
		self.video.SetParam(param)
 | 
						|
 | 
						|
	def rebindvideo(self):
 | 
						|
		gl.winset(self.window)
 | 
						|
		self.bindvideo()
 | 
						|
 | 
						|
	def reset(self):
 | 
						|
		self.close_video()
 | 
						|
		self.close_audio()
 | 
						|
		if self.vcr:
 | 
						|
			try:
 | 
						|
				ok = self.vcr.still()
 | 
						|
			except VCR.error:
 | 
						|
				pass
 | 
						|
			self.vcr = None
 | 
						|
		self.b_capture.set_button(0)
 | 
						|
 | 
						|
	# Event handler (catches resize of video window)
 | 
						|
 | 
						|
	def do_event(self, dev, val):
 | 
						|
		#print 'Event:', dev, val
 | 
						|
		if dev in (DEVICE.WINSHUT, DEVICE.WINQUIT):
 | 
						|
			self.close()
 | 
						|
		if dev == DEVICE.REDRAW and val == self.window:
 | 
						|
			self.rebindvideo()
 | 
						|
			self.settitle()
 | 
						|
 | 
						|
	# Video controls: format, mode, file
 | 
						|
 | 
						|
	def cb_vformat(self, *args):
 | 
						|
		self.reset()
 | 
						|
		self.get_vformat()
 | 
						|
		if self.mono_use_thresh:
 | 
						|
			s = `self.mono_thresh`
 | 
						|
			s = fl.show_input('Please enter mono threshold', s)
 | 
						|
			if s:
 | 
						|
				try:
 | 
						|
					self.mono_thresh = string.atoi(s)
 | 
						|
				except string.atoi_error:
 | 
						|
					fl.show_message('Bad input, using', \
 | 
						|
						  `self.mono_thresh`, '')
 | 
						|
		self.rebindvideo()
 | 
						|
 | 
						|
	def cb_cformat(self, *args):
 | 
						|
		i = self.c_cformat.get_choice()
 | 
						|
		self.comp_scheme = self.all_comp_schemes[i-1]
 | 
						|
 | 
						|
		
 | 
						|
	def cb_vmode(self, *args):
 | 
						|
		if self.vcr:
 | 
						|
			self.vcr = None
 | 
						|
		self.vmode = self.c_vmode.get_choice()
 | 
						|
		self.form.freeze_form()
 | 
						|
		self.g_cont.hide_object()
 | 
						|
		self.g_burst.hide_object()
 | 
						|
		self.g_single.hide_object()
 | 
						|
		self.g_vcr.hide_object()
 | 
						|
		if self.vmode == VM_CONT:
 | 
						|
			self.g_cont.show_object()
 | 
						|
		elif self.vmode == VM_BURST:
 | 
						|
			self.g_burst.show_object()
 | 
						|
		elif self.vmode == VM_SINGLE:
 | 
						|
			self.g_single.show_object()
 | 
						|
		elif self.vmode == VM_VCR:
 | 
						|
			self.g_vcr.show_object()
 | 
						|
		self.form.unfreeze_form()
 | 
						|
 | 
						|
	def cb_vfile(self, *args):
 | 
						|
		filename = self.vfile
 | 
						|
		hd, tl = os.path.split(filename)
 | 
						|
		filename = fl.file_selector('Video save file:', hd, '', tl)
 | 
						|
		if filename:
 | 
						|
			self.reset()
 | 
						|
			hd, tl = os.path.split(filename)
 | 
						|
			if hd == os.getcwd():
 | 
						|
				filename = tl
 | 
						|
			self.vfile = filename
 | 
						|
 | 
						|
	# Video mode specific video controls
 | 
						|
 | 
						|
	def cb_rate(self, *args):
 | 
						|
		pass
 | 
						|
 | 
						|
	def cb_drop(self, *args):
 | 
						|
		self.rebindvideo()
 | 
						|
 | 
						|
	def cb_maxmem(self, *args):
 | 
						|
		pass
 | 
						|
 | 
						|
	def cb_nframes(self, *args):
 | 
						|
		pass
 | 
						|
 | 
						|
	def cb_fps(self, *args):
 | 
						|
		pass
 | 
						|
 | 
						|
	def cb_nframes_vcr(self, *args):
 | 
						|
		pass
 | 
						|
 | 
						|
	def cb_rate_vcr(self, *args):
 | 
						|
		pass
 | 
						|
 | 
						|
	def cb_vcrspeed(self, *args):
 | 
						|
		pass
 | 
						|
 | 
						|
	def cb_rgb24_size(self, *args):
 | 
						|
		i = self.c_rgb24_size.get_choice()
 | 
						|
		if i:
 | 
						|
			self.rgb24_size = i
 | 
						|
 | 
						|
	# Audio controls: format, file
 | 
						|
 | 
						|
	def cb_aformat(self, *args):
 | 
						|
		self.get_aformat()
 | 
						|
 | 
						|
	def cb_afile(self, *args):
 | 
						|
		filename = self.afile
 | 
						|
		hd, tl = os.path.split(filename)
 | 
						|
		filename = fl.file_selector('Audio save file:', hd, '', tl)
 | 
						|
		if filename:
 | 
						|
			self.reset()
 | 
						|
			hd, tl = os.path.split(filename)
 | 
						|
			if hd == os.getcwd():
 | 
						|
				filename = tl
 | 
						|
			self.afile = filename
 | 
						|
 | 
						|
	# General controls: capture, reset, play, quit
 | 
						|
 | 
						|
	def cb_capture(self, *args):
 | 
						|
		if self.capturing:
 | 
						|
			raise StopCapture
 | 
						|
		if not self.b_capture.get_button():
 | 
						|
			return
 | 
						|
		if not self.video or not self.vformat:
 | 
						|
			gl.ringbell()
 | 
						|
			return
 | 
						|
		if self.vmode == VM_CONT:
 | 
						|
			self.cont_capture()
 | 
						|
		elif self.vmode == VM_BURST:
 | 
						|
			self.burst_capture()
 | 
						|
		elif self.vmode == VM_SINGLE:
 | 
						|
			self.single_capture(None, None)
 | 
						|
		elif self.vmode == VM_VCR:
 | 
						|
			self.vcr_capture()
 | 
						|
 | 
						|
	def cb_reset(self, *args):
 | 
						|
		self.reset()
 | 
						|
 | 
						|
	def cb_play(self, *args):
 | 
						|
		self.reset()
 | 
						|
		sts = os.system('Vplay -q ' + self.vfile + ' &')
 | 
						|
 | 
						|
	def cb_quit(self, *args):
 | 
						|
		self.close()
 | 
						|
 | 
						|
	# Capture routines
 | 
						|
 | 
						|
	def burst_capture(self):
 | 
						|
		self.setwatch()
 | 
						|
		gl.winset(self.window)
 | 
						|
		x, y = gl.getsize()
 | 
						|
		if self.use_24:
 | 
						|
			fl.show_message('Sorry, no 24 bit continuous capture yet', '', '')
 | 
						|
			return
 | 
						|
		vformat = SV.RGB8_FRAMES
 | 
						|
		nframes = self.getint(self.in_nframes, 0)
 | 
						|
		if nframes == 0:
 | 
						|
			maxmem = self.getint(self.in_maxmem, 1.0)
 | 
						|
			memsize = int(maxmem * 1024 * 1024)
 | 
						|
			nframes = self.calcnframes(memsize)
 | 
						|
		info = (vformat, x, y, nframes, 1)
 | 
						|
		try:
 | 
						|
			info2, data, bitvec = self.video.CaptureBurst(info)
 | 
						|
		except sv.error, msg:
 | 
						|
			self.b_capture.set_button(0)
 | 
						|
			self.setarrow()
 | 
						|
			fl.show_message('Capture error:', str(msg), '')
 | 
						|
			return
 | 
						|
		if info <> info2: print info, '<>', info2
 | 
						|
		self.save_burst(info2, data, bitvec)
 | 
						|
		self.setarrow()
 | 
						|
 | 
						|
	def calcnframes(self, memsize):
 | 
						|
		gl.winset(self.window)
 | 
						|
		x, y = gl.getsize()
 | 
						|
		pixels = x*y
 | 
						|
		pixels = pixels/2	# XXX always assume fields
 | 
						|
		if self.mono or self.grey:
 | 
						|
			n = memsize/pixels
 | 
						|
		else:
 | 
						|
			n = memsize/(4*pixels)
 | 
						|
		return max(1, n)
 | 
						|
 | 
						|
	def save_burst(self, info, data, bitvec):
 | 
						|
		(vformat, x, y, nframes, rate) = info
 | 
						|
		self.open_if_closed()
 | 
						|
		fieldsize = x*y/2
 | 
						|
		nskipped = 0
 | 
						|
		realframeno = 0
 | 
						|
		tpf = 1000 / 50.0     # XXX
 | 
						|
		for frameno in range(0, nframes*2):
 | 
						|
			if frameno <> 0 and \
 | 
						|
				  bitvec[frameno] == bitvec[frameno-1]:
 | 
						|
				nskipped = nskipped + 1
 | 
						|
				continue
 | 
						|
			#
 | 
						|
			# Save field.
 | 
						|
			# XXX Works only for fields and top-to-bottom
 | 
						|
			#
 | 
						|
			start = frameno*fieldsize
 | 
						|
			field = data[start:start+fieldsize]
 | 
						|
			realframeno = realframeno + 1
 | 
						|
			fn = int(realframeno*tpf)
 | 
						|
			if not self.write_frame(fn, field):
 | 
						|
				break
 | 
						|
 | 
						|
	def cont_capture(self):
 | 
						|
		saved_label = self.b_capture.label
 | 
						|
		self.b_capture.label = 'Stop\n' + saved_label
 | 
						|
		self.open_if_closed()
 | 
						|
		self.init_cont()
 | 
						|
		fps = 59.64		# Fields per second
 | 
						|
		# XXX (fps of Indigo monitor, not of PAL or NTSC!)
 | 
						|
		tpf = 1000.0 / fps	# Time per field in msec
 | 
						|
		self.capturing = 1
 | 
						|
		self.start_audio()
 | 
						|
		while 1:
 | 
						|
			try:
 | 
						|
				void = fl.check_forms()
 | 
						|
			except StopCapture:
 | 
						|
				break
 | 
						|
			try:
 | 
						|
				cd, id = self.video.GetCaptureData()
 | 
						|
			except sv.error:
 | 
						|
				sgi.nap(1)
 | 
						|
				continue
 | 
						|
			id = id + 2*self.rate
 | 
						|
			data = cd.InterleaveFields(1)
 | 
						|
			cd.UnlockCaptureData()
 | 
						|
			t = id*tpf
 | 
						|
			if not self.write_frame(t, data):
 | 
						|
				break
 | 
						|
		self.stop_audio()
 | 
						|
		self.capturing = 0
 | 
						|
		self.end_cont()
 | 
						|
		if self.aout:
 | 
						|
			# If recording audio, can't capture multiple sequences
 | 
						|
			self.reset()
 | 
						|
		self.b_capture.label = saved_label
 | 
						|
 | 
						|
	def single_capture(self, stepfunc, timecode):
 | 
						|
		self.open_if_closed()
 | 
						|
		self.init_cont()
 | 
						|
		while 1:
 | 
						|
			try:
 | 
						|
				cd, id = self.video.GetCaptureData()
 | 
						|
				break
 | 
						|
			except sv.error:
 | 
						|
				pass
 | 
						|
			sgi.nap(1)
 | 
						|
			if stepfunc:		# This might step the video
 | 
						|
				d=stepfunc()	# to the next frame
 | 
						|
		if not self.use_24:
 | 
						|
			data = cd.InterleaveFields(1)
 | 
						|
		else:
 | 
						|
			x, y = self.vout.getsize()
 | 
						|
			if self.use_compress:
 | 
						|
				if self.rgb24_size == 1:
 | 
						|
					data = cd.YUVtoYUV422DC(0)
 | 
						|
				elif self.rgb24_size == 2:
 | 
						|
					data = cd.YUVtoYUV422DC_quarter(1)
 | 
						|
					x = x/2
 | 
						|
					y = y/2
 | 
						|
				elif self.rgb24_size == 3:
 | 
						|
					data = cd.YUVtoYUV422DC_sixteenth(1)
 | 
						|
					x = x/4
 | 
						|
					y = y/4
 | 
						|
			else:
 | 
						|
				data = cd.YUVtoRGB(1)
 | 
						|
				if self.maxx*self.maxy*4 <> len(data):
 | 
						|
					print 'maxx,maxy,exp,got=', self.maxx,
 | 
						|
					print self.maxy,self.maxx*self.maxy*4,
 | 
						|
					print len(data)
 | 
						|
					fl.showmessage('Wrong sized data')
 | 
						|
					return 0
 | 
						|
				if self.rgb24_size <> 1:
 | 
						|
					data = imageop.scale(data, 4, \
 | 
						|
						  self.maxx, self.maxy, x, y)
 | 
						|
			if self.use_jpeg:
 | 
						|
				import jpeg
 | 
						|
				data = jpeg.compress(data, x, y, 4)
 | 
						|
			if self.use_compress:
 | 
						|
				data = self.compressor.Compress(1, data)
 | 
						|
		cd.UnlockCaptureData()
 | 
						|
		self.end_cont()
 | 
						|
		if timecode == None:
 | 
						|
			timecode = (self.nframes+1) * (1000/25)
 | 
						|
		return self.write_frame(timecode, data)
 | 
						|
 | 
						|
	def vcr_capture(self):
 | 
						|
		if not self.vcr:
 | 
						|
			try:
 | 
						|
				print 'Connecting to VCR ...'
 | 
						|
				self.vcr = VCR.VCR()
 | 
						|
				print 'Waiting for VCR to come online ...'
 | 
						|
				self.vcr.initvcr()
 | 
						|
				print 'Preparing VCR ...'
 | 
						|
				if not (self.vcr.fmmode('dnr') and \
 | 
						|
					  self.vcr.dmcontrol('digital slow')):
 | 
						|
					self.vcr_error('digital slow failed')
 | 
						|
					return
 | 
						|
				print 'VCR OK.'
 | 
						|
			except VCR.error, msg:
 | 
						|
				self.vcr = None
 | 
						|
				self.vcr_error(msg)
 | 
						|
				return
 | 
						|
		if not self.vcr.still():
 | 
						|
			self.vcr_error('still failed')
 | 
						|
			return
 | 
						|
		self.open_if_closed()
 | 
						|
		rate = self.getint(self.in_rate_vcr, 1)
 | 
						|
		rate = max(rate, 1)
 | 
						|
		vcrspeed = self.c_vcrspeed.get_choice()
 | 
						|
		vcrspeed = VcrSpeeds[vcrspeed]
 | 
						|
		if vcrspeed == 0:
 | 
						|
			stepfunc = self.vcr.step
 | 
						|
		else:
 | 
						|
			stepfunc = None
 | 
						|
		self.speed_factor = rate
 | 
						|
		addr = start_addr = self.vcr.sense()
 | 
						|
		if not self.single_capture(None, 0):
 | 
						|
			return
 | 
						|
		print 'captured %02d:%02d:%02d:%02d' % self.vcr.addr2tc(addr)
 | 
						|
		count = self.getint(self.in_nframes_vcr, 1) - 1
 | 
						|
		if count <= 0:
 | 
						|
			while rate > 0:
 | 
						|
				if not self.vcr.step():
 | 
						|
					self.vcr_error('step failed')
 | 
						|
				here = self.vcr.sense()
 | 
						|
				if here > addr:
 | 
						|
					rate = rate - (here - addr)
 | 
						|
				addr = here
 | 
						|
			return
 | 
						|
		if not self.vcr.fwdshuttle(vcrspeed):
 | 
						|
			self.vcr_error('fwd shuttle failed')
 | 
						|
			return
 | 
						|
		cycle = 0
 | 
						|
		while count > 0:
 | 
						|
			try:
 | 
						|
				here = self.vcr.sense()
 | 
						|
			except VCR.error, msg:
 | 
						|
				self.vcr_error(msg)
 | 
						|
				break
 | 
						|
			if here <> addr:
 | 
						|
				if here <> addr+1:
 | 
						|
					print 'Missed', here-addr-1,
 | 
						|
					print 'frame' + 's'*(here-addr-1 <> 1)
 | 
						|
				cycle = (cycle+1) % rate
 | 
						|
				if cycle == 0:
 | 
						|
					tc = (here-start_addr)*40
 | 
						|
					if not self.single_capture(stepfunc, \
 | 
						|
						  tc):
 | 
						|
						break
 | 
						|
					print 'captured %02d:%02d:%02d:%02d' \
 | 
						|
						  % self.vcr.addr2tc(here)
 | 
						|
					count = count -1
 | 
						|
				addr = here
 | 
						|
		if self.vcr and not self.vcr.still():
 | 
						|
			self.vcr_error('still failed')
 | 
						|
 | 
						|
	def vcr_error(self, msg):
 | 
						|
		self.reset()
 | 
						|
		fl.show_message('VCR error:', str(msg), '')
 | 
						|
 | 
						|
	# Init/end continuous capture mode
 | 
						|
 | 
						|
	def init_cont(self):
 | 
						|
		qsize = 1
 | 
						|
		if self.vmode == VM_CONT:
 | 
						|
			self.rate = self.getint(self.in_rate, 2)
 | 
						|
		else:
 | 
						|
			self.rate = 2
 | 
						|
		x, y = self.vout.getsize()
 | 
						|
		if self.use_24:
 | 
						|
			info = (SV.YUV411_FRAMES, x, y, qsize, self.rate)
 | 
						|
		else:
 | 
						|
			info = (SV.RGB8_FRAMES, x, y, qsize, self.rate)
 | 
						|
		info2 = self.video.InitContinuousCapture(info)
 | 
						|
		if info2 <> info:
 | 
						|
			# XXX This is really only debug info
 | 
						|
			print 'Info mismatch: requested', info, 'got', info2
 | 
						|
 | 
						|
	def end_cont(self):
 | 
						|
		self.video.EndContinuousCapture()
 | 
						|
 | 
						|
	# Misc stuff
 | 
						|
 | 
						|
	def settitle(self):
 | 
						|
		gl.winset(self.window)
 | 
						|
		x, y = gl.getsize()
 | 
						|
		title = 'Vb ' + self.vfile + ' (%dx%d)' % (x, y)
 | 
						|
		gl.wintitle(title)
 | 
						|
 | 
						|
	def get_vformat(self):
 | 
						|
		i = self.c_vformat.get_choice()
 | 
						|
		label = VideoFormatLabels[i-1]
 | 
						|
		format = VideoFormats[i-1]
 | 
						|
		if format == 'compress' and cl == None:
 | 
						|
			fl.show_message('Sorry, no compression library support')
 | 
						|
			format = ''
 | 
						|
			label = 'Video off'
 | 
						|
		self.vformat = format
 | 
						|
		if self.vformat == '':
 | 
						|
			self.form.freeze_form()
 | 
						|
			self.g_video.hide_object()
 | 
						|
			self.g_cont.hide_object()
 | 
						|
			self.g_burst.hide_object()
 | 
						|
			self.g_single.hide_object()
 | 
						|
			self.form.unfreeze_form()
 | 
						|
		else:
 | 
						|
			self.g_video.show_object()
 | 
						|
			if self.vmode == VM_CONT:
 | 
						|
				self.g_cont.show_object()
 | 
						|
			elif self.vmode == VM_BURST:
 | 
						|
				self.g_burst.show_object()
 | 
						|
			elif self.vmode == VM_SINGLE:
 | 
						|
				self.g_single.show_object()
 | 
						|
		#
 | 
						|
		self.rgb = (format[:3] == 'rgb' or format == 'compress')
 | 
						|
		self.mono = (format == 'mono')
 | 
						|
		self.grey = (format[:4] == 'grey')
 | 
						|
		self.use_24 = (format in ('rgb', 'jpeg', 'compress'))
 | 
						|
		if self.use_24:
 | 
						|
			self.g_rgb24.show_object()
 | 
						|
		else:
 | 
						|
			self.g_rgb24.hide_object()
 | 
						|
		self.use_jpeg = (format == 'jpeg')
 | 
						|
		self.mono_use_thresh = (label == 'mono thresh')
 | 
						|
		self.use_compress = (format == 'compress')
 | 
						|
		if self.use_compress:
 | 
						|
			self.g_compress.show_object()
 | 
						|
		else:
 | 
						|
			self.g_compress.hide_object()
 | 
						|
		s = format[4:]
 | 
						|
		if self.grey and s:
 | 
						|
			self.greybits = string.atoi(s)
 | 
						|
		else:
 | 
						|
			self.greybits = 8
 | 
						|
		if label == 'grey2 dith':
 | 
						|
			self.greybits = -2
 | 
						|
		#
 | 
						|
		convertor = None
 | 
						|
		if self.grey:
 | 
						|
			if self.greybits == 2:
 | 
						|
				convertor = imageop.grey2grey2
 | 
						|
			elif self.greybits == 4:
 | 
						|
				convertor = imageop.grey2grey4
 | 
						|
			elif self.greybits == -2:
 | 
						|
				convertor = imageop.dither2grey2
 | 
						|
		self.convertor = convertor
 | 
						|
		self.optfullsizewindow()
 | 
						|
 | 
						|
	def get_aformat(self):
 | 
						|
		self.reset()
 | 
						|
		self.aformat = self.c_aformat.get_choice()
 | 
						|
		if self.aformat == A_OFF:
 | 
						|
			self.g_audio.hide_object()
 | 
						|
		else:
 | 
						|
			self.g_audio.show_object()
 | 
						|
 | 
						|
	def init_compressor(self, w, h):
 | 
						|
		self.compressor = None
 | 
						|
		scheme = cl.QuerySchemeFromName(cl.VIDEO, self.comp_scheme)
 | 
						|
		self.compressor = cl.OpenCompressor(scheme)
 | 
						|
		parambuf = [cl.IMAGE_WIDTH, w, \
 | 
						|
			  cl.IMAGE_HEIGHT, h, \
 | 
						|
			  cl.ORIGINAL_FORMAT, cl.YUV422DC]
 | 
						|
		self.compressor.SetParams(parambuf)
 | 
						|
		return self.compressor.Compress(0, '')
 | 
						|
 | 
						|
	def open_if_closed(self):
 | 
						|
		if not self.vout:
 | 
						|
			self.open_video()
 | 
						|
		if not self.aout:
 | 
						|
			self.open_audio()
 | 
						|
 | 
						|
	# File I/O handling
 | 
						|
 | 
						|
	def open_video(self):
 | 
						|
		self.close_video()
 | 
						|
		gl.winset(self.window)
 | 
						|
		x, y = gl.getsize()
 | 
						|
		if self.use_24:
 | 
						|
			if self.rgb24_size == 2:
 | 
						|
				x, y = x/2, y/2
 | 
						|
			elif self.rgb24_size == 3:
 | 
						|
				x, y = x/4, y/4
 | 
						|
		vout = VFile.VoutFile(self.vfile)
 | 
						|
		vout.setformat(self.vformat)
 | 
						|
		if self.vformat == 'compress':
 | 
						|
			cheader = self.init_compressor(x, y)
 | 
						|
			vout.setcompressheader(cheader)
 | 
						|
		vout.setsize(x, y)
 | 
						|
		if self.vmode == VM_BURST:
 | 
						|
			vout.setpf((1, -2))
 | 
						|
		vout.writeheader()
 | 
						|
		self.vout = vout
 | 
						|
		self.nframes = 0
 | 
						|
		self.speed_factor = 1
 | 
						|
		self.t_nframes.label = `self.nframes`
 | 
						|
 | 
						|
	def write_frame(self, t, data):
 | 
						|
		t = t * self.speed_factor
 | 
						|
		if not self.vout:
 | 
						|
			gl.ringbell()
 | 
						|
			return 0
 | 
						|
		if self.convertor:
 | 
						|
			data = self.convertor(data, len(data), 1)
 | 
						|
		elif self.mono:
 | 
						|
			if self.mono_use_thresh:
 | 
						|
				data = imageop.grey2mono(data, \
 | 
						|
					  len(data), 1,\
 | 
						|
					  self.mono_thresh)
 | 
						|
			else:
 | 
						|
				data = imageop.dither2mono(data, \
 | 
						|
					  len(data), 1)
 | 
						|
		try:
 | 
						|
			self.vout.writeframe(int(t), data, None)
 | 
						|
		except IOError, msg:
 | 
						|
			self.reset()
 | 
						|
			if msg == (0, 'Error 0'):
 | 
						|
				msg = 'disk full??'
 | 
						|
			fl.show_message('IOError', str(msg), '')
 | 
						|
			return 0
 | 
						|
		self.nframes = self.nframes + 1
 | 
						|
		self.t_nframes.label = `self.nframes`
 | 
						|
		return 1
 | 
						|
 | 
						|
	def close_video(self):
 | 
						|
		if not self.vout:
 | 
						|
			return
 | 
						|
		self.nframes = 0
 | 
						|
		self.t_nframes.label = ''
 | 
						|
		try:
 | 
						|
			self.vout.close()
 | 
						|
		except IOError, msg:
 | 
						|
			if msg == (0, 'Error 0'):
 | 
						|
				msg = 'disk full??'
 | 
						|
			fl.show_message('IOError', str(msg), '')
 | 
						|
		self.vout = None
 | 
						|
		self.compressor = None
 | 
						|
 | 
						|
	# Watch cursor handling
 | 
						|
 | 
						|
	def setwatch(self):
 | 
						|
		gl.winset(self.form.window)
 | 
						|
		gl.setcursor(WATCH, 0, 0)
 | 
						|
		gl.winset(self.window)
 | 
						|
		gl.setcursor(WATCH, 0, 0)
 | 
						|
 | 
						|
	def setarrow(self):
 | 
						|
		gl.winset(self.form.window)
 | 
						|
		gl.setcursor(ARROW, 0, 0)
 | 
						|
		gl.winset(self.window)
 | 
						|
		gl.setcursor(ARROW, 0, 0)
 | 
						|
 | 
						|
	# Numeric field handling
 | 
						|
 | 
						|
	def getint(self, field, default):
 | 
						|
		try:
 | 
						|
			value = string.atoi(field.get_input())
 | 
						|
		except string.atoi_error:
 | 
						|
			value = default
 | 
						|
		field.set_input(`value`)
 | 
						|
		return value
 | 
						|
 | 
						|
	def getfloat(self, field, default):
 | 
						|
		try:
 | 
						|
			value = float(eval(field.get_input()))
 | 
						|
		except:
 | 
						|
			value = float(default)
 | 
						|
		field.set_input(`value`)
 | 
						|
		return value
 | 
						|
 | 
						|
	# Audio stuff
 | 
						|
 | 
						|
	def open_audio(self):
 | 
						|
		if self.aformat == A_OFF:
 | 
						|
			return
 | 
						|
		import aifc
 | 
						|
		import al
 | 
						|
		import AL
 | 
						|
		import thread
 | 
						|
		self.close_audio()
 | 
						|
		params = [AL.INPUT_RATE, 0]
 | 
						|
		al.getparams(AL.DEFAULT_DEVICE, params)
 | 
						|
		rate = params[1]
 | 
						|
		self.aout = aifc.open(self.afile, 'w')
 | 
						|
		if self.aformat in (A_16_STEREO, A_8_STEREO):
 | 
						|
			nch = AL.STEREO
 | 
						|
		else:
 | 
						|
			nch = AL.MONO
 | 
						|
		if self.aformat in (A_16_STEREO, A_16_MONO):
 | 
						|
			width = AL.SAMPLE_16
 | 
						|
		else:
 | 
						|
			width = AL.SAMPLE_8
 | 
						|
		self.aout.setnchannels(nch)
 | 
						|
		self.aout.setsampwidth(width)
 | 
						|
		self.aout.setframerate(rate)
 | 
						|
		c = al.newconfig()
 | 
						|
		c.setqueuesize(8000)
 | 
						|
		c.setchannels(nch)
 | 
						|
		c.setwidth(width)
 | 
						|
		self.aport = al.openport('Vb audio record', 'r', c)
 | 
						|
		self.audio_stop = 0
 | 
						|
		self.audio_ok = 0
 | 
						|
		self.audio_busy = 1
 | 
						|
		thread.start_new_thread(self.record_audio, ())
 | 
						|
 | 
						|
	def start_audio(self):
 | 
						|
		if self.aformat == A_OFF:
 | 
						|
			return
 | 
						|
		self.audio_ok = 1
 | 
						|
 | 
						|
	def record_audio(self, *args):
 | 
						|
		# This function runs in a separate thread
 | 
						|
		# Currently no semaphores are used
 | 
						|
		while not self.audio_stop:
 | 
						|
			data = self.aport.readsamps(4000)
 | 
						|
			if self.audio_ok:
 | 
						|
				self.aout.writeframes(data)
 | 
						|
			data = None
 | 
						|
		self.audio_busy = 0
 | 
						|
 | 
						|
	def stop_audio(self):
 | 
						|
		self.audio_ok = 0
 | 
						|
 | 
						|
	def close_audio(self):
 | 
						|
		if self.aout:
 | 
						|
			self.audio_ok = 0
 | 
						|
			self.audio_stop = 1
 | 
						|
			while self.audio_busy:
 | 
						|
				time.sleep(0.1)
 | 
						|
			self.aout.close()
 | 
						|
			self.aout = None
 | 
						|
		if self.aport:
 | 
						|
			self.aport.closeport()
 | 
						|
			self.aport = None
 | 
						|
 | 
						|
 | 
						|
try:
 | 
						|
	main()
 | 
						|
except KeyboardInterrupt:
 | 
						|
	print '[Interrupt]'
 | 
						|
	sys.exit(1)
 |