1
# PiTiVi , Non-linear video editor
5
# Copyright (c) 2005, Edward Hervey <bilboed@bilboed.com>
7
# This program is free software; you can redistribute it and/or
8
# modify it under the terms of the GNU Lesser General Public
9
# License as published by the Free Software Foundation; either
10
# version 2.1 of the License, or (at your option) any later version.
12
# This program is distributed in the hope that it will be useful,
13
# but WITHOUT ANY WARRANTY; without even the implied warranty of
14
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15
# Lesser General Public License for more details.
17
# You should have received a copy of the GNU Lesser General Public
18
# License along with this program; if not, write to the
19
# Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
20
# Boston, MA 02110-1301, USA.
23
Convenience functions for creating the output media sinks
27
# The plumber takes care of the sinks
29
# This is a required level of abstraction for the many different sinks that
32
# They should be provided by a generic sink provider
35
from gst import interfaces
36
from pitivi.factories.base import SinkFactory
39
class DefaultVideoSink(SinkFactory):
41
def __init__(self, *args, **kwargs):
42
SinkFactory.__init__(self, *args, **kwargs)
44
self._cachedsink = None
49
def _makeBin(self, input_stream=None):
50
""" Returns a video sink bin"""
51
if self._cachedsink != None:
52
self.debug("Returning cached sink")
53
return self._cachedsink
56
ffmpegcolorspace = gst.element_factory_make("ffmpegcolorspace")
57
videoscale = gst.element_factory_make("videoscale")
59
autovideosink = gst.element_factory_make("autovideosink")
60
autovideosink.set_state(gst.STATE_READY)
62
bin.add(ffmpegcolorspace, videoscale, autovideosink)
63
ffmpegcolorspace.link_pads_full("src", videoscale, "sink", gst.PAD_LINK_CHECK_NOTHING)
64
videoscale.link_pads_full("src", autovideosink, "sink", gst.PAD_LINK_CHECK_NOTHING)
65
pad = ffmpegcolorspace.get_pad("sink")
66
ghost = gst.GhostPad("sink", pad)
69
if not autovideosink.implements_interface(interfaces.XOverlay):
70
autovideosink.info("doesn't implement XOverlay interface")
72
self._realsink = autovideosink.get_by_interface(interfaces.XOverlay)
73
if not self._realsink:
74
self.info("%s", list(autovideosink.elements()))
75
autovideosink.warning("couldn't even find an XOverlay within!!!")
77
self._realsink.info("implements XOverlay interface")
79
self._realsink = autovideosink
83
self._realsink.props.force_aspect_ratio = True
84
except AttributeError:
88
self._realsink.props.double_buffer = False
89
except AttributeError:
92
self._realsink.props.sync = self.sync
93
self._realsink.props.qos = self.sync
95
self._cachedsink = autovideosink
98
def _releaseBin(self, bin, *args):
99
if bin == self._cachedsink:
100
self._realsink = None
101
self._cachedsink = None
103
def setSync(self, sync=True):
104
self.debug("sync:%r", sync)
105
if self.sync == sync:
109
self.debug("_realsink:%r", self._realsink)
111
self._realsink.props.sync = self.sync
112
self._realsink.props.qos = self.sync
115
class DefaultAudioSink(SinkFactory):
117
def __init__(self, *args, **kwargs):
118
SinkFactory.__init__(self, *args, **kwargs)
120
self._cachedsink = None
121
self._realsink = None
124
def _makeBin(self, input_stream=None):
125
""" Returns an audio sink bin that can be used in the Discoverer """
126
if self._cachedsink != None:
127
self.debug("Returning cached sink")
128
return self._cachedsink
129
autoaudiosink = gst.element_factory_make("autoaudiosink")
131
autoaudiosink.set_state(gst.STATE_READY)
132
self._realsink = find_recursive_element(autoaudiosink, gst.BaseSink)
133
self._realsink.props.sync = self.sync
135
audiosink = gst.Bin("pitivi-audiosink")
136
aconv = gst.element_factory_make("audioconvert", "audiobin-convert")
137
ares = gst.element_factory_make("audioresample", "audiobin-resample")
139
audiosink.add(aconv, ares, autoaudiosink)
140
aconv.link_pads_full("src", ares, "sink", gst.PAD_LINK_CHECK_NOTHING)
141
# FIXME : This is really bad
142
# For starters... it means we can't edit/preview multi-channel audio
143
# Also, most hardware cards do internal resampling much better
144
audiocaps = "audio/x-raw-int,channels=2,rate=44100,depth=16;audio/x-raw-float,channels=2,rate=44100"
145
ares.link(autoaudiosink, gst.Caps(audiocaps))
147
audiosink.add_pad(gst.GhostPad("sink", aconv.get_pad("sink")))
149
self._cachedsink = audiosink
152
def _releaseBin(self, bin, *args):
153
if bin == self._cachedsink:
154
self._realsink = None
155
self._cachedsink = None
157
def setSync(self, sync=True):
158
self.debug("sync:%r", sync)
159
if self.sync == sync:
162
self.debug("_realsink:%r", self._realsink)
164
self._realsink.props.sync = self.sync
167
def find_recursive_element(bin, typ):
168
if not isinstance(bin, gst.Bin):
169
if isinstance(bin, typ):
172
for elt in bin.elements():
173
if isinstance(elt, typ):
175
if isinstance(elt, gst.Bin):
176
r = find_recursive_element(elt, typ)