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