summaryrefslogtreecommitdiffstats
path: root/Demo/sgi/video/LiveVideoIn.py
blob: 661ea738b27935c46f48673151d90da8286c8058 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
# Live video input class.
# Note that importing this module attempts to initialize video.


# Check if video is available.
# There are three reasons for failure here:
# (1) this version of Python may not have the sv or imageop modules;
# (2) this machine may not have a video board;
# (3) initializing the video board may fail for another reason.
# The global variable have_video is set to true iff we reall do have video.

try:
	import sv
	import SV
	import imageop
	try:
		v = sv.OpenVideo()
		have_video = 1
	except sv.error:
		have_video = 0
except ImportError:
	have_video = 0


# The live video input class.
# Only instantiate this if have_video is true!

class LiveVideoIn:

	# Initialize an instance.  Arguments:
	# vw, vh: size of the video window data to be captured.
	# For some reason, vw MUST be a multiple of 4.
	# Note that the data has to be cropped unless vw and vh are
	# just right for the video board (vw:vh == 4:3 and vh even).

	def __init__(self, pktmax, vw, vh, type):
		if not have_video:
			raise RuntimeError, 'no video available'
		if vw % 4 != 0:
			raise ValueError, 'vw must be a multiple of 4'
		self.pktmax = pktmax
		realvw = vh*SV.PAL_XMAX/SV.PAL_YMAX
		if realvw < vw:
			realvw = vw
		self.realwidth, self.realheight = v.QuerySize(realvw, vh)
		if not type in ('rgb8', 'grey', 'mono', 'grey2', 'grey4'):
			raise 'Incorrent video data type', type
		self.type = type
		if type in ('grey', 'grey4', 'grey2', 'mono'):
			v.SetParam([SV.COLOR, SV.MONO, SV.INPUT_BYPASS, 1])
		else:
			v.SetParam([SV.COLOR, SV.DEFAULT_COLOR, \
				  SV.INPUT_BYPASS, 0])
		# Initialize capture
		(mode, self.realwidth, self.realheight, qsize, rate) = \
			v.InitContinuousCapture(SV.RGB8_FRAMES, \
				self.realwidth, self.realheight, 1, 2)
		self.width = vw
		self.height = vh
		self.x0 = (self.realwidth-self.width)/2
		self.x1 = self.x0 + self.width - 1
		self.y0 = (self.realheight-self.height)/2
		self.y1 = self.y0 + self.height - 1
		# Compute # full lines per packet
		self.lpp = pktmax / self.linewidth()
		self.pktsize = self.lpp*self.linewidth()
		self.data = None
		self.dataoffset = 0
		self.lpos = 0
		self.justright = (self.realwidth == self.width and \
			self.realheight == self.height)
##		if not self.justright:
##			print 'Want:', self.width, 'x', self.height,
##			print '; grab:', self.realwidth, 'x', self.realheight

	# Change the size of the video being displayed.

	def resizevideo(self, vw, vh):
		self.close()
		self.__init__(self.pktmax, vw, vh, self.type)

	# Remove an instance.
	# This turns off continuous capture.

	def close(self):
		v.EndContinuousCapture()

	# Get the length in bytes of a video line
	def linewidth(self):
		if self.type == 'mono':
			return (self.width+7)/8
		elif self.type == 'grey2':
			return (self.width+3)/4
		elif self.type == 'grey4':
			return (self.width+1)/2
		else:
			return self.width

	# Get the next video packet.
	# This returns (lpos, data) where:
	# - lpos is the line position
	# - data is a piece of data
	# The dimensions of data are:
	# - pixel depth = 1 byte
	# - scan line width = self.width (the vw argument to __init__())
	# - number of scan lines = self.lpp (PKTMAX / vw)

	def getnextpacket(self):
		if not self.data or self.dataoffset >= len(self.data):
			try:
				cd, id = v.GetCaptureData()
			except sv.error:
				return None
			data = cd.InterleaveFields(1)
			cd.UnlockCaptureData()
			if self.justright:
				self.data = data
			else:
				self.data = imageop.crop(data, 1, \
					  self.realwidth, \
					  self.realheight, \
					  self.x0, self.y0, \
					  self.x1, self.y1)
			self.lpos = 0
			self.dataoffset = 0
			if self.type == 'mono':
				self.data = imageop.dither2mono(self.data, \
					  self.width, self.height)
			elif self.type == 'grey2':
				self.data = imageop.dither2grey2(self.data, \
					  self.width, self.height)
			elif self.type == 'grey4':
				self.data = imageop.grey2grey4(self.data, \
					  self.width, self.height)
		data = self.data[self.dataoffset:self.dataoffset+self.pktsize]
		lpos = self.lpos
		self.dataoffset = self.dataoffset + self.pktsize
		self.lpos = self.lpos + self.lpp
		return lpos, data