1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 import gst
19 import gobject
20 from twisted.internet import reactor
21
22 from flumotion.component import feedcomponent
23
24 __version__ = "$Rev$"
25
26 GST_DEINTERLACER = "deinterlace"
27 FF_DEINTERLACER = "ffdeinterlace"
28 PASSTHROUGH_DEINTERLACER = "identity"
29
30 DEINTERLACE_MODE = [
31 "auto",
32 "interlaced",
33 "disabled"]
34
35 DEINTERLACE_METHOD = {
36
37 "tomsmocomp": GST_DEINTERLACER,
38 "greedyh": GST_DEINTERLACER,
39 "greedyl": GST_DEINTERLACER,
40 "vfir": GST_DEINTERLACER,
41 "linear": GST_DEINTERLACER,
42 "linearblend": GST_DEINTERLACER,
43 "scalerbob": GST_DEINTERLACER,
44 "weave": GST_DEINTERLACER,
45 "weavetff": GST_DEINTERLACER,
46 "weavebff": GST_DEINTERLACER,
47
48 "ffmpeg": FF_DEINTERLACER}
49
50
52 """
53 I am a GStreamer bin that can deinterlace a video stream from its
54 source pad using different methods.
55 """
56 logCategory = "deinterlace"
57 DEFAULT_MODE = 'auto'
58 DEFAULT_METHOD = 'ffmpeg'
59
60 __gproperties__ = {
61 'keep-framerate': (gobject.TYPE_BOOLEAN, 'keeps the input framerate',
62 'keeps in the output the same framerate as in the output '
63 'even if the deinterlacer changes it',
64 True, gobject.PARAM_READWRITE),
65 'mode': (gobject.TYPE_STRING, 'deinterlace mode',
66 'mode used to deinterlace incoming frames',
67 'auto', gobject.PARAM_READWRITE),
68 'method': (gobject.TYPE_STRING, 'deinterlace method',
69 'method/algorithm used to deinterlace incoming frames',
70 'ffmpeg', gobject.PARAM_READWRITE)}
71
73 gst.Bin.__init__(self)
74
75 self.keepFR = True
76 self.deinterlacerName = PASSTHROUGH_DEINTERLACER
77 self._interlaced = False
78
79
80 self._colorspace = gst.element_factory_make("ffmpegcolorspace")
81 self._colorfilter = gst.element_factory_make("capsfilter")
82 self._deinterlacer = gst.element_factory_make(PASSTHROUGH_DEINTERLACER)
83 self._deinterlacer.set_property('silent', True)
84 self._videorate = gst.element_factory_make("videorate")
85 self._ratefilter = gst.element_factory_make("capsfilter")
86
87
88 self.add(self._colorspace, self._colorfilter, self._deinterlacer,
89 self._videorate, self._ratefilter)
90
91
92
93
94
95
96 self._colorfilter.set_property('caps', gst.Caps(
97 'video/x-raw-yuv, format=(fourcc)I420'))
98
99
100 self._colorspace.link(self._colorfilter)
101 self._colorfilter.link(self._deinterlacer)
102 self._deinterlacer.link(self._videorate)
103 self._videorate.link(self._ratefilter)
104
105
106 self._sinkPad = gst.GhostPad('sink', self._colorspace.get_pad('sink'))
107 self._srcPad = gst.GhostPad('src', self._ratefilter.get_pad('src'))
108 self.add_pad(self._sinkPad)
109 self.add_pad(self._srcPad)
110
111
112 self._sinkPeerPad = self._colorspace.get_pad('src')
113 self._srcPeerPad = self._videorate.get_pad('sink')
114
115
116 self._sinkPad.set_setcaps_function(self._sinkSetCaps)
117
118
119 self._setMethod(method)
120 self._setMode(mode)
121
124
126 struct = caps[0]
127
128 if self.keepFR:
129 try:
130 framerate = struct['framerate']
131 except KeyError:
132 framerate = gst.Fraction(25, 1)
133 fr = '%s/%s' % (framerate.num, framerate.denom)
134 self._ratefilter.set_property('caps', gst.Caps(
135 'video/x-raw-yuv, framerate=%s;'
136 'video/x-raw-rgb, framerate=%s' % (fr, fr)))
137
138 try:
139 interlaced = struct['interlaced']
140 except KeyError:
141 interlaced = False
142 if interlaced == self._interlaced:
143 return True
144 else:
145 self.debug("Input is%sinterlaced" %
146 (interlaced and " " or " not "))
147 self._interlaced = interlaced
148
149
150 if self.mode == 'auto':
151 if self._interlaced and self.isPassthrough():
152 self._replaceDeinterlacer(self._sinkPeerPad,
153 DEINTERLACE_METHOD[self.method])
154 elif not self._interlaced and not self.isPassthrough():
155 self._replaceDeinterlacer(self._sinkPeerPad,
156 PASSTHROUGH_DEINTERLACER)
157 return True
158
160
161 def unlinkAndReplace(Pad, blocked, deinterlacerName):
162 oldDeinterlacer = self._deinterlacer
163 self._deinterlacer = gst.element_factory_make(deinterlacerName)
164 if deinterlacerName == GST_DEINTERLACER:
165 self._deinterlacer.set_property("method", self.method)
166 elif deinterlacerName == PASSTHROUGH_DEINTERLACER:
167 self._deinterlacer.set_property("silent", True)
168 self._deinterlacer.set_state(gst.STATE_PLAYING)
169 self.add(self._deinterlacer)
170
171 self._colorfilter.unlink(oldDeinterlacer)
172 oldDeinterlacer.unlink(self._videorate)
173
174 oldDeinterlacer.set_state(gst.STATE_NULL)
175 self.remove(oldDeinterlacer)
176 self._colorfilter.link(self._deinterlacer)
177 self._deinterlacer.link(self._videorate)
178 reactor.callFromThread(self._sinkPeerPad.set_blocked, False)
179 self.debug("%s has been replaced succesfully" %
180 self.deinterlacerName)
181 self.deinterlacerName = deinterlacerName
182
183
184 self.debug("Replacing %s deinterlacer with %s:%s" %
185 (self.deinterlacerName, deinterlacerName, self.method))
186 reactor.callFromThread(blockPad.set_blocked_async,
187 True, unlinkAndReplace, deinterlacerName)
188
212
231
233 if property.name == 'mode':
234 if value != self.mode:
235 self._setMode(value)
236 elif property.name == 'method':
237 if value != self.method:
238 self._setMethod(value)
239 elif property.name == 'keep-framerate':
240 self.keepFR = value
241 else:
242 raise AttributeError('uknown property %s' % property.name)
243
245 if property.name == 'mode':
246 return self.mode
247 elif property.name == 'method':
248 return self.method
249 elif property.name == 'keep-framerate':
250 return self.keepFR
251 else:
252 raise AttributeError('uknown property %s' % property.name)
253
254
256 """
257 I am an effect that can be added to any component that has a deinterlacer
258 component and a way of changing the deinterlace method.
259 """
260 logCategory = "deinterlace"
261
262 - def __init__(self, name, sourcePad, pipeline, mode, method):
272
279
281 """
282 Sets the deinterlacing method
283
284 @param value: the method to set to deinterlace
285
286 @return: the actual method set to deinterlace
287 """
288 self.effectBin.set_property('method', method)
289 self.info('Changing deinterlacing method to %s', method)
290
291 self.uiState.set('deinterlace-method', method)
292 return method
293
295 """
296 Gets the deinterlacing method
297
298 @return: the method set for deinterlacing
299 @rtype: string
300 """
301 return self.effectBin.get_property('method')
302
304 """
305 Sets the deinterlacing mode
306
307 @param value: the method to set to deinterlace
308
309 @return: the actual method set to deinterlace
310 """
311 self.effectBin.set_property('mode', mode)
312 self.info('Changing deinterlacing mode to %s', mode)
313
314 self.uiState.set('deinterlace-mode', mode)
315 return mode
316
318 """
319 GetSets the deinterlacing method
320
321 @param value: the method used for deinterlacing
322
323 Returns: the actual method used to deinterlace
324 """
325 return self.effectBin.get_property('mode')
326