1
2
3
4 import gst
5
6 from twisted.python import log
7
8 from sparked import events
9 from sparked.hardware import hal
13 """
14 Video device monitor.
15 """
16 subsystem = "video4linux"
17 uniquePath = "/dev/v4l/by-id/"
18
21
22 videoEvents = events.EventDispatcher()
23 """ Event dispatcher for serial events """
28 """
29 Represents a V4L video input device.
30 """
31
32 - def __init__(self, device, v4l2version=2):
33 self.preferMimes = ["image/jpeg", "video/x-raw-yuv", "video/x-raw-rgb"]
34 self.setDevice(device, v4l2version)
35
36
38 """
39 Find out the resolutions of the device
40 """
41
42 pipe = gst.parse_launch("%s name=source device=%s ! fakesink" % (self.gstSrc, self.device))
43 pipe.set_state(gst.STATE_PAUSED)
44 caps = pipe.get_by_name("source").get_pad("src").get_caps()
45
46 self._resolutions = []
47
48 for struct in caps:
49 if struct.get_name() not in self.preferMimes:
50 log.msg("mime \"%s\" currently not supported." % struct.get_name())
51 continue
52 if not isinstance(struct["width"], int):
53 log.msg("\"range\" resolutions currently not supported.")
54 continue
55 if type(struct["framerate"]) == list:
56 fr = min(struct["framerate"])
57 else:
58 fr = struct["framerate"]
59 r = {'mime': struct.get_name(),
60 'width': struct['width'],
61 'height': struct['height'],
62 'framerate': fr}
63 self.resolutions.append(r)
64 pipe.set_state(gst.STATE_NULL)
65
66
67 @property
69 if self._resolutions is None:
70 self._probe()
71 return self._resolutions
72
73
75 """
76 Set the device
77 """
78 self.device = device
79
80 self.v4l2version = v4l2version
81 if str(self.v4l2version) == '2':
82 self.gstSrc = "v4l2src"
83 else:
84 self.gstSrc = "v4lsrc"
85 self._resolutions = None
86
87
89 """
90 Optionally given a mime, get the highest possible resolution, without
91 taking framerate into account. Returns a resolution dict.
92 """
93 mxres = 0
94 mx = None
95 pref = self.preferMimes
96 for r in self.resolutions:
97 if mime and r['mime'] != mime:
98 continue
99 if not mx or r['width']*r['height']>mxres:
100 mx = r
101 mxres = r['width']*r['height']
102 elif r['width']*r['height']==mxres and float(r['framerate'])>float(mx['framerate']):
103 mx = r
104 elif r['width']*r['height']==mxres and float(r['framerate'])==float(mx['framerate']) and pref.index(r['mime'])<pref.index(mx['mime']):
105 mx = r
106 return mx
107
108
110 """
111 Optionally given a mime, get the fastest possible resolution, without
112 taking resolution into account. Returns a resolution dict.
113 """
114 mxfr = None
115 mx = None
116 pref = self.preferMimes
117 for r in self.resolutions:
118 if mime and r['mime'] != mime:
119 continue
120 if not mx or float(r['framerate'])>float(mxfr):
121 mx = r
122 mxfr = r['framerate']
123 elif float(r['framerate'])==float(mxfr) and r['width']*r['height']>mx['width']*mx['height']:
124 mx = r
125 elif float(r['framerate'])==float(mxfr) and r['width']*r['height']==mx['width']*mx['height'] and pref.index(r['mime'])<pref.index(mx['mime']):
126 mx = r
127
128 return mx
129
130
132 """
133 Return the best supported video mime type.
134 """
135 mime = None
136 pref = self.preferMimes
137 for r in self.resolutions:
138 if not mime or pref.index(mime) > pref.index(r['mime']):
139 mime = r['mime']
140 return mime
141
142
144 if resolution == "auto" or resolution == "highest":
145 return self.getHighestResolution(mime)
146 if resolution == "fastest":
147 return self.getFastestResolution(mime)
148
149 w,h = parseResolution(resolution)
150 mx = None
151 pref = self.preferMimes
152 for r in self.resolutions:
153 if r['width'] != w or r['height'] != h:
154 continue
155 if mime and r['mime'] != mime:
156 continue
157 if not mx:
158 mx = r
159 elif pref.index(mx['mime']) > pref.index(r['mime']):
160 mx = r
161 return mx
162
163
164 - def getPipeline(self, outputMime=None, resolution="auto"):
165 """
166 Construct a string which is parsable as the "input" part of the pipeline for a gstreamer camera.
167 """
168
169 r = self.getResolution(resolution)
170 if r is None:
171 raise ValueError("Unsupported resolution: "+resolution)
172 w, h = r['width'], r['height']
173 inputMime = r['mime']
174 framerate = r['framerate']
175
176 if outputMime is None:
177 outputMime = inputMime
178
179 pipe = "%s device=%s ! %s,width=%d,height=%d,framerate=%d/%d" % (self.gstSrc, self.device, inputMime, w, h, framerate.num, framerate.denom)
180
181 if inputMime == outputMime:
182 return pipe
183 if inputMime == "image/jpeg":
184 pipe += " ! jpegdec"
185 else:
186 pipe += " ! ffmpegcolorspace"
187 pipe += " ! " + outputMime
188 return pipe
189
192 try:
193 return tuple(map(int, res.split("x")))
194 except:
195 raise ValueError("Invalid resolution: " + res)
196