[transmageddon] Partway comit of new encodebin work



commit 7e883f35c8fd04865f6ea4f873898498dfc0f32a
Author: Christian Fredrik Kalager Schaller <christian schaller collabora co uk>
Date:   Sun Feb 6 17:25:30 2011 +0000

    Partway comit of new encodebin work

 src/transcoder_engine_encodebin.py |  429 ++++++++++++++++++++++++++++++++++++
 src/transmageddon.py               |  167 +++++++++------
 2 files changed, 529 insertions(+), 67 deletions(-)
---
diff --git a/src/transcoder_engine_encodebin.py b/src/transcoder_engine_encodebin.py
new file mode 100644
index 0000000..fb7c05e
--- /dev/null
+++ b/src/transcoder_engine_encodebin.py
@@ -0,0 +1,429 @@
+# Transmageddon
+# Copyright (C) 2009 Christian Schaller <uraeus gnome org>
+# 
+# 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
+import codecfinder
+import presets
+
+try:
+   import gobject; gobject.threads_init()
+   import pygst
+   import glib
+   pygst.require("0.10")
+   import gst
+except Exception, e:
+   print "failed to import required modules"
+   print e
+   sys.exit(1)
+
+class Transcoder(gobject.GObject):
+
+   __gsignals__ = {
+            'ready-for-querying' : (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, []),
+            'got-eos' : (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, []),
+            'got-error' : (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, (gobject.TYPE_PYOBJECT,))
+                    }
+
+   def __init__(self, FILECHOSEN, FILENAME, DESTDIR, CONTAINERCHOICE, AUDIOCODECVALUE, VIDEOCODECVALUE, PRESET, 
+                      OHEIGHT, OWIDTH, FRATENUM, FRATEDEN, ACHANNELS, MULTIPASS, PASSCOUNTER, OUTPUTNAME, 
+                      TIMESTAMP, ROTATIONVALUE, AUDIOPASSTOGGLE, VIDEOPASSTOGGLE, INTERLACED):
+       gobject.GObject.__init__(self)
+
+       # Choose plugin based on Container name
+       containercaps = codecfinder.containermap[CONTAINERCHOICE]
+       self.ContainerFormatPlugin = codecfinder.get_muxer_element(containercaps)
+
+       # Choose plugin based on Codec Name
+       # or switch to remuxing mode if any of the values are set to 'pastr'
+       self.stoptoggle=False
+       self.audiocaps = AUDIOCODECVALUE
+       self.videocaps = VIDEOCODECVALUE
+       self.audiopasstoggle = AUDIOPASSTOGGLE
+       self.interlaced = INTERLACED
+       self.videopasstoggle = VIDEOPASSTOGGLE
+       self.doaudio= False
+       if self.audiopasstoggle == False:
+           # print "audiopasstoggle is false, setting AudioEncoderPlugin"
+           # print "self.audiocaps IS **** " + str(self.audiocaps)
+           self.AudioEncoderPlugin = codecfinder.get_audio_encoder_element(self.audiocaps)
+       if self.videopasstoggle == False:
+           # print "self.videopasstoggle is false so setting self.VideoEncoderPlugin"
+           # print "look at incoming videocaps " + str(self.videocaps)
+           self.VideoEncoderPlugin = codecfinder.get_video_encoder_element(self.videocaps)
+           # print "self.VideoEncoderPlugin " + str(self.VideoEncoderPlugin)
+       self.preset = PRESET
+       self.oheight = OHEIGHT
+       self.owidth = OWIDTH
+       self.fratenum = FRATENUM
+       self.frateden = FRATEDEN
+       self.achannels = ACHANNELS
+       # print "transcoder_engine achannels is " + str(self.achannels)
+       self.blackborderflag = False
+       self.multipass = MULTIPASS
+       self.passcounter = PASSCOUNTER
+       self.outputfilename = OUTPUTNAME
+       self.timestamp = TIMESTAMP
+       self.rotationvalue = int(ROTATIONVALUE)
+       self.vbox = {}
+
+       # if needed create a variable to store the filename of the multipass statistics file
+       if self.multipass != False:
+           self.cachefile = (str(glib.get_user_cache_dir())+"/"+"multipass-cache-file"+self.timestamp+".log")
+
+       # Create transcoding pipeline
+       self.pipeline = gst.Pipeline("TranscodingPipeline")
+       self.pipeline.set_state(gst.STATE_PAUSED)
+
+       self.uridecoder = gst.element_factory_make("uridecodebin", "uridecoder")
+       self.uridecoder.set_property("uri", FILECHOSEN)
+       self.uridecoder.connect("pad-added", self.OnDynamicPad)
+
+       self.gstmultiqueue = gst.element_factory_make("multiqueue")
+       self.multiqueueaudiosinkpad = self.gstmultiqueue.get_request_pad("sink0")
+       self.multiqueuevideosinkpad = self.gstmultiqueue.get_request_pad("sink1")
+       self.multiqueueaudiosrcpad = self.gstmultiqueue.get_pad("src0")
+       self.multiqueuevideosrcpad = self.gstmultiqueue.get_pad("src1")
+
+       self.pipeline.add(self.gstmultiqueue) 
+
+       self.encodebinprofile = gst.pbutils.EncodingContainerProfile ("ogg", None , gst.Caps("application/ogg"), None)
+       self.videoprofile = gst.pbutils.EncodingVideoProfile (gst.Caps("video/x-theora"), None, gst.caps_new_any(), 0)
+       self.audioprofile = gst.pbutils.EncodingAudioProfile (gst.Caps("audio/x-vorbis"), None, gst.caps_new_any(), 0)
+       self.encodebinprofile.add_profile(self.videoprofile)
+       self.encodebinprofile.add_profile(self.audioprofile)
+
+       self.encodebin = gst.element_factory_make ("encodebin", None)
+       self.encodebin.set_property("profile", self.encodebinprofile)
+       self.pipeline.add(self.encodebin)
+
+       self.remuxcaps = gst.Caps()
+       if self.audiopasstoggle:
+          self.remuxcaps.append(self.audiocaps)
+       if self.videopasstoggle:
+          self.remuxcaps.append(self.videocaps)
+       if self.audiopasstoggle and not self.videopasstoggle:
+          self.remuxcaps.append_structure(gst.Structure("video/x-raw-rgb"))
+          self.remuxcaps.append_structure(gst.Structure("video/x-raw-yuv"))
+       if self.videopasstoggle and not self.audiopasstoggle:
+          self.remuxcaps.append_structure(gst.Structure("audio/x-raw-float"))
+          self.remuxcaps.append_structure(gst.Structure("audio/x-raw-int"))  
+
+       if (self.audiopasstoggle) or (self.videopasstoggle):
+           # print "remuxcaps is " + str(self.remuxcaps)
+           self.uridecoder.set_property("caps", self.remuxcaps)
+       self.pipeline.add(self.uridecoder)
+
+       self.containermuxer = gst.element_factory_make(self.ContainerFormatPlugin, "containermuxer")
+       videointersect = ("EMPTY")
+       audiointersect = ("EMPTY")   
+       factory = gst.registry_get_default().lookup_feature(self.ContainerFormatPlugin)
+       for x in factory.get_static_pad_templates():
+           if (x.direction == gst.PAD_SINK):
+               sourcecaps = x.get_caps()
+               if videointersect == ("EMPTY"): 
+                   videointersect = sourcecaps.intersect(gst.caps_from_string(self.videocaps))
+                   if videointersect != ("EMPTY"):
+                   # print "pad is X which is " + str(x)
+                       self.containermuxervideosinkpad = self.containermuxer.get_request_pad(x.name_template)
+               if audiointersect == ("EMPTY"):
+                   audiointersect = sourcecaps.intersect(gst.caps_from_string(self.audiocaps))
+                   if audiointersect != ("EMPTY"):
+                       self.containermuxeraudiosinkpad = self.containermuxer.get_request_pad(x.name_template)
+       self.pipeline.add(self.containermuxer)
+
+       # Add a tag setting Transmageddon as the application used for creating file if supported by format
+       GstTagSetterType = gobject.type_from_name("GstTagSetter")
+       if GstTagSetterType in gobject.type_interfaces(self.containermuxer):
+           taglist=gst.TagList()
+           taglist[gst.TAG_APPLICATION_NAME] = "Transmageddon"
+           self.containermuxer.merge_tags(taglist, gst.TAG_MERGE_APPEND)
+
+       self.transcodefileoutput = gst.element_factory_make("filesink", "transcodefileoutput")
+       self.transcodefileoutput.set_property("location", (DESTDIR+"/"+self.outputfilename))
+       self.pipeline.add(self.transcodefileoutput)
+
+       self.transcodefileoutput2 = gst.element_factory_make("filesink", "transcodefileoutput2")
+       self.transcodefileoutput2.set_property("location", (DESTDIR+"/"+self.outputfilename+"B"))
+       self.pipeline.add(self.transcodefileoutput2)
+       self.encodebin.link(self.transcodefileoutput2)
+
+       self.containermuxer.link(self.transcodefileoutput)
+       # print "reached end of first pipeline bulk, next step dynamic audio/video pads"
+   
+
+       self.uridecoder.set_state(gst.STATE_PAUSED)
+       self.encodebin.set_state(gst.STATE_PAUSED)
+       # print "setting uridcodebin to paused"
+       self.BusMessages = self.BusWatcher()
+
+       self.uridecoder.connect("no-more-pads", self.noMorePads) # we need to wait on this one before going further
+       # print "connecting to no-more-pads"
+
+       # Some encoders like x264enc are not able to handle odd height or widths
+      # if width % 2:
+        #   width += 1
+      # if height % 2:
+       #    height += 1
+
+       if self.rotationvalue == 1 or self.rotationvalue == 3:
+           # print "switching height and with around"
+           nwidth = height
+           nheight = width
+           height = nheight
+           width = nwidth
+
+       # 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)):
+           self.transcodefileoutput2.set_state(gst.STATE_PAUSED)
+           self.containermuxer.set_state(gst.STATE_PAUSED)
+       glib.idle_add(self.idlePlay)
+       # print "No More pads received"
+
+   def idlePlay(self):
+        self.Pipeline("playing")
+        # print "gone to playing"
+        return False
+
+   def BusWatcher(self):
+       bus = self.pipeline.get_bus()
+       bus.add_watch(self.on_message)
+
+   def on_message(self, bus, message):
+       mtype = message.type
+       # print mtype
+       if mtype == gst.MESSAGE_ERROR:
+           err, debug = message.parse_error()
+           print err 
+           print debug
+           gst.DEBUG_BIN_TO_DOT_FILE (self.pipeline, gst.DEBUG_GRAPH_SHOW_ALL, 'transmageddon.dot')
+       elif mtype == gst.MESSAGE_ASYNC_DONE:
+           self.emit('ready-for-querying')
+       elif mtype == gst.MESSAGE_EOS:
+           if (self.multipass != False):
+               if (self.passcounter == 0):
+                   #removing multipass cache file when done
+                   if os.access(self.cachefile, os.F_OK):
+                       os.remove(self.cachefile)
+           self.emit('got-eos')
+           self.pipeline.set_state(gst.STATE_NULL)
+       elif mtype == gst.MESSAGE_APPLICATION:
+           print "I am getting the appliation message"
+           self.pipeline.set_state(gst.STATE_NULL)
+           self.pipeline.remove(self.uridecoder)
+       return True
+
+   def list_compat(self, a1, b1):
+       for x1 in a1:
+           if not x1 in b1:
+               return False
+       return True
+
+   def OnDynamicPad(self, uridecodebin, src_pad):
+       c = src_pad.get_caps().to_string()
+       print "c is " + str(c)
+       sinkpad = self.encodebin.emit("request-pad", src_pad.get_caps())
+       print "action signal returned", sinkpad
+       src_pad.link(sinkpad)
+  
+
+
+
+   bob=False
+   if bob != False:
+   #def OnDynamicPad(self, dbin, sink_pad):
+       c = sink_pad.get_caps().to_string()
+       if c.startswith("audio/"):
+           if self.stoptoggle==True:
+               bus = self.pipeline.get_bus()
+               bus.post(gst.message_new_application(self.pipeline, gst.Structure('STOP TRANSCODER')))
+               #return
+           # First check for passthough mode
+           if self.audiopasstoggle is False:
+               # Check if either we are not doing multipass or if its the final pass before enabling audio
+               if (self.multipass == False) or (self.passcounter == int(0)):
+                   self.audioconverter = gst.element_factory_make("audioconvert")
+                   self.pipeline.add(self.audioconverter)
+                   self.audioencoder = gst.element_factory_make(self.AudioEncoderPlugin)
+                   self.pipeline.add(self.audioencoder)
+           
+                   self.audioresampler = gst.element_factory_make("audioresample")
+                   self.pipeline.add(self.audioresampler)
+                   sink_pad.link(self.audioconverter.get_pad("sink"))
+
+                   self.audioconverter.link(self.audioresampler)
+                   self.audioresampler.link(self.audioencoder)
+
+                   self.audioencoder.get_static_pad("src").link(self.multiqueueaudiosinkpad)
+                   self.audioconverter.set_state(gst.STATE_PAUSED)
+                   self.audioresampler.set_state(gst.STATE_PAUSED)
+                   self.audioencoder.set_state(gst.STATE_PAUSED)
+                   self.gstmultiqueue.set_state(gst.STATE_PAUSED)
+                   self.multiqueueaudiosrcpad.link(self.containermuxeraudiosinkpad)
+
+           else:
+               # This code is for handling passthrough mode. 
+               # TODO: dynamically plug correct parser. Iterate on parsers and intersect.
+               # No parser if output is framed
+               parsedcaps = gst.caps_from_string(self.audiocaps+",parsed=true")
+               framedcaps = gst.caps_from_string(self.audiocaps+",framed=true")
+               if (sink_pad.get_caps().is_subset(parsedcaps)) or (sink_pad.get_caps().is_subset(framedcaps)):
+                   sink_pad.link(self.multiqueueaudiosinkpad)
+                   self.multiqueueaudiosrcpad.link(self.containermuxeraudiosinkpad)
+                   self.gstmultiqueue.set_state(gst.STATE_PAUSED)
+               else:
+                   flist = gst.registry_get_default().get_feature_list(gst.ElementFactory)
+                   parsers = []
+                   self.aparserelement = False
+                   for fact in flist:
+                       # print "fact is " + str(fact)
+                       if self.list_compat(["Codec", "Parser","Audio"], fact.get_klass().split('/')):
+                           parsers.append(fact.get_name())
+                           for x in parsers:
+                               parser = x
+                               factory = gst.registry_get_default().lookup_feature(str(x))
+                               sinkcaps = [x.get_caps() for x in factory.get_static_pad_templates() if x.direction == gst.PAD_SRC]
+                               parseintersect = ("EMPTY")   
+                               for caps in sinkcaps:
+                                   if parseintersect == ("EMPTY"):
+                                       parseintersect = caps.intersect(gst.caps_from_string(self.audiocaps))
+                                   if parseintersect != ("EMPTY"):
+                                       self.aparserelement = parser
+                   if self.aparserelement == False:
+                                   error_message="noaudioparser"
+                                   self.emit("got-error", error_message)
+                                   self.stoptoggle=True
+                                 #  return  
+                   self.audioparse = gst.element_factory_make(self.aparserelement)
+                   self.pipeline.add(self.audioparse)
+
+                   # print "audiopad " + str(self.multiqueueaudiosinkpad)
+                   sink_pad.link(self.audioparse.get_static_pad("sink"))
+                   self.audioparse.get_static_pad("src").link(self.multiqueueaudiosinkpad)                    
+                   self.multiqueueaudiosrcpad.link(self.containermuxeraudiosinkpad)
+                   self.audioparse.set_state(gst.STATE_PAUSED)
+                   self.gstmultiqueue.set_state(gst.STATE_PAUSED)
+
+       elif c.startswith("video/"):
+           if self.stoptoggle==True:
+               bus = self.pipeline.get_bus()
+               bus.post(gst.message_new_application(self.pipeline, gst.Structure('STOP TRANSCODER')))
+               #return
+           if self.videopasstoggle == False:
+               # print "Got an video cap"
+               self.colorspaceconverter = gst.element_factory_make("ffmpegcolorspace")
+               self.pipeline.add(self.colorspaceconverter)
+               # checking for deinterlacer
+               if self.interlaced == True:
+                   self.deinterlacer = gst.element_factory_make("deinterlace", "deinterlacer")
+                   self.pipeline.add(self.deinterlacer)
+               self.videoflipper = gst.element_factory_make("videoflip")
+               self.videoflipper.set_property("method", self.rotationvalue)
+               self.pipeline.add(self.videoflipper)
+
+               self.vcaps2 = gst.Caps()
+               self.vcaps2 = gst.caps_from_string(self.videocaps)
+               if self.preset != "nopreset":
+                   height, width, num, denom, pixelaspectratio = self.provide_presets()
+                   for vcap in self.vcaps2:
+                       if pixelaspectratio != gst.Fraction(0, 0):
+                           vcap["pixel-aspect-ratio"] = pixelaspectratio
+               self.vcapsfilter2 = gst.element_factory_make("capsfilter")
+               self.vcapsfilter2.set_property("caps", self.vcaps2)
+               self.pipeline.add(self.vcapsfilter2)
+
+ 
+               self.videoencoder = gst.element_factory_make(self.VideoEncoderPlugin)
+               self.pipeline.add(self.videoencoder)
+
+               # check if interlaced
+               if self.interlaced:
+                   sink_pad.link(self.deinterlacer.get_pad("sink"))
+                   self.deinterlacer.link(self.videoflipper)
+                   self.videoflipper.link(self.colorspaceconverter)
+                   self.colorspaceconverter.link(self.videoencoder)
+               else:
+                   sink_pad.link(self.colorspaceconverter.get_pad("sink"))
+                   self.colorspaceconverter.link(self.videoflipper)
+                   self.videoflipper.link(self.videoencoder)
+
+               self.videoencoder.link(self.vcapsfilter2)
+               self.vcapsfilter2.get_static_pad("src").link(self.multiqueuevideosinkpad)
+
+               self.colorspaceconverter.set_state(gst.STATE_PAUSED)
+               if self.interlaced:
+                   self.deinterlacer.set_state(gst.STATE_PAUSED)
+               self.videoflipper.set_state(gst.STATE_PAUSED)  
+
+               self.vcapsfilter2.set_state(gst.STATE_PAUSED)
+               self.videoencoder.set_state(gst.STATE_PAUSED)
+               self.gstmultiqueue.set_state(gst.STATE_PAUSED)
+               self.multiqueuevideosrcpad.link(self.containermuxervideosinkpad)
+           else:
+               # Code for passthrough mode
+               vparsedcaps = gst.caps_from_string(self.videocaps+",parsed=true")
+               vframedcaps = gst.caps_from_string(self.videocaps+",framed=true")
+               if (sink_pad.get_caps().is_subset(vparsedcaps)) or (sink_pad.get_caps().is_subset(vframedcaps)):
+                   sink_pad.link(self.multiqueuevideosinkpad)
+                   self.multiqueuevideosrcpad.link(self.containermuxervideosinkpad)
+                   self.gstmultiqueue.set_state(gst.STATE_PAUSED)
+               else:
+                   flist = gst.registry_get_default().get_feature_list(gst.ElementFactory)
+                   parsers = []
+                   self.vparserelement = False
+                   for fact in flist:
+                       if self.list_compat(["Codec", "Parser","Video"], fact.get_klass().split('/')):
+                           parsers.append(fact.get_name())
+                       elif self.list_compat(["Codec", "Parser"], fact.get_klass().split('/')):
+                           parsers.append(fact.get_name())
+                           for x in parsers:
+                               parser = x
+                               factory = gst.registry_get_default().lookup_feature(str(x))
+                               sinkcaps = [x.get_caps() for x in factory.get_static_pad_templates() if x.direction == gst.PAD_SRC]
+                               parseintersect = ("EMPTY")   
+                               for caps in sinkcaps:
+                                   if parseintersect == ("EMPTY"):
+                                       parseintersect = caps.intersect(gst.caps_from_string(self.videocaps))
+                                   if parseintersect != ("EMPTY"):
+                                       self.vparserelement = parser                               
+                   if self.vparserelement == False:
+                                   error_message="novideoparser"
+                                   self.emit("got-error", error_message)
+                                   self.stoptoggle=True
+                                   #return
+
+
+                   self.videoparse = gst.element_factory_make(self.vparserelement)
+                   self.pipeline.add(self.videoparse)
+                   sink_pad.link(self.videoparse.get_static_pad("sink"))
+                   self.videoparse.get_static_pad("src").link(self.multiqueuevideosinkpad)
+                   self.videoparse.set_state(gst.STATE_PAUSED)                    
+                   self.multiqueuevideosrcpad.link(self.containermuxervideosinkpad)
+                   self.gstmultiqueue.set_state(gst.STATE_PAUSED)
+       else:
+           raise Exception("Got a non-A/V pad!")
+           # print "Got a non-A/V pad!"
+
+   def Pipeline (self, state):
+       if state == ("playing"):
+           self.pipeline.set_state(gst.STATE_PLAYING)
+       elif state == ("null"):
+           self.pipeline.set_state(gst.STATE_NULL)
diff --git a/src/transmageddon.py b/src/transmageddon.py
index 7f9ba6d..8896856 100644
--- a/src/transmageddon.py
+++ b/src/transmageddon.py
@@ -28,6 +28,7 @@ import time
 import transcoder_engine
 import transcoder_engine_preset
 import transcoder_engine_audio
+import transcoder_engine_encodebin
 import gobject; gobject.threads_init()
 from urlparse import urlparse
 import codecfinder
@@ -121,18 +122,19 @@ supported_video_container_map = {
 }
 
 supported_audio_container_map = {
-    'Ogg':        [ 'Vorbis', 'FLAC', 'Speex', 'Celt Ultra' ],
-    'MXF':        [ 'mp3', 'AAC', 'AC3' ],
-    'Matroska':   [ 'FLAC', 'AAC', 'ac3', 'Vorbis' ],
-    'AVI':        [ 'mp3', 'AC3', 'Windows Media Audio 2' ],
-    'Quicktime':  [ 'AAC', 'AC3', 'mp3' ],
-    'MPEG4':      [ 'AAC', 'mp3' ],
-    '3GPP':       [ 'AAC', 'mp3', 'AMR-NB' ],
-    'MPEG PS':    [ 'mp3', 'AC3', 'AAC' ],
-    'MPEG TS':    [ 'mp3', 'AC3', 'AAC' ],
-    'FLV':        [ 'mp3' ],
-    'ASF':        [ 'Windows Media Audio 2', 'mp3'],
-    'WebM':       [ 'Vorbis']
+    'Ogg':         [ 'Vorbis', 'FLAC', 'Speex', 'Celt Ultra' ],
+    'MXF':         [ 'mp3', 'AAC', 'AC3' ],
+    'Matroska':    [ 'FLAC', 'AAC', 'ac3', 'Vorbis' ],
+    'AVI':         [ 'mp3', 'AC3', 'Windows Media Audio 2' ],
+    'Quicktime':   [ 'AAC', 'AC3', 'mp3' ],
+    'MPEG4':       [ 'AAC', 'mp3' ],
+    '3GPP':        [ 'AAC', 'mp3', 'AMR-NB' ],
+    'MPEG PS':     [ 'mp3', 'AC3', 'AAC' ],
+    'MPEG TS':     [ 'mp3', 'AC3', 'AAC' ],
+    'FLV':         [ 'mp3' ],
+    'ASF':         [ 'Windows Media Audio 2', 'mp3'],
+    'WebM':        [ 'Vorbis'],
+    'No container':[ 'mp3','AAC','FLAC']
 }
 
 
@@ -291,6 +293,11 @@ class TransmageddonUI:
        self.missingtoggle=False
        self.oldaudiocodec={}
        self.oldvideocodec={}
+       self.interlaced=False
+       self.havevideo=False
+       self.haveaudio=False
+       self.devicename = "nopreset"
+       self.nocontaineroptiontoggle=False
 
        self.p_duration = gst.CLOCK_TIME_NONE
        self.p_time = gst.FORMAT_TIME
@@ -484,7 +491,7 @@ class TransmageddonUI:
                audiotags=i.get_tags()
                audiochannels=i.get_channels()
                samplerate=i.get_sample_rate()
-
+               self.haveaudio=True
                self.audiodata = { 'audiochannels' : audiochannels, 'samplerate' : samplerate, 'audiotype' : inputaudiocaps, 'clipduration' : clipduration }
                self.audioinformation.set_markup(''.join(('<small>', 'Audio channels: ', str(audiochannels) ,'</small>')))
                self.audiocodec.set_markup(''.join(('<small>','Audio codec: ', str(gst.pbutils.get_codec_description(inputaudiocaps)),'</small>')))
@@ -495,8 +502,7 @@ class TransmageddonUI:
                interlacedbool = i.is_interlaced()
                if interlacedbool is True:
                    self.interlaced=True
-               else:
-                   self.interlaced=False
+               self.havevideo=True
                videoheight=i.get_height()
                videowidth=i.get_width()
                videodenom=i.get_framerate_denom()
@@ -512,6 +518,10 @@ class TransmageddonUI:
 #
 
            self.discover_done=True
+           if self.havevideo==False:
+               self.videoinformation.set_markup(''.join(('<small>', "No Video", '</small>')))
+               self.videocodec.set_markup(''.join(('<small>', "",
+                                      '</small>')))
            if self.waiting_for_signal == True:
                if self.containertoggle == True:
                    if self.container != False:
@@ -535,32 +545,35 @@ class TransmageddonUI:
    def check_for_passthrough(self, containerchoice):
        videointersect = ("EMPTY")
        audiointersect = ("EMPTY")
-       # print "container is " + str(containerchoice)
-       container = codecfinder.containermap[containerchoice]
-       containerelement = codecfinder.get_muxer_element(container)
-       # print "container element is " + str(containerelement)
-       if containerelement == False:
-           self.containertoggle = True
-           self.check_for_elements()
-       else:
-           factory = gst.registry_get_default().lookup_feature(containerelement)
-           for x in factory.get_static_pad_templates():
-               if (x.direction == gst.PAD_SINK):
-                   sourcecaps = x.get_caps()
-                   if videointersect == ("EMPTY"):
-                       videointersect = sourcecaps.intersect(self.videodata['videotype'])
-                       if videointersect != ("EMPTY"):
-                           self.vsourcecaps = videointersect
-                   if audiointersect == ("EMPTY"):
-                       audiointersect = sourcecaps.intersect(self.audiodata['audiotype'])
-                       if audiointersect != ("EMPTY"):
-                           self.asourcecaps = audiointersect
-           if videointersect != ("EMPTY"):
-               self.videorows[0].append_text("Video passthrough")
-               self.oldvideocodec.append("Video passthrough")
-           if audiointersect != ("EMPTY"):
-               self.audiorows[0].append_text("Audio passthrough")
-               self.oldaudiocodec.append("Audio passthrough")
+       print "containerchoice is " + str(containerchoice)
+       if containerchoice != "No container":
+           # print "container is " + str(containerchoice)
+           container = codecfinder.containermap[containerchoice]
+           containerelement = codecfinder.get_muxer_element(container)
+           # print "container element is " + str(containerelement)
+           if containerelement == False:
+               self.containertoggle = True
+               self.check_for_elements()
+           else:
+               factory = gst.registry_get_default().lookup_feature(containerelement)
+               for x in factory.get_static_pad_templates():
+                   if (x.direction == gst.PAD_SINK):
+                       sourcecaps = x.get_caps()
+                       if self.havevideo==True:
+                          if videointersect == ("EMPTY"):
+                              videointersect = sourcecaps.intersect(self.videodata['videotype'])
+                              if videointersect != ("EMPTY"):
+                                  self.vsourcecaps = videointersect
+                       if audiointersect == ("EMPTY"):
+                           audiointersect = sourcecaps.intersect(self.audiodata['audiotype'])
+                           if audiointersect != ("EMPTY"):
+                               self.asourcecaps = audiointersect
+               if videointersect != ("EMPTY"):
+                   self.videorows[0].append_text("Video passthrough")
+                   self.oldvideocodec.append("Video passthrough")
+               if audiointersect != ("EMPTY"):
+                   self.audiorows[0].append_text("Audio passthrough")
+                   self.oldaudiocodec.append("Audio passthrough")
 
    # define the behaviour of the other buttons
    def on_FileChooser_file_set(self, widget):
@@ -569,37 +582,51 @@ class TransmageddonUI:
        if self.filename is not None: 
            codecinfo = self.mediacheck(self.filename)
            self.containerchoice.set_sensitive(True)
-           self.presetchoice.set_sensitive(True)
-           self.presetchoice.set_active(0)
            self.ProgressBar.set_fraction(0.0)
            self.ProgressBar.set_text(_("Transcoding Progress"))
+           if (self.havevideo==False and self.nocontaineroptiontoggle==False):
+               self.containerchoice.append_text("No container")
+               self.nocontaineroptiontoggle=True
+           else:
+               self.presetchoice.set_sensitive(True)
+               self.presetchoice.set_active(0)
+               self.containerchoice.remove_text(13)
+               self.nocontaineroptiontoggle=False
 
    def _start_transcoding(self): 
        filechoice = self.builder.get_object ("FileChooser").get_uri()
        self.filename = self.builder.get_object ("FileChooser").get_filename()
-       vheight = self.videodata['videoheight']
-       vwidth = self.videodata['videowidth']
-       ratenum = self.videodata['fratenum']
-       ratednom = self.videodata['frateden']
+       if self.havevideo:
+           vheight = self.videodata['videoheight']
+           vwidth = self.videodata['videowidth']
+           ratenum = self.videodata['fratenum']
+           ratednom = self.videodata['frateden']
+           if self.videopasstoggle == False:
+               videocodec = codecfinder.codecmap[self.VideoCodec]
+           else:
+               videocodec = gst.Caps.to_string(self.vsourcecaps)
        achannels = self.audiodata['audiochannels']
-       if self.videopasstoggle == False:
-           videocodec = codecfinder.codecmap[self.VideoCodec]
-       else:
-           videocodec = gst.Caps.to_string(self.vsourcecaps)
        if self.audiopasstoggle == False:
            audiocodec = codecfinder.codecmap[self.AudioCodec]
        else:
            audiocodec = gst.Caps.to_string(self.asourcecaps)
        container = self.builder.get_object ("containerchoice").get_active_text ()
-       print self.devicename
        if self.devicename == "nopreset":
-           self._transcoder = transcoder_engine.Transcoder(filechoice, self.filename, self.videodirectory, container, 
+           if self.havevideo: 
+               # non-preset transcoding with audio and video
+               self._transcoder = transcoder_engine_encodebin.Transcoder(filechoice, self.filename, self.videodirectory, container, 
                                                        audiocodec, videocodec, self.devicename, 
                                                        vheight, vwidth, ratenum, ratednom, achannels, 
                                                        self.multipass, self.passcounter, self.outputfilename,
                                                        self.timestamp, self.rotationvalue, self.audiopasstoggle, 
                                                        self.videopasstoggle, self.interlaced)
+           else:
+               # non-preset transcoding with audio only
+               self._transcoder = transcoder_engine_audio.Transcoder(filechoice, self.filename, self.videodirectory, container, 
+                                                       audiocodec, achannels, self.outputfilename,
+                                                       self.timestamp, self.audiopasstoggle)
        else:
+           # transcoding with preset
            self._transcoder = transcoder_engine_preset.Transcoder(filechoice, self.filename, self.videodirectory, container, 
                                                        audiocodec, videocodec, self.devicename, 
                                                        vheight, vwidth, ratenum, ratednom, achannels, 
@@ -650,15 +677,20 @@ class TransmageddonUI:
 
    def check_for_elements(self):
        containerchoice = self.builder.get_object ("containerchoice").get_active_text ()
-       containerstatus = codecfinder.get_muxer_element(codecfinder.containermap[containerchoice])
+       if containerchoice == "No container":
+           containerstatus=True
+       else:
+           containerstatus = codecfinder.get_muxer_element(codecfinder.containermap[containerchoice])
        # print "containerstatus is " + str(containerstatus)
        if self.AudioCodec != "Audio passthrough":
            audiostatus = codecfinder.get_audio_encoder_element(codecfinder.codecmap[self.AudioCodec])
        else:
            audiostatus = "Audio passthrough"
-       if self.VideoCodec != "Video passthrough":
-           videostatus = codecfinder.get_video_encoder_element(codecfinder.codecmap[self.VideoCodec])
-
+       if self.havevideo:
+           if self.VideoCodec != "Video passthrough":
+               videostatus = codecfinder.get_video_encoder_element(codecfinder.codecmap[self.VideoCodec])
+       else:
+           videostatus=True    
 
        if not containerstatus or not videostatus or not audiostatus:
            self.missingtoggle=True
@@ -709,6 +741,7 @@ class TransmageddonUI:
            self.ProgressBar.set_text(_("Pass %(count)d Progress") % {'count': self.passcounter})
        if self.audiodata.has_key("samplerate"):
            self.check_for_elements()
+           print "missingtoggle is " + str(self.missingtoggle)
            if self.missingtoggle==False:
                self._start_transcoding()
        else:
@@ -731,7 +764,6 @@ class TransmageddonUI:
 
    def on_containerchoice_changed(self, widget):
        self.CodecBox.set_sensitive(True)
-       self.rotationchoice.set_sensitive(True)
        self.ProgressBar.set_fraction(0.0)
        self.ProgressBar.set_text(_("Transcoding Progress"))
        self.container = self.builder.get_object ("containerchoice").get_active_text ()
@@ -744,15 +776,16 @@ class TransmageddonUI:
            self.audiorows[0].set_sensitive(True)
            self.audiorows[0].set_active(0)
        self.oldaudiocodec=audio_codecs
-
-       video_codecs = supported_video_container_map[self.container]
-       for c in self.oldvideocodec:
-           self.videorows[0].remove_text(0)
-       for c in video_codecs:
-           self.videorows[0].append_text(c)
-           self.videorows[0].set_sensitive(True)
-           self.videorows[0].set_active(0)
-       self.oldvideocodec=video_codecs
+       if self.havevideo==True:
+           self.rotationchoice.set_sensitive(True)
+           video_codecs = supported_video_container_map[self.container]
+           for c in self.oldvideocodec:
+               self.videorows[0].remove_text(0)
+           for c in video_codecs:
+               self.videorows[0].append_text(c)
+               self.videorows[0].set_sensitive(True)
+               self.videorows[0].set_active(0)
+           self.oldvideocodec=video_codecs
 
        if self.discover_done == True:
            self.check_for_passthrough(self.container)



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