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: 7162 $"
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 proc(struct, vals.high)
102 else:
103
104 proc(struct, vals)
105
106 def addRatesForWidth(struct, width):
107
108 def addRatesForHeight(struct, height):
109
110 def addRate(struct, rate):
111 if (width, height) not in sizes:
112 sizes[(width, height)] = []
113 d = {'framerate': (rate.num, rate.denom),
114 'mime': struct.get_name()}
115 if 'yuv' in d['mime']:
116 d['format'] = struct['format'].fourcc
117 sizes[(width, height)].append(d)
118 forAllStructValues(struct, 'framerate', addRate)
119 forAllStructValues(struct, 'height', addRatesForHeight)
120 for struct in caps:
121 if 'yuv' not in struct.get_name():
122 continue
123 forAllStructValues(struct, 'width', addRatesForWidth)
124
125 return (name, element.get_factory().get_name(), sizes)
126
127 def tryV4L2():
128 log.debug('webcam', 'trying v4l2')
129 version = gstreamer.get_plugin_version('video4linux2')
130 minVersion = (0, 10, 5, 1)
131 if not version or version < minVersion:
132 log.info('webcam', 'v4l2 version %r too old (need >=%r)',
133 version, minVersion)
134 return defer.fail(NotImplementedError())
135
136 pipeline = 'v4l2src name=source device=%s ! fakesink' % (device, )
137 d = do_element_check(pipeline, 'source', probeDevice,
138 state=gst.STATE_PAUSED, set_state_deferred=True)
139 return d
140
141 def tryV4L1(_):
142 log.debug('webcam', 'trying v4l1')
143 pipeline = 'v4lsrc name=source device=%s ! fakesink' % (device, )
144 d = do_element_check(pipeline, 'source', probeDevice,
145 state=gst.STATE_PAUSED, set_state_deferred=True)
146 return d
147
148 result = messages.Result()
149
150 d = tryV4L2()
151 d.addErrback(tryV4L1)
152 d.addCallback(check.callbackResult, result)
153 d.addErrback(check.errbackNotFoundResult, result, mid, device)
154 d.addErrback(check.errbackResult, result, mid, device)
155
156 return d
157