1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 import sys
19
20 import gobject
21 import gst
22
23 from flumotion.common.i18n import gettexter
24 from flumotion.component import feedcomponent
25 from flumotion.common import gstreamer
26
27 __version__ = "$Rev$"
28 T_ = gettexter()
29
30 DEFAULT_TOLERANCE = 20000000
31
32
34 """
35 I am a GStreamer bin that can convert an an audio stream, changing its
36 samplerate and the number of channels
37 """
38 logCategory = "audiorate"
39 RATE_CAPS = ', rate=%d'
40 CHANNELS_CAPS = ', channels=%d'
41 CAPS_TEMPLATE = ("audio/x-raw-int %(extra_caps)s ;"
42 "audio/x-raw-float %(extra_caps)s")
43
44 __gproperties__ = {
45 'channels': (gobject.TYPE_UINT, 'channels',
46 'Audio channels', 1, 8, 2,
47 gobject.PARAM_READWRITE),
48 'samplerate': (gobject.TYPE_UINT, 'samplerate',
49 'Audio samplerate', 1, 200000, 44100,
50 gobject.PARAM_READWRITE),
51 'tolerance': (gobject.TYPE_UINT, 'tolerance',
52 'Correct imperfect timestamps when it exeeds the '
53 'tolerance', 0, sys.maxint, DEFAULT_TOLERANCE,
54 gobject.PARAM_READWRITE)}
55
58 gst.Bin.__init__(self)
59 self._samplerate = samplerate
60 self._samplerate_caps = ''
61 self._channels = channels
62 self._channels_caps = ''
63
64 if self._use_audiorate():
65 self._audiorate = gst.element_factory_make("audiorate")
66 self._audiorate.set_property("skip-to-first", True)
67 else:
68 self._audiorate = gst.element_factory_make("identity")
69 self._audiorate.set_property("silent", True)
70
71 self._audioconv = gst.element_factory_make("audioconvert")
72
73 resampler = 'audioresample'
74 if gstreamer.element_factory_exists('legacyresample'):
75 resampler = 'legacyresample'
76 self._audioresample = gst.element_factory_make(resampler)
77
78 self._capsfilter = gst.element_factory_make("capsfilter")
79 self._identity = gst.parse_launch("identity silent=true")
80 self.add(self._audiorate)
81 self.add(self._audioconv)
82 self.add(self._audioresample)
83 self.add(self._capsfilter)
84 self.add(self._identity)
85
86 self._audiorate.link(self._audioconv)
87 self._audioconv.link(self._audioresample)
88 self._audioresample.link(self._capsfilter)
89 self._capsfilter.link(self._identity)
90
91
92 self._sinkPad = gst.GhostPad('sink', self._audiorate.get_pad('sink'))
93 self._srcPad = gst.GhostPad('src', self._identity.get_pad('src'))
94 self.add_pad(self._sinkPad)
95 self.add_pad(self._srcPad)
96
97 self._sinkPad.set_event_function(self.eventfunc)
98
99 self._setSamplerate(samplerate)
100 self._setChannels(channels)
101 self._setTolerance(tolerance)
102
106
108 extra_caps = ' '.join([self._samplerate_caps, self._channels_caps])
109 return self.CAPS_TEMPLATE % dict(extra_caps=extra_caps)
110
112 self._channels = channels
113 self._channels_caps = ''
114 if self._channels is not None:
115 self._channels_caps = self.CHANNELS_CAPS % channels
116 self._capsfilter.set_property('caps', gst.Caps(self._getCapsString()))
117
119 self._samplerate = samplerate
120 self._samplerate_caps = ''
121 if self._samplerate is not None:
122 self._samplerate_caps = self.RATE_CAPS % samplerate
123 self._capsfilter.set_property('caps', gst.Caps(self._getCapsString()))
124
126 self._tolerance = tolerance
127 if gstreamer.element_has_property(self._audiorate, 'tolerance'):
128 self._audiorate.set_property('tolerance', self._tolerance)
129 else:
130 self.warning("The 'tolerance' property could not be set in the "
131 "audiorate element.")
132
142
144 if property.name == 'channels':
145 return self._channels
146 if property.name == 'samplerate':
147 return self._samplerate
148 if property.name == 'tolerance':
149 return self._tolerance
150 else:
151 raise AttributeError('unknown property %s' % property.name)
152
159
160
162 """
163 I am an effect that can be added to any component that changes the
164 samplerate of the audio output.
165 """
166 logCategory = "audioconvert-effect"
167
168 - def __init__(self, name, sourcePad, pipeline, channels=None,
169 samplerate=None, tolerance=DEFAULT_TOLERANCE,
170 use_audiorate=True):
171 """
172 @param element: the video source element on which the post
173 processing effect will be added
174 @param sourcePad: source pad used for linking the effect
175 @param pipeline: the pipeline of the element
176 @param channels: number of output channels
177 @param samplerate: output samplerate
178 @param tolerance: tolerance to correct imperfect timestamps
179 """
180 feedcomponent.PostProcEffect.__init__(self, name, sourcePad,
181 AudioconvertBin(channels, samplerate, tolerance),
182 pipeline)
183
185 self.effectBin.set_property("tolerance", tolerance)
186 return tolerance
187
189 return self.effectBin.get_property('tolerance')
190
192 self.effectBin.set_property("samplerate", samplerate)
193 return samplerate
194
196 return self.effectBin.get_property('samplerate')
197
199 self.effectBin.set_property("channels", channels)
200 return channels
201
203 return self.effectBin.get_property('channels')
204