1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import gst
23
24 from twisted.internet import defer
25
26 from flumotion.common import gstreamer, log, messages
27 from flumotion.worker.checks import check
28 from flumotion.worker.checks.gst010 import do_element_check
29
30 __version__ = "$Rev$"
31
32
34 """
35 Probe the given device node as a TV card.
36 Return a deferred firing a human-readable device name, a list of channel
37 names (Tuner/Composite/...), and a list of norms (PAL/NTSC/SECAM/...).
38
39 @rtype: L{twisted.internet.defer.Deferred}
40 """
41 result = messages.Result()
42
43 def get_name_channels_norms(element):
44 deviceName = element.get_property('device-name')
45 channels = [channel.label for channel in element.list_channels()]
46 norms = [norm.label for norm in element.list_norms()]
47 return (deviceName, channels, norms)
48
49 pipeline = 'v4lsrc name=source device=%s ! fakesink' % device
50 d = do_element_check(pipeline, 'source', get_name_channels_norms)
51
52 d.addCallback(check.callbackResult, result)
53 d.addErrback(check.errbackNotFoundResult, result, mid, device)
54 d.addErrback(check.errbackResult, result, mid, device)
55
56 return d
57
58
60 """
61 Probe the given device node as a webcam.
62
63 The result is either:
64 - succesful, with a None value: no device found
65 - succesful, with a tuple:
66 - device name
67 - dict of mime, format, width, height, fps pair
68 - failed
69
70 @rtype: L{flumotion.common.messages.Result}
71 """
72
73
74
75 def probeDevice(element):
76 name = element.get_property('device-name')
77 caps = element.get_pad("src").get_caps()
78 log.debug('check', 'caps: %s' % caps.to_string())
79
80 sizes = {}
81
82
83
84
85 def forAllStructValues(struct, key, proc):
86 vals = struct[key]
87 if isinstance(vals, list):
88 for val in vals:
89 proc(struct, val)
90 elif isinstance(vals, gst.IntRange):
91 val = vals.low
92 while val < vals.high:
93 proc(struct, val)
94 val *= 2
95 proc(struct, vals.high)
96 elif isinstance(vals, gst.DoubleRange):
97
98 proc(struct, vals.high)
99 elif isinstance(vals, gst.FractionRange):
100
101 val = vals.low
102 while float(val) < float(vals.high):
103 proc(struct, val)
104 val.num += 5
105 proc(struct, vals.high)
106 else:
107
108 proc(struct, vals)
109
110 def addRatesForWidth(struct, width):
111
112 def addRatesForHeight(struct, height):
113
114 def addRate(struct, rate):
115 if not rate.num:
116 return
117 if (width, height) not in sizes:
118 sizes[(width, height)] = []
119 d = {'framerate': (rate.num, rate.denom),
120 'mime': struct.get_name()}
121 if 'yuv' in d['mime']:
122 d['format'] = struct['format'].fourcc
123 sizes[(width, height)].append(d)
124 forAllStructValues(struct, 'framerate', addRate)
125 forAllStructValues(struct, 'height', addRatesForHeight)
126 for struct in caps:
127 if 'yuv' not in struct.get_name():
128 continue
129 forAllStructValues(struct, 'width', addRatesForWidth)
130
131 return (element.get_factory().get_name(), sizes)
132
133 def tryV4L2():
134 log.debug('webcam', 'trying v4l2')
135 version = gstreamer.get_plugin_version('video4linux2')
136 minVersion = (0, 10, 5, 1)
137 if not version or version < minVersion:
138 log.info('webcam', 'v4l2 version %r too old (need >=%r)',
139 version, minVersion)
140 return defer.fail(NotImplementedError())
141
142 pipeline = 'v4l2src name=source device=%s ! fakesink' % (device, )
143 d = do_element_check(pipeline, 'source', probeDevice,
144 state=gst.STATE_PAUSED, set_state_deferred=True)
145 return d
146
147 def tryV4L1(_):
148 log.debug('webcam', 'trying v4l1')
149 pipeline = 'v4lsrc name=source device=%s ! fakesink' % (device, )
150 d = do_element_check(pipeline, 'source', probeDevice,
151 state=gst.STATE_PAUSED, set_state_deferred=True)
152 return d
153
154 result = messages.Result()
155
156 d = tryV4L2()
157 d.addErrback(tryV4L1)
158 d.addCallback(check.callbackResult, result)
159 d.addErrback(check.errbackNotFoundResult, result, mid, device)
160 d.addErrback(check.errbackResult, result, mid, device)
161
162 return d
163