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