[transmageddon] Further fixes for multipass encoding



commit 62da35379faf08f100c67c0b36313e2c452ccb53
Author: Christian Fredrik Kalager Schaller <uraeus linuxrisin org>
Date:   Tue Sep 11 21:15:52 2012 +0200

    Further fixes for multipass encoding

 profiles/ipod.xml        |    2 +-
 src/codecfinder.py       |    6 ++-
 src/transcoder_engine.py |  112 +++++++++++++++++++++++++++------------------
 src/transmageddon.py     |   25 +++++------
 4 files changed, 83 insertions(+), 62 deletions(-)
---
diff --git a/profiles/ipod.xml b/profiles/ipod.xml
index dd969f3..7423628 100644
--- a/profiles/ipod.xml
+++ b/profiles/ipod.xml
@@ -21,7 +21,7 @@
         </audio>
         <video>
             <name>video/x-h264, profile=constrained-baseline</name>
-            <passes>2</passes>
+            <passes>0</passes>
             <pixelaspectratio>0/0</pixelaspectratio>
             <width>320, 640</width>
             <height>240, 480</height>
diff --git a/src/codecfinder.py b/src/codecfinder.py
index 25b616c..a85aa2a 100644
--- a/src/codecfinder.py
+++ b/src/codecfinder.py
@@ -227,7 +227,9 @@ def get_video_encoder_element(videoencodercaps):
    features = []
    elementname = False
    for fact in flist:
-       if Gst.ElementFactory.list_is_type(fact, 21):
+       if Gst.ElementFactory.list_is_type(fact, 2814749767106562):
+           test=fact.get_name()
+           # print "videoencoder is " + str(test)
            encoders.append(fact.get_name())
            features.append(fact) 
        # elif list_compat(["Codec", "Encoder", "Image"], \
@@ -243,7 +245,6 @@ def get_video_encoder_element(videoencodercaps):
            sinkcaps = [x.get_caps() for x in factory.get_static_pad_templates() \
                    if x.direction == Gst.PadDirection.SRC]
            for caps in sinkcaps:
-               # print "incoming caps is " + str(incomingcaps)
                intersect= caps.intersect(incomingcaps).to_string()
                if intersect != "EMPTY":
                    if elementname == False:
@@ -253,4 +254,5 @@ def get_video_encoder_element(videoencodercaps):
                        original = Gst.PluginFeature.get_rank(encoderfeature[elementname])
                        if mostrecent >= original:
                            elementname = element
+   print "elementname is " +str(elementname)
    return elementname
diff --git a/src/transcoder_engine.py b/src/transcoder_engine.py
index a0f250b..b5eb77d 100644
--- a/src/transcoder_engine.py
+++ b/src/transcoder_engine.py
@@ -87,7 +87,7 @@ class Transcoder(GObject.GObject):
 
        # if needed create a variable to store the filename of the multipass \
        # statistics file
-       if self.multipass != False:
+       if self.multipass != 0:
            self.cachefile = (str (GLib.get_user_cache_dir()) + "/" + \
                    "multipass-cache-file" + self.timestamp + ".log")
 
@@ -121,22 +121,22 @@ class Transcoder(GObject.GObject):
  
            # What to do if we are not doing video passthrough (we only support video 
            # with container format
-           if self.videopasstoggle==False:
-                   self.videoflipper = Gst.ElementFactory.make('videoflip', None)
-                   self.videoflipper.set_property("method", self.rotationvalue)
-                   self.pipeline.add(self.videoflipper)
+           if self.videopasstoggle==False and self.passcounter == int(0):
+               self.videoflipper = Gst.ElementFactory.make('videoflip', None)
+               self.videoflipper.set_property("method", self.rotationvalue)
+               self.pipeline.add(self.videoflipper)
 
-                   self.colorspaceconverter = Gst.ElementFactory.make("videoconvert", None)
-                   self.pipeline.add(self.colorspaceconverter)
+               self.colorspaceconverter = Gst.ElementFactory.make("videoconvert", None)
+               self.pipeline.add(self.colorspaceconverter)
 
-                  #self.deinterlacer = Gst.ElementFactory.make('deinterlace', None)
-                  # self.pipeline.add(self.deinterlacer)
+               self.deinterlacer = Gst.ElementFactory.make('deinterlace', 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)
+               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.videocaps != "novid":
                if (self.videocaps != False):
@@ -154,12 +154,29 @@ class Transcoder(GObject.GObject):
                self.audioprofile = GstPbutils.EncodingAudioProfile.new(self.audiocaps, audiopreset, Gst.Caps.new_any(), 0)
                self.encodebinprofile.add_profile(self.audioprofile)
        
+       if self.passcounter != int(0):
+           passvalue = "Pass "+ str(self.passcounter)
+           videoencoderplugin = codecfinder.get_video_encoder_element(self.videocaps)
+           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):
+               bob = self.videoencoder.load_preset(passvalue)
+               self.videoencoder.set_property("multipass-cache-file", self.cachefile)
+           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)
 
-       self.encodebin = Gst.ElementFactory.make ("encodebin", None)
-       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)
+
+       else:
+           self.encodebin = Gst.ElementFactory.make ("encodebin", None)
+           self.encodebin.set_property("profile", self.encodebinprofile)
+           self.encodebin.set_property("avoid-reencoding", True)
+           if (self.multipass != 0) and (self.passcounter == int(0)):
+               self.encodebin.connect("element-added", self.SetCacheFileProperty)
+           self.pipeline.add(self.encodebin)
+           self.encodebin.set_state(Gst.State.PAUSED)
        
        # put together remuxing caps to set on uridecodebin if doing 
        # passthrough on audio or video
@@ -190,14 +207,17 @@ class Transcoder(GObject.GObject):
            self.uridecoder.set_property("caps", self.remuxcaps) 
        self.uridecoder.set_state(Gst.State.PAUSED)
        self.pipeline.add(self.uridecoder)
-
-       self.transcodefileoutput = Gst.ElementFactory.make("filesink", \
+       
+       if self.passcounter != int(0):
+           self.videoencoder.link(self.multipassfakesink)
+       else:
+           self.transcodefileoutput = Gst.ElementFactory.make("filesink", \
                "transcodefileoutput")
-       self.transcodefileoutput.set_property("location", \
+           self.transcodefileoutput.set_property("location", \
                (DESTDIR+"/"+self.outputfilename))
-       self.pipeline.add(self.transcodefileoutput)
-       self.encodebin.link(self.transcodefileoutput)
-
+           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()
@@ -214,7 +234,6 @@ class Transcoder(GObject.GObject):
 
    # Gather preset values and create preset elements
    def provide_presets(self):
-       print "LOADING PRESETS IN TRANSCODER ENGINE"
        devices = presets.get()
        device = devices[self.preset]
        preset = device.presets["Normal"]
@@ -239,10 +258,7 @@ class Transcoder(GObject.GObject):
        wmin, wmax  =  preset.vcodec.width
        hmin, hmax = preset.vcodec.height
        width, height = self.owidth, self.oheight
-       print "wmax is " +str(wmax)
-       print "hmax is " +str(hmax)
-       print "width is " +str(width)
-       print "height is " +str(height)
+
        # Get Display aspect ratio
        pixelaspectratio = preset.vcodec.aspectratio
 
@@ -282,22 +298,19 @@ class Transcoder(GObject.GObject):
        else:
            num = self.fratenum
            denom = self.frateden
-       
-       print "audiocaps " +self.audiocaps.to_string()
-       print "videocaps " +self.videocaps.to_string()
+
        # set audio and video caps from preset file
        self.audiocaps=Gst.caps_from_string(preset.acodec.name+","+"channels="+str(self.channels))
        self.videocaps=Gst.caps_from_string(preset.vcodec.name+","+"height="+str(height)+","+"width="+str(width)+","+"framerate="+str(num)+"/"+str(denom))
        # self.videocaps.set_value("pixelaspectratio", pixelaspectratio) this doesn't work due to pixelaspectratio being a fraction, 
        # needs further investigation
-       print "audiocaps " +str(self.audiocaps.to_string())
-       print "videocaps " + str(self.videocaps.to_string())
+
 
        # print "final height " + str(height) + " final width " + str(width)
        # return height, width, num, denom, pixelaspectratio
 
    def noMorePads(self, dbin):
-       if (self.multipass == False) or (self.passcounter == int(0)):
+       if self.passcounter == int(0):
            self.transcodefileoutput.set_state(Gst.State.PAUSED)
        GLib.idle_add(self.idlePlay)
        # print "No More pads received"
@@ -326,7 +339,7 @@ class Transcoder(GObject.GObject):
        elif mtype == Gst.MessageType.ASYNC_DONE:
            self.emit('ready-for-querying')
        elif mtype == Gst.MessageType.EOS:
-           if (self.multipass != False):
+           if (self.multipass != 0):
                if (self.passcounter == 0):
                    #removing multipass cache file when done
                    if os.access(self.cachefile, os.F_OK):
@@ -356,26 +369,35 @@ class Transcoder(GObject.GObject):
                        src_pad.link(sinkpad)
            else:
                # Checking if its a subtitle pad which we can't deal with
-               # currently.0
+               # currently.
                # Making sure that when we remove video from a file we don't
                # bother with the video pad.
                c = origin.to_string()
                if not c.startswith("text/"):
                    if not (c.startswith("video/") and (self.videocaps == False)):
-                       sinkpad = self.encodebin.emit("request-pad", origin)
+                       if self.passcounter == int(0):
+                           sinkpad = self.encodebin.emit("request-pad", origin)
                if c.startswith("audio/"):
-                   src_pad.link(sinkpad)
+                   if (self.multipass == 0) and (self.passcounter == int(0)):
+                       src_pad.link(sinkpad)
                elif ((c.startswith("video/") or c.startswith("image/")) and (self.videocaps != False)):
                    if self.videopasstoggle==False:
+                       if (self.multipass != 0) and (self.passcounter != int(0)):
+                           videoencoderpad = self.videoencoder.get_static_pad("sink")
+                           src_pad.link(videoencoderpad)
+                       else:
                        # port fix- should be self.deinterlacer
                        # print "self.colorspaceconverter before use " + str(self.colorspaceconverter)
-                       colorspacepad = self.colorspaceconverter.get_static_pad("sink")
-                       src_pad.link(colorspacepad)
-                       self.videoflipper.get_static_pad("src").link(sinkpad)
-                       
+                           deinterlacerpad = self.deinterlacer.get_static_pad("sink")
+                           src_pad.link(deinterlacerpad)
+                           self.videoflipper.get_static_pad("src").link(sinkpad)   
                    else:
-                       src_pad.link(sinkpad)
+                           src_pad.link(sinkpad)
 
+   def SetCacheFileProperty(self, encodebin, element):
+       print "element is " + str(element)
+        # self.videoencoder.set_property("multipass-cache-file", self.cachefile)
+       # self.videoencoder.set_property("multipass-cache-file", self.cachefile) #### NEEDS FIXING
        # Grab element from encodebin which supports tagsetter interface and set app name
        # to Transmageddon
        #GstTagSetterType = GObject.type_from_name("GstTagSetter")
diff --git a/src/transmageddon.py b/src/transmageddon.py
index 78fc17e..2bf6eb0 100644
--- a/src/transmageddon.py
+++ b/src/transmageddon.py
@@ -108,7 +108,7 @@ supported_video_container_map = {
     'Ogg':        [ 'Theora', 'Dirac', 'On2 vp8' ],
     'MXF':        [ 'H264', 'MPEG2', 'MPEG4' ],
     'Matroska':   [ 'Dirac', 'Theora', 'H264', 'On2 vp8',
-                    'MPEG4', 'MPEG2', 'xvid', 'H263+' ],
+                    'MPEG4', 'MPEG2', 'H263+' ],
     'AVI':        [ 'H264', 'Dirac', 'MPEG2', 'MPEG4',
                     'Windows Media Video 2', 'On2 vp8' ],
     'Quicktime':  [ 'H264', 'Dirac', 'MPEG2', 'MPEG4', 'On2 vp8' ],
@@ -251,8 +251,8 @@ class TransmageddonUI:
        #        Gdk.DragAction.COPY)
 
        self.start_time = False
-       self.multipass = False
-       self.passcounter = False
+       self.multipass = 0
+       self.passcounter = 0
        
        # Set the Videos XDG UserDir as the default directory for the filechooser
        # also make sure directory exists
@@ -422,11 +422,9 @@ class TransmageddonUI:
 
        # Check for number of passes
        passes = preset.vcodec.passes
-       print "passes is " +str(passes)
        if passes == "0":
-           self.multipass = False
+           self.multipass = 0
        else:
-           print "self.multipass " +str(self.multipass)
            self.multipass = int(passes)
            self.passcounter = int(0)
 
@@ -500,7 +498,7 @@ class TransmageddonUI:
 
    def _on_eos(self, source):
        context_id = self.StatusBar.get_context_id("EOS")
-       if (self.multipass ==  False) or (self.passcounter == int(0)):
+       if self.passcounter == int(0):
            self.StatusBar.push(context_id, (_("File saved to %(dir)s") % \
                    {'dir': self.outputdirectory}))
            uri = "file://" + os.path.abspath(os.path.curdir) + "/transmageddon.svg"
@@ -517,8 +515,8 @@ class TransmageddonUI:
            self.ProgressBar.set_text(_("Done Transcoding"))
            self.ProgressBar.set_fraction(1.0)
            self.start_time = False
-           self.multipass = False
-           self.passcounter = False
+           self.multipass = 0
+           self.passcounter = 0
            self.audiopasstoggle=False
            self.videopasstoggle=False
            self.houseclean=False # due to not knowing which APIs to use I need
@@ -528,7 +526,6 @@ class TransmageddonUI:
            self.StatusBar.push(context_id, (_("Pass %(count)d Complete") % \
                    {'count': self.passcounter}))
            self.start_time = False
-           self.ProgressBar.set_text(_("Start next pass"))
            if self.passcounter == (self.multipass-1):
                self.passcounter = int(0)
                self._start_transcoding()
@@ -576,7 +573,7 @@ class TransmageddonUI:
                    self.containerchoice.set_active(-1) # set this here to ensure it happens even with quick audio-only
                    self.containerchoice.set_active(0)
                if self.haveaudio==False:
-                   self.audioinformation.set_markup(''.join(('<small>', _("No Audio"), '</small>')))
+                   self.audioinformation.set_markup(''.join(('<small>', _("No Audio"), '</small>'))) 
                    self.audiocodec.set_markup(''.join(('<small>', "",'</small>')))
 
                if isinstance(i, GstPbutils.DiscovererVideoInfo):
@@ -855,7 +852,7 @@ class TransmageddonUI:
        self.outputfilename = str(self.nosuffix+self.timestamp+self.ContainerFormatSuffix)
        context_id = self.StatusBar.get_context_id("EOS")
        self.StatusBar.push(context_id, (_("Writing %(filename)s") % {'filename': self.outputfilename}))
-       if self.multipass != False:
+       if self.multipass != 0:
            self.passcounter=int(1)
            self.StatusBar.push(context_id, (_("Pass %(count)d Progress") % {'count': self.passcounter}))
        if self.haveaudio:
@@ -999,8 +996,8 @@ class TransmageddonUI:
            self.containerchoice.set_sensitive(True)
            self.containerchoice.set_active(0)
            self.start_time = False
-           self.multipass = False
-           self.passcounter = False
+           self.multipass = 0
+           self.passcounter = 0
            self.rotationchoice.set_sensitive(True)
            if self.builder.get_object("containerchoice").get_active():
                self.populate_menu_choices()



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]