1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 from twisted.internet import defer
23 from flumotion.worker.checks import check
24
25 import gst
26
27 from gst010 import *
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, id, device)
50 d.addErrback(check.errbackResult, result, id, device)
51
52 return d
53
55 """
56 Probe the given device node as a webcam.
57
58 The result is either:
59 - succesful, with a None value: no device found
60 - succesful, with a tuple:
61 - device name
62 - dict of mime, format, width, height, fps pair
63 - failed
64
65 @rtype: L{flumotion.common.messages.Result}
66 """
67
68
69 def probeDevice(element):
70 name = element.get_property('device-name')
71 caps = element.get_pad("src").get_caps()
72 log.debug('check', 'caps: %s' % caps.to_string())
73
74 sizes = {}
75
76
77
78
79 def forAllStructValues(struct, key, proc):
80 vals = struct[key]
81 if isinstance(vals, list):
82 for val in vals:
83 proc(struct, val)
84 elif isinstance(vals, gst.IntRange):
85 val = vals.low
86 while val < vals.high:
87 proc(struct, val)
88 val *= 2
89 proc(struct, vals.high)
90 elif isinstance(vals, gst.DoubleRange):
91
92 proc(struct, vals.high)
93 elif isinstance(vals, gst.FractionRange):
94
95 proc(struct, vals.high)
96 else:
97
98 proc(struct, vals)
99 def addRatesForWidth(struct, width):
100 def addRatesForHeight(struct, height):
101 def addRate(struct, rate):
102 if (width, height) not in sizes:
103 sizes[(width, height)] = []
104 d = {'framerate': (rate.num, rate.denom),
105 'mime': struct.get_name()}
106 if 'yuv' in d['mime']:
107 d['format'] = struct['format'].fourcc
108 sizes[(width, height)].append(d)
109 forAllStructValues(struct, 'framerate', addRate)
110 forAllStructValues(struct, 'height', addRatesForHeight)
111 for struct in caps:
112 if 'yuv' not in struct.get_name():
113 continue
114 forAllStructValues(struct, 'width', addRatesForWidth)
115
116 return (name, element.get_factory().get_name(), sizes)
117
118 def tryV4L2():
119 log.debug('webcam', 'trying v4l2')
120 version = gstreamer.get_plugin_version('video4linux2')
121 minVersion = (0, 10, 5, 1)
122 if not version or version < minVersion:
123 log.info('webcam', 'v4l2 version %r too old (need >=%r)',
124 version, minVersion)
125 return defer.fail(NotImplementedError())
126
127 pipeline = 'v4l2src name=source device=%s ! fakesink' % (device,)
128 d = do_element_check(pipeline, 'source', probeDevice,
129 state=gst.STATE_PAUSED, set_state_deferred=True)
130 return d
131
132 def tryV4L1(_):
133 log.debug('webcam', 'trying v4l1')
134 pipeline = 'v4lsrc name=source device=%s ! fakesink' % (device,)
135 d = do_element_check(pipeline, 'source', probeDevice,
136 state=gst.STATE_PAUSED, set_state_deferred=True)
137 return d
138
139 result = messages.Result()
140
141 d = tryV4L2()
142 d.addErrback(tryV4L1)
143 d.addCallback(check.callbackResult, result)
144 d.addErrback(check.errbackNotFoundResult, result, id, device)
145 d.addErrback(check.errbackResult, result, id, device)
146
147 return d
148