from gi.repository import GstPbutils from gi.repository import GstTranscoder from pitivi.check import GstDependency from pitivi.configure import get_gstpresets_dir from pitivi.dialogs.prefs import PreferencesDialog from pitivi.settings import GlobalSettings from pitivi.utils.loggable import Loggable from pitivi.utils.misc import ASSET_DURATION_META from pitivi.utils.misc import asset_get_duration # Remove check when we depend on Gst >= 1.20 HAS_GST_1_19 = GstDependency("Gst", apiversion="1.0", version_required="1.19").check() # Make sure gst knowns about our own GstPresets Gst.preset_set_app_dir(get_gstpresets_dir()) class ProxyingStrategy: AUTOMATIC = "automatic" ALL = "all" NOTHING = "nothing" GlobalSettings.add_config_section("proxy") GlobalSettings.add_config_option('proxying_strategy', section='proxy', key='proxying-strategy', default=ProxyingStrategy.AUTOMATIC) GlobalSettings.add_config_option('num_transcoding_jobs',
import time from gi.repository import GES from gi.repository import Gio from gi.repository import GLib from gi.repository import GObject from gi.repository import Gst from gi.repository import GstPbutils from gi.repository import GstTranscoder from pitivi.configure import get_gstpresets_dir from pitivi.settings import GlobalSettings from pitivi.utils.loggable import Loggable # Make sure gst knowns about our own GstPresets Gst.preset_set_app_dir(get_gstpresets_dir()) class ProxyingStrategy: AUTOMATIC = "automatic" ALL = "all" NOTHING = "nothing" GlobalSettings.addConfigSection("proxy") GlobalSettings.addConfigOption('proxyingStrategy', section='proxy', key='proxying-strategy', default=ProxyingStrategy.AUTOMATIC) GlobalSettings.addConfigOption('numTranscodingJobs', section='proxy',
def __init__(self, STREAMDATA, AUDIODATA, VIDEODATA): GObject.GObject.__init__(self) # Choose plugin based on Container name self.audiodata = AUDIODATA self.videodata = VIDEODATA self.streamdata = STREAMDATA # set preset directory Gst.preset_set_app_dir("/usr/share/transmageddon/presets/") # Choose plugin based on Codec Name # or switch to remuxing mode if any of the values are set to 'pastr' self.stoptoggle = False self.doaudio = False self.preset = self.streamdata['devicename'] self.blackborderflag = False self.missingplugin = False self.probestreamid = False self.sinkpad = None self.usedstreamids = [] # switching width and height around for rotationchoices where it makes sense if int(self.videodata[0]['rotationvalue']) == 1 or int( self.videodata[0]['rotationvalue']) == 3: nwidth = self.videodata[0]['videoheight'] nheight = self.videodata[0]['videowidth'] self.videodata[0]['videoheight'] = nheight self.videodata[0]['videowidth'] = nwidth # if needed create a variable to store the filename of the multipass \ # statistics file if self.streamdata['multipass'] != 0: videoencoderplugin = codecfinder.get_video_encoder_element( self.videodata[0]['outputvideocaps']) videoencoder = Gst.ElementFactory.make(videoencoderplugin, "videoencoder") properties = videoencoder.get_property_names() if "multipass-cache-file" in properties: self.cachefile = (str (GLib.get_user_cache_dir()) + "/transmageddon/" + \ "multipass-cache-file" + ".log") else: self.streamdata['multipass'] = 0 # gather preset data if relevant if self.preset != "nopreset": self.provide_presets() # Create transcoding pipeline self.pipeline = Gst.Pipeline() self.pipeline.set_state(Gst.State.PAUSED) # first check if we have a container format, if not set up output # for possible outputs should not be hardcoded if self.streamdata['container'] == False: x = 0 while x < len(self.audiodata): if self.audiodata[x]['outputaudiocaps'] != False: if not (self.audiodata[x]['outputaudiocaps'].intersect( Gst.caps_from_string( "audio/mpeg, mpegversion=1, layer=3")) ).is_empty(): self.streamdata['container'] = Gst.caps_from_string( "application/x-id3") x = x + 1 else: self.encodebinprofile = GstPbutils.EncodingContainerProfile.new( "containerformat", None, self.streamdata['container'], None) # What to do if we are not doing video passthrough (we only support video inside a # container format if self.videodata[0]['outputvideocaps'] != False: if (self.videodata[0]['dopassthrough'] == False) and (self.streamdata['passcounter'] == int(0)): self.videoflipper = Gst.ElementFactory.make( 'videoflip', None) self.videoflipper.set_property( "method", int(self.videodata[0]['rotationvalue'])) self.pipeline.add(self.videoflipper) self.colorspaceconverter = Gst.ElementFactory.make( "videoconvert", None) self.pipeline.add(self.colorspaceconverter) self.deinterlacer = Gst.ElementFactory.make( 'avdeinterlace', None) self.pipeline.add(self.deinterlacer) self.deinterlacer.link(self.colorspaceconverter) self.colorspaceconverter.link(self.videoflipper) self.deinterlacer.set_state(Gst.State.PAUSED) self.colorspaceconverter.set_state(Gst.State.PAUSED) self.videoflipper.set_state(Gst.State.PAUSED) # this part of the pipeline is used for both passthrough and re-encoding if (self.videodata[0]['outputvideocaps'] != False): videopreset = None self.videoprofile = GstPbutils.EncodingVideoProfile.new( self.videodata[0]['outputvideocaps'], videopreset, Gst.Caps.new_any(), 0) self.encodebinprofile.add_profile(self.videoprofile) # We do not need to do anything special for passthrough for audio, since we are not # including any extra elements between uridecodebin and encodebin x = 0 while x < len(self.audiodata): # print(self.audiodata[x]['outputaudiocaps']) if self.audiodata[x]['outputaudiocaps'] != False: audiopreset = None if self.streamdata['container'] == False: self.encodebinprofile = GstPbutils.EncodingAudioProfile.new( self.audiodata[x]['outputaudiocaps'], audiopreset, Gst.Caps.new_any(), 0) else: audioprofile = GstPbutils.EncodingAudioProfile.new( self.audiodata[x]['outputaudiocaps'], audiopreset, Gst.Caps.new_any(), 0) audioprofile.set_name("audioprofilename" + str(x)) self.encodebinprofile.add_profile(audioprofile) x = x + 1 # Dealing with Video multipass encoding if (self.streamdata['passcounter'] != int(0) and self.streamdata['multipass'] != int(0)): videoencoderplugin = codecfinder.get_video_encoder_element( self.videodata[0]['outputvideocaps']) self.videoencoder = Gst.ElementFactory.make( videoencoderplugin, "videoencoder") self.pipeline.add(self.videoencoder) GstPresetType = GObject.type_from_name("GstPreset") if GstPresetType in GObject.type_interfaces(self.videoencoder): self.videoencoder.load_preset( "Pass " + str(self.streamdata['passcounter'])) properties = self.videoencoder.get_property_names() if "multipass-cache-file" in properties: self.videoencoder.set_property("multipass-cache-file", self.cachefile) else: self.streamdata['multipass'] = 0 self.multipassfakesink = Gst.ElementFactory.make( "fakesink", "multipassfakesink") self.pipeline.add(self.multipassfakesink) self.videoencoder.set_state(Gst.State.PAUSED) self.multipassfakesink.set_state(Gst.State.PAUSED) else: self.encodebin = Gst.ElementFactory.make("encodebin", None) self.encodebin.connect("element-added", self.OnEncodebinElementAdd) self.encodebin.set_property("profile", self.encodebinprofile) self.encodebin.set_property("avoid-reencoding", True) self.pipeline.add(self.encodebin) self.encodebin.set_state(Gst.State.PAUSED) self.audiopads = {} x = 0 while x < len(self.audiodata): if self.audiodata[x]['outputaudiocaps'] != False: if self.streamdata['container'] != False: self.audiopads[x] = self.encodebin.emit( "request-profile-pad", "audioprofilename" + str(x)) x = x + 1 self.uridecoder = Gst.ElementFactory.make("uridecodebin", "uridecoder") self.uridecoder.set_property("uri", self.streamdata['filechoice']) self.uridecoder.connect('autoplug-continue', self.on_autoplug_continue) self.uridecoder.connect("pad-added", self.OnDynamicPad) self.uridecoder.connect('source-setup', self.dvdreadproperties) self.uridecoder.set_state(Gst.State.PAUSED) self.pipeline.add(self.uridecoder) if self.streamdata['passcounter'] != int(0): self.videoencoder.link(self.multipassfakesink) else: self.transcodefileoutput = Gst.ElementFactory.make("filesink", \ "transcodefileoutput") self.transcodefileoutput.set_property("location", \ (self.streamdata['outputdirectory']+"/"+self.streamdata['outputfilename'])) self.pipeline.add(self.transcodefileoutput) self.encodebin.link(self.transcodefileoutput) self.transcodefileoutput.set_state(Gst.State.PAUSED) self.uridecoder.set_state(Gst.State.PAUSED) self.BusMessages = self.BusWatcher() Gst.debug_bin_to_dot_file(self.pipeline, Gst.DebugGraphDetails.ALL, 'transmageddon-debug-graph') # we need to wait on this one before going further self.uridecoder.connect("no-more-pads", self.noMorePads)
def __init__(self, STREAMDATA, AUDIODATA, VIDEODATA): GObject.GObject.__init__(self) # Choose plugin based on Container name self.audiodata = AUDIODATA self.videodata = VIDEODATA self.streamdata = STREAMDATA # set preset directory Gst.preset_set_app_dir("/usr/share/transmageddon/presets/") # Choose plugin based on Codec Name # or switch to remuxing mode if any of the values are set to 'pastr' self.stoptoggle = False self.doaudio = False self.preset = self.streamdata["devicename"] self.blackborderflag = False self.missingplugin = False self.probestreamid = False self.sinkpad = None self.usedstreamids = [] # switching width and height around for rotationchoices where it makes sense if int(self.videodata[0]["rotationvalue"]) == 1 or int(self.videodata[0]["rotationvalue"]) == 3: nwidth = self.videodata[0]["videoheight"] nheight = self.videodata[0]["videowidth"] self.videodata[0]["videoheight"] = nheight self.videodata[0]["videowidth"] = nwidth # if needed create a variable to store the filename of the multipass \ # statistics file if self.streamdata["multipass"] != 0: videoencoderplugin = codecfinder.get_video_encoder_element(self.videodata[0]["outputvideocaps"]) videoencoder = Gst.ElementFactory.make(videoencoderplugin, "videoencoder") properties = videoencoder.get_property_names() if "multipass-cache-file" in properties: self.cachefile = str(GLib.get_user_cache_dir()) + "/transmageddon/" + "multipass-cache-file" + ".log" else: self.streamdata["multipass"] = 0 # gather preset data if relevant if self.preset != "nopreset": self.provide_presets() # Create transcoding pipeline self.pipeline = Gst.Pipeline() self.pipeline.set_state(Gst.State.PAUSED) # first check if we have a container format, if not set up output # for possible outputs should not be hardcoded if self.streamdata["container"] == False: x = 0 while x < len(self.audiodata): if self.audiodata[x]["outputaudiocaps"] != False: if not ( self.audiodata[x]["outputaudiocaps"].intersect( Gst.caps_from_string("audio/mpeg, mpegversion=1, layer=3") ) ).is_empty(): self.streamdata["container"] = Gst.caps_from_string("application/x-id3") x = x + 1 else: self.encodebinprofile = GstPbutils.EncodingContainerProfile.new( "containerformat", None, self.streamdata["container"], None ) # What to do if we are not doing video passthrough (we only support video inside a # container format if self.videodata[0]["outputvideocaps"] != False: if (self.videodata[0]["dopassthrough"] == False) and (self.streamdata["passcounter"] == int(0)): self.videoflipper = Gst.ElementFactory.make("videoflip", None) self.videoflipper.set_property("method", int(self.videodata[0]["rotationvalue"])) self.pipeline.add(self.videoflipper) self.colorspaceconverter = Gst.ElementFactory.make("videoconvert", None) self.pipeline.add(self.colorspaceconverter) self.deinterlacer = Gst.ElementFactory.make("avdeinterlace", None) self.pipeline.add(self.deinterlacer) self.deinterlacer.link(self.colorspaceconverter) self.colorspaceconverter.link(self.videoflipper) self.deinterlacer.set_state(Gst.State.PAUSED) self.colorspaceconverter.set_state(Gst.State.PAUSED) self.videoflipper.set_state(Gst.State.PAUSED) # this part of the pipeline is used for both passthrough and re-encoding if self.videodata[0]["outputvideocaps"] != False: videopreset = None self.videoprofile = GstPbutils.EncodingVideoProfile.new( self.videodata[0]["outputvideocaps"], videopreset, Gst.Caps.new_any(), 0 ) self.encodebinprofile.add_profile(self.videoprofile) # We do not need to do anything special for passthrough for audio, since we are not # including any extra elements between uridecodebin and encodebin x = 0 while x < len(self.audiodata): # print(self.audiodata[x]['outputaudiocaps']) if self.audiodata[x]["outputaudiocaps"] != False: audiopreset = None if self.streamdata["container"] == False: self.encodebinprofile = GstPbutils.EncodingAudioProfile.new( self.audiodata[x]["outputaudiocaps"], audiopreset, Gst.Caps.new_any(), 0 ) else: audioprofile = GstPbutils.EncodingAudioProfile.new( self.audiodata[x]["outputaudiocaps"], audiopreset, Gst.Caps.new_any(), 0 ) audioprofile.set_name("audioprofilename" + str(x)) self.encodebinprofile.add_profile(audioprofile) x = x + 1 # Dealing with Video multipass encoding if self.streamdata["passcounter"] != int(0) and self.streamdata["multipass"] != int(0): videoencoderplugin = codecfinder.get_video_encoder_element(self.videodata[0]["outputvideocaps"]) self.videoencoder = Gst.ElementFactory.make(videoencoderplugin, "videoencoder") self.pipeline.add(self.videoencoder) GstPresetType = GObject.type_from_name("GstPreset") if GstPresetType in GObject.type_interfaces(self.videoencoder): self.videoencoder.load_preset("Pass " + str(self.streamdata["passcounter"])) properties = self.videoencoder.get_property_names() if "multipass-cache-file" in properties: self.videoencoder.set_property("multipass-cache-file", self.cachefile) else: self.streamdata["multipass"] = 0 self.multipassfakesink = Gst.ElementFactory.make("fakesink", "multipassfakesink") self.pipeline.add(self.multipassfakesink) self.videoencoder.set_state(Gst.State.PAUSED) self.multipassfakesink.set_state(Gst.State.PAUSED) else: self.encodebin = Gst.ElementFactory.make("encodebin", None) self.encodebin.connect("element-added", self.OnEncodebinElementAdd) self.encodebin.set_property("profile", self.encodebinprofile) self.encodebin.set_property("avoid-reencoding", True) self.pipeline.add(self.encodebin) self.encodebin.set_state(Gst.State.PAUSED) self.audiopads = {} x = 0 while x < len(self.audiodata): if self.audiodata[x]["outputaudiocaps"] != False: if self.streamdata["container"] != False: self.audiopads[x] = self.encodebin.emit("request-profile-pad", "audioprofilename" + str(x)) x = x + 1 self.uridecoder = Gst.ElementFactory.make("uridecodebin", "uridecoder") self.uridecoder.set_property("uri", self.streamdata["filechoice"]) self.uridecoder.connect("autoplug-continue", self.on_autoplug_continue) self.uridecoder.connect("pad-added", self.OnDynamicPad) self.uridecoder.connect("source-setup", self.dvdreadproperties) self.uridecoder.set_state(Gst.State.PAUSED) self.pipeline.add(self.uridecoder) if self.streamdata["passcounter"] != int(0): self.videoencoder.link(self.multipassfakesink) else: self.transcodefileoutput = Gst.ElementFactory.make("filesink", "transcodefileoutput") self.transcodefileoutput.set_property( "location", (self.streamdata["outputdirectory"] + "/" + self.streamdata["outputfilename"]) ) self.pipeline.add(self.transcodefileoutput) self.encodebin.link(self.transcodefileoutput) self.transcodefileoutput.set_state(Gst.State.PAUSED) self.uridecoder.set_state(Gst.State.PAUSED) self.BusMessages = self.BusWatcher() Gst.debug_bin_to_dot_file(self.pipeline, Gst.DebugGraphDetails.ALL, "transmageddon-debug-graph") # we need to wait on this one before going further self.uridecoder.connect("no-more-pads", self.noMorePads)