1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import sys
23
24 import gobject
25 import gst
26
27 from flumotion.common.i18n import gettexter
28 from flumotion.component import feedcomponent
29 from flumotion.common import gstreamer
30
31 __version__ = "$Rev$"
32 T_ = gettexter()
33
34 DEFAULT_TOLERANCE = 20000000
35
36
38 """
39 I am a GStreamer bin that can change the samplerate of an audio stream.
40 """
41 logCategory = "audiorate"
42 RATE_CAPS = ', rate=%d'
43 CAPS_TEMPLATE = ("audio/x-raw-int %(extra_caps)s ;"
44 "audio/x-raw-float %(extra_caps)s")
45
46 __gproperties__ = {
47 'samplerate': (gobject.TYPE_UINT, 'samplerate',
48 'Audio samplerate', 1, 200000, 44100,
49 gobject.PARAM_READWRITE),
50 'tolerance': (gobject.TYPE_UINT, 'tolerance',
51 'Correct imperfect timestamps when it exeeds the '
52 'tolerance', 0, sys.maxint, DEFAULT_TOLERANCE,
53 gobject.PARAM_READWRITE)}
54
56 gst.Bin.__init__(self)
57 self._samplerate = samplerate
58 self._samplerate_caps = ''
59
60 self._audiorate = gst.element_factory_make("audiorate")
61 self._audioconv = gst.element_factory_make("audioconvert")
62 self._audioresample = gst.element_factory_make("legacyresample")
63 self._capsfilter = gst.element_factory_make("capsfilter")
64 self._identity = gst.parse_launch("identity silent=true")
65 self.add(self._audiorate)
66 self.add(self._audioconv)
67 self.add(self._audioresample)
68 self.add(self._capsfilter)
69 self.add(self._identity)
70
71 self._audiorate.link(self._audioconv)
72 self._audioconv.link(self._audioresample)
73 self._audioresample.link(self._capsfilter)
74 self._capsfilter.link(self._identity)
75
76
77 self._sinkPad = gst.GhostPad('sink', self._audiorate.get_pad('sink'))
78 self._srcPad = gst.GhostPad('src', self._identity.get_pad('src'))
79 self.add_pad(self._sinkPad)
80 self.add_pad(self._srcPad)
81
82 self._setSamplerate(samplerate)
83 self._setTolerance(tolerance)
84
86
87 extra_caps = ' '.join([self._samplerate_caps, ])
88 return self.CAPS_TEMPLATE % dict(extra_caps=extra_caps)
89
91 self._samplerate = samplerate
92 self._samplerate_caps = ''
93 if self._samplerate is not None:
94 self._samplerate_caps = self.RATE_CAPS % samplerate
95 self._capsfilter.set_property('caps', gst.Caps(self._getCapsString()))
96
98 self._tolerance = tolerance
99 if gstreamer.element_has_property(self._audiorate, 'tolerance'):
100 self._audiorate.set_property('tolerance', self._tolerance)
101 else:
102 self.warning("The 'tolerance' property could not be set in the "
103 "audiorate element.")
104
106 if property.name == 'samplerate':
107 self._setSamplerate(value)
108 if property.name == 'tolerance':
109 self._setTolerance(value)
110 else:
111 raise AttributeError('unknown property %s' % property.name)
112
114 if property.name == 'samplerate':
115 return self._samplerate
116 if property.name == 'tolerance':
117 return self._tolerance
118 else:
119 raise AttributeError('unknown property %s' % property.name)
120
121
122 -class Audiorate(feedcomponent.PostProcEffect):
123 """
124 I am an effect that can be added to any component that changes the
125 samplerate of the audio output.
126 """
127 logCategory = "audiorate-effect"
128
131 """
132 @param element: the video source element on which the post
133 processing effect will be added
134 @param sourcePad: source pad used for linking the effect
135 @param pipeline: the pipeline of the element
136 @param samplerate: output samplerate
137 @param tolerance: tolerance to correct imperfect timestamps
138 """
139 feedcomponent.PostProcEffect.__init__(self, name, sourcePad,
140 AudiorateBin(samplerate, tolerance), pipeline)
141
143 self.effectBin.set_property("tolerance", tolerance)
144 return tolerance
145
147 return self.effectBin.get_property('tolerance')
148
150 self.effectBin.set_property("samplerate", samplerate)
151 return samplerate
152
154 return self.effectBin.get_property('samplerate')
155