# Transmageddon # Copyright (C) 2009-2011 Christian Schaller # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Library General Public # License as published by the Free Software Foundation; either # version 2 of the License, or (at your option) any later version. # # This librarmy is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Library General Public License for more details. # # You should have received a copy of the GNU Library General Public # License along with this library; if not, write to the # Free Software Foundation, Inc., 59 Temple Place - Suite 330, # Boston, MA 02111-1307, USA. import sys import os os.environ["GST_DEBUG_DUMP_DOT_DIR"] = "/tmp" from gi.repository import GObject GObject.threads_init() from gi.repository import GLib from gi.repository import Gst Gst.init(None) from gi.repository import GstPbutils class Mixer(GObject.GObject): __gsignals__ = { 'ready-for-querying' : (GObject.SignalFlags.RUN_LAST, None, []), 'got-eos' : (GObject.SignalFlags.RUN_LAST, None, []), 'missing-plugin' : (GObject.SignalFlags.RUN_LAST, None, []), 'got-error' : (GObject.SignalFlags.RUN_LAST, None, (GObject.TYPE_PYOBJECT,)) } def __init__(self): self.mainloop = GObject.MainLoop() GObject.GObject.__init__(self) # Create transcoding pipeline self.pipeline = Gst.Pipeline() self.pipeline.set_state(Gst.State.PAUSED) self.videoenc = Gst.ElementFactory.make("theoraenc", None) self.pipeline.add(self.videoenc) self.audioenc = Gst.ElementFactory.make("vorbisenc", None) self.pipeline.add(self.audioenc) factory=self.audioenc.get_factory() print(factory) if factory != None: # Set Transmageddon as Application name using Tagsetter interface tagyes = factory.has_interface("GstTagSetter") if tagyes ==True: taglist=Gst.TagList.new_empty() taglist.add_value(Gst.TagMergeMode.APPEND, Gst.TAG_APPLICATION_NAME, "Testmageddon transcoder") self.audioenc.merge_tags(taglist, Gst.TagMergeMode.REPLACE) if Gst.ElementFactory.list_is_type(factory, 1125899906842626): # Audio Encoders factory code print("got audio encoder") taglist=Gst.TagList.new_empty() taglist.add_value(Gst.TagMergeMode.APPEND, Gst.TAG_LANGUAGE_CODE, "fr") #set language to french longname=factory.get_metadata('long-name') # get longname to set encoder tag taglist.add_value(Gst.TagMergeMode.APPEND, Gst.TAG_ENCODER, longname) self.audioenc.merge_tags(taglist, Gst.TagMergeMode.REPLACE) self.muxer = Gst.ElementFactory.make('oggmux', None) self.pipeline.add(self.muxer) self.filesink = Gst.ElementFactory.make('filesink', None) self.filesink.set_property("location", "/home/cschalle/Videos/testclip-out.ogg") self.pipeline.add(self.filesink) self.videoenc.link(self.muxer) self.audioenc.link(self.muxer) self.muxer.link(self.filesink) self.audioenc.set_state(Gst.State.PAUSED) self.videoenc.set_state(Gst.State.PAUSED) self.muxer.set_state(Gst.State.PAUSED) self.uridecoder = Gst.ElementFactory.make("uridecodebin", "uridecoder") self.uridecoder.set_property("uri", "file:///home/cschalle/Videos/testclip.ogg" ) self.uridecoder.connect("pad-added", self.OnDynamicPad) self.pipeline.add(self.uridecoder) self.uridecoder.set_state(Gst.State.PAUSED) # we need to wait on this one before going further self.uridecoder.connect("no-more-pads", self.noMorePads) self.BusMessages = self.BusWatcher() self.mainloop.run() def noMorePads(self, dbin): Gst.debug_bin_to_dot_file (self.pipeline, Gst.DebugGraphDetails.ALL, 'mixer') self.muxer.set_state(Gst.State.PAUSED) self.filesink.set_state(Gst.State.PAUSED) GLib.idle_add(self.idlePlay) def idlePlay(self): # print("going to playing") self.pipeline.set_state(Gst.State.PLAYING) def BusWatcher(self): bus = self.pipeline.get_bus() bus.add_signal_watch() bus.connect('message', self.on_message) def on_message(self, bus, message): mtype = message.type if mtype == Gst.MessageType.ERROR: print("we got an error, life is shit") err, debug = message.parse_error() print(err) print(debug) Gst.debug_bin_to_dot_file (self.pipeline, \ Gst.DebugGraphDetails.ALL, 'mixer-error') elif mtype == Gst.MessageType.ELEMENT: if GstPbutils.is_missing_plugin_message(message): if self.missingplugin==False: self.missingplugin=message self.emit('missing-plugin') elif mtype == Gst.MessageType.ASYNC_DONE: self.emit('ready-for-querying') elif mtype == Gst.MessageType.EOS: self.emit('got-eos') self.pipeline.set_state(Gst.State.NULL) self.mainloop.quit() elif mtype == Gst.MessageType.APPLICATION: self.pipeline.set_state(Gst.State.NULL) self.pipeline.remove(self.uridecoder) return True def OnDynamicPad(self, uridecodebin, src_pad): origin = src_pad.query_caps(None) c = origin.to_string() # print(c) if not c.startswith("text/"): if c.startswith("audio/"): apad1=self.audioenc.get_compatible_pad(src_pad, None) src_pad.link(apad1) elif (c.startswith("video/") or c.startswith("image/")): vconvert1pad=self.videoenc.get_compatible_pad(src_pad, None) src_pad.link(vconvert1pad) if __name__ == "__main__": app = Mixer()