[transmageddon] Further work on multistream handling



commit d05e9d20a3695f1113abaa829667ea644aae40c1
Author: Christian Fredrik Kalager Schaller <uraeus linuxrisin org>
Date:   Wed Dec 5 14:56:12 2012 +0100

    Further work on multistream handling

 src/transcoder_engine.py |   36 +++++++++---
 src/transmageddon.py     |  149 +++++++++++++++++++++++++---------------------
 2 files changed, 108 insertions(+), 77 deletions(-)
---
diff --git a/src/transcoder_engine.py b/src/transcoder_engine.py
index aad5dcb..ee6ee13 100644
--- a/src/transcoder_engine.py
+++ b/src/transcoder_engine.py
@@ -36,14 +36,17 @@ class Transcoder(GObject.GObject):
             'got-error' : (GObject.SignalFlags.RUN_LAST, None, (GObject.TYPE_PYOBJECT,))
                     }
 
-   def __init__(self, FILECHOSEN, FILENAME, DESTDIR, CONTAINERCHOICE, AUDIOCODECVALUE, VIDEOCODECVALUE, PRESET, 
-                      OHEIGHT, OWIDTH, FRATENUM, FRATEDEN, ACHANNELS, MULTIPASS, PASSCOUNTER, OUTPUTNAME, 
+   def __init__(self, FILECHOSEN, FILENAME, DESTDIR, CONTAINERCHOICE, AUDIODATA, VIDEOCODECVALUE, PRESET, 
+                      OHEIGHT, OWIDTH, FRATENUM, FRATEDEN, MULTIPASS, PASSCOUNTER, OUTPUTNAME, 
                       TIMESTAMP, ROTATIONVALUE, AUDIOPASSTOGGLE, VIDEOPASSTOGGLE, INTERLACED, INPUTVIDEOCAPS):
        GObject.GObject.__init__(self)
 
        # Choose plugin based on Container name
+       self.audiodata = AUDIODATA
+       print(self.audiodata)
        self.container = CONTAINERCHOICE
-       self.audiocaps = AUDIOCODECVALUE
+       self.audiocaps = self.audiodata[0]['audiotype']
+       print("audiocaps " +str(self.audiocaps))
        if self.container != False:
            self.containercaps = Gst.caps_from_string(codecfinder.containermap[CONTAINERCHOICE])
        # special case mp3 which is a no-container format with a container (id3mux)
@@ -69,15 +72,18 @@ class Transcoder(GObject.GObject):
        self.owidth = OWIDTH
        self.fratenum = FRATENUM
        self.frateden = FRATEDEN
-       self.achannels = ACHANNELS
+       self.achannels = self.audiodata[0]['audiochannels']
+       self.astreamid = self.audiodata[0]['streamid']
        self.blackborderflag = False
        self.multipass = MULTIPASS
        self.passcounter = PASSCOUNTER
        self.outputfilename = OUTPUTNAME
        self.timestamp = TIMESTAMP
        self.rotationvalue = int(ROTATIONVALUE)
-       self.vbox = {}
        self.missingplugin= False
+       self.probestreamid = False
+       self.sinkpad = False
+
           
 
        # switching width and height around for rotationchoices where it makes sense
@@ -327,6 +333,16 @@ class Transcoder(GObject.GObject):
      bus.add_signal_watch()
      bus.connect('message', self.on_message)
 
+   def padprobe(self, pad, probeinfo, userdata):
+       event = probeinfo.get_event()
+       eventtype=event.type
+       if eventtype==Gst.EventType.STREAM_START:
+           self.probestreamid = event.parse_stream_start()
+           if self.probestreamid==self.astreamid:
+               print("stream id matches")
+               pad.link(self.sinkpad)
+       return Gst.PadProbeReturn.OK
+
    def on_message(self, bus, message):
        mtype = message.type
        # print(mtype)
@@ -363,7 +379,6 @@ class Transcoder(GObject.GObject):
        return True
 
    def OnDynamicPad(self, uridecodebin, src_pad):
-       # print "src_pad is" +str(src_pad)
        origin = src_pad.query_caps(None)
        if (self.container==False):
            a =  origin.to_string()
@@ -390,14 +405,19 @@ class Transcoder(GObject.GObject):
                            sinkpad = self.encodebin.emit("request-pad", origin)
                if c.startswith("audio/"):
                    if self.passcounter == int(0):
-                       src_pad.link(sinkpad)
+                       self.sinkpad = self.encodebin.emit("request-pad", origin)
+                       src_pad.add_probe(Gst.PadProbeType.EVENT_DOWNSTREAM, self.padprobe, None)
+                       #if self.probestreamid==self.astreamid:
+                       #    print("got streamid from probe")
+                       #    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:
-                       # print "self.colorspaceconverter before use " + str(self.colorspaceconverter)
+                           src_pad.add_probe(Gst.PadProbeType.EVENT_DOWNSTREAM, self.padprobe, None)
                            deinterlacerpad = self.deinterlacer.get_static_pad("sink")
                            src_pad.link(deinterlacerpad)
                            self.videoflipper.get_static_pad("src").link(sinkpad)   
diff --git a/src/transmageddon.py b/src/transmageddon.py
index 4d88223..4738dbe 100644
--- a/src/transmageddon.py
+++ b/src/transmageddon.py
@@ -224,7 +224,7 @@ class TransmageddonUI(Gtk.ApplicationWindow):
        self.videorows=[]
        self.audiocodecs=[]
        self.videocodecs=[]
-       self.flag=False
+
        # set flag so we remove bogus value from menu only once
        self.bogus=0
        
@@ -275,6 +275,7 @@ class TransmageddonUI(Gtk.ApplicationWindow):
        self.containerchoice.connect("changed", self.on_containerchoice_changed)
        self.presetchoice.connect("changed", self.on_presetchoice_changed)
        self.audiorows[0].connect("changed", self.on_audiocodec_changed)
+       self.audiorows[0].set_name("audiorow0")
        self.videorows[0].connect("changed", self.on_videocodec_changed)
        self.rotationchoice.connect("changed", self.on_rotationchoice_changed)
 
@@ -363,7 +364,7 @@ class TransmageddonUI(Gtk.ApplicationWindow):
        self.videopasstoggle=False # toggle for passthrough mode chosen
        self.audiopasstoggle=False
        self.videopass=False # toggle for enabling adding of video passthrough on menu
-       self.audiopass=False
+       self.audiopass=[False]
        self.containertoggle=False # used to not check for encoders with pbutils
        self.discover_done=False # lets us know that discover is finished
        self.missingtoggle=False
@@ -386,7 +387,8 @@ class TransmageddonUI(Gtk.ApplicationWindow):
        self.nocontainernumber = int(13) # this needs to be set to the number of the no container option in the menu (from 0)
        self.p_duration = Gst.CLOCK_TIME_NONE
        self.p_time = Gst.Format.TIME
-       self.streamids=[] # (list of stream ids)
+       self.audiostreamids=[] # (list of stream ids)
+       self.videostreamids=[]
        self.language=[]
        self.audiostreamcounter=int(-1)
        self.videostreamcounter=int(-1)
@@ -399,6 +401,7 @@ class TransmageddonUI(Gtk.ApplicationWindow):
        self.markupaudiocodec=[]
        self.markupvideoinfo=[]
        self.markupvideocodec=[]
+       self.audiodata =[] # create list object to hold the rows
 
        # Populate the Container format combobox
        # print("do we try to populate container choice")
@@ -443,6 +446,15 @@ class TransmageddonUI(Gtk.ApplicationWindow):
 
        self.waiting_for_signal="False"
 
+
+   # define the audiodata structure here as the canonical location. This structure should include everything
+   # needed for the audio pipelines. Use strings to describe the type of data to be stored.
+   # The two caps values should be GStreamer caps objects, not caps in string format. 
+   # When a row is added, any data you are missing at that point should be replaced by 'False' values
+   def add_audiodata_row(self, audiochannels, samplerate, inputaudiocaps, outputaudiocaps, streamid, passthrough, language):
+       audiodata = {'audiochannels' : audiochannels, 'samplerate' : samplerate, 'inputaudiocaps' : inputaudiocaps, 'outputaudiocaps' : outputaudiocaps , 'streamid' : streamid, 'passthrough' : passthrough, 'language' : language }
+       return audiodata
+
    # Get all preset values
    def reverse_lookup(self,v):
        for k in codecfinder.codecmap:
@@ -614,25 +626,24 @@ class TransmageddonUI(Gtk.ApplicationWindow):
            for i in info.get_stream_list():
                if isinstance(i, GstPbutils.DiscovererAudioInfo):
                    streamid=i.get_stream_id()
-                   if streamid not in self.streamids:
+                   if streamid not in self.audiostreamids:
                        self.audiostreamcounter=self.audiostreamcounter+1
-                       print(self.audiostreamcounter)
-                       self.inputaudiocaps.append(i.get_caps())
-                       self.streamids.append(streamid)
-                       self.language.append(GstTag.tag_get_language_name(i.get_language()))
-                       self.audiostreams.append( \
-                           GstPbutils.pb_utils_get_codec_description(self.inputaudiocaps[self.audiostreamcounter]))
-                       self.audiochannels.append(i.get_channels())
-                       self.samplerate.append(i.get_sample_rate())
+                       # self.inputaudiocaps.append(i.get_caps())
+                       self.audiostreamids.append(streamid)
+                       # self.language.append(GstTag.tag_get_language_name(i.get_language()))
+                       # self.audiostreams.append( \
+                       #    GstPbutils.pb_utils_get_codec_description(self.inputaudiocaps[self.audiostreamcounter]))
+                       # self.audiochannels.append(i.get_channels())
+                       # self.samplerate.append(i.get_sample_rate())
                        self.haveaudio=True
-                       self.audiodata = { 'audiochannels' : self.audiochannels[self.audiostreamcounter], \
-                           'samplerate' : self.samplerate[self.audiostreamcounter], 'audiotype' : self.inputaudiocaps[self.audiostreamcounter], \
-                           'clipduration' : clipduration }
-
+                       self.audiodata.append(self.add_audiodata_row(i.get_channels(), i.get_sample_rate(), i.get_caps(), False, streamid, False, i.get_language()))
+                       #print(self.audiodata)
                        if self.audiostreamcounter > 0:
                            combo = Gtk.ComboBoxText.new()
                            self.audiorows.append(combo)
                            self.audiobox.add(self.audiorows[self.audiostreamcounter])
+                           self.audiorows[self.audiostreamcounter].connect("changed", self.on_audiocodec_changed)
+                           self.audiorows[self.audiostreamcounter].set_name("audiorow"+str(self.audiostreamcounter))
                            self.audiorows[self.audiostreamcounter].show()
 
                        self.containerchoice.set_active(-1) # set this here to ensure it happens even with quick audio-only
@@ -640,14 +651,14 @@ class TransmageddonUI(Gtk.ApplicationWindow):
 
                if isinstance(i, GstPbutils.DiscovererVideoInfo):
                    streamid=i.get_stream_id()
-                   if streamid not in self.streamids:
+                   if streamid not in self.videostreamids:
                        self.inputvideocaps=i.get_caps()
                        videotags=i.get_tags()
                        interlacedbool = i.is_interlaced()
                        if interlacedbool is True:
                            self.interlaced=True
                        self.havevideo=True
-                       self.streamids.append(streamid)
+                       self.videostreamids.append(streamid)
                        self.populate_menu_choices() # run this to ensure video menu gets filled
                        videoheight=i.get_height()
                        videowidth=i.get_width()
@@ -670,28 +681,26 @@ class TransmageddonUI(Gtk.ApplicationWindow):
                if self.waiting_for_signal == True:
                    if self.containertoggle == True:
                        if self.codeccontainer != False:
-                           # self.check_for_passthrough(self.codeccontainer)
-                           print("snoke")
+                           self.check_for_passthrough(self.codeccontainer)
                    else:
                        # self.check_for_elements()
                        if self.missingtoggle==False:
                            self._start_transcoding()
                if self.codeccontainer != False:
-                   #self.check_for_passthrough(self.codeccontainer)
-                   print("hei")
+                   self.check_for_passthrough(self.codeccontainer)
        
            # set UI markup, will wary in size depending on number of streams         
 
            if self.haveaudio:
                self.markupaudioinfo=[]
                if self.audiostreamcounter==0:
-                   self.markupaudioinfo.append(''.join(('<small>','Audio channels: ', str(self.audiochannels[self.audiostreamcounter]), '</small>',"\n", '<small>','Audio codec: ',str(GstPbutils.pb_utils_get_codec_description(self.inputaudiocaps[self.audiostreamcounter])), "\n", 'Language: ', self.language[self.audiostreamcounter],'</small>')))
+                   self.markupaudioinfo.append(''.join(('<small>','Audio channels: ', str(self.audiodata[self.audiostreamcounter]['audiochannels']), '</small>',"\n", '<small>','Audio codec: ',str(GstPbutils.pb_utils_get_codec_description(self.audiodata[self.audiostreamcounter]['inputaudiocaps'])), "\n", 'Language: ', self.audiodata[self.audiostreamcounter]['language'],'</small>')))
                    self.audioinformation.set_markup("".join(self.markupaudioinfo))
                else:
                    if self.audiostreamcounter==1:
                        x=0
                        while x <= self.audiostreamcounter:
-                           self.markupaudioinfo.append(''.join(('<small>','<b>','Audiostream no: ',str(x+1),'</b>','</small>',"\n",'<small>','Audio channels: ', str(self.audiochannels[x]), '</small>',"\n", '<small>','Audio codec: ',str(GstPbutils.pb_utils_get_codec_description(self.inputaudiocaps[x])), "\n", 'Language: ', self.language[x],'</small>',"\n")))
+                           self.markupaudioinfo.append(''.join(('<small>','<b>','Audiostream no: ',str(x+1),'</b>','</small>',"\n",'<small>','Audio channels: ', str(self.audiodata[x]['audiochannels']), '</small>',"\n", '<small>','Audio codec: ',str(GstPbutils.pb_utils_get_codec_description(self.audiodata[x]['inputaudiocaps'])), "\n", 'Language: ', self.audiodata[x]['language'],'</small>',"\n")))
                            self.audioinformation.set_markup("".join(self.markupaudioinfo))
                            x=x+1
 
@@ -718,9 +727,9 @@ class TransmageddonUI(Gtk.ApplicationWindow):
    def check_for_passthrough(self, containerchoice):
        videointersect = Gst.Caps.new_empty()
        audiointersect = []
-       for x in self.streamids:
+       for x in self.audiostreamids:
            audiointersect.append(Gst.Caps.new_empty())
-       if containerchoice != False: # or self.usingpreset==False): <- Need to figure out what this was about
+       if containerchoice != False:
            container = codecfinder.containermap[containerchoice]
            containerelement = codecfinder.get_muxer_element(container)
            if containerelement == False:
@@ -736,26 +745,37 @@ class TransmageddonUI(Gtk.ApplicationWindow):
                               self.vsourcecaps = videointersect
                        if self.haveaudio == True:
                            x=0
-                           while x < self.audiostreamcounter:
-                               x=x+1
+                           count=len(self.audiostreamids)
+                           while x < count:
                                if audiointersect[x].is_empty():
-                                   audiointersect[x] = sourcecaps.intersect(self.audiodata['audiotype'])
-                                   # print(audiointersect[x])
+                                   audiointersect[x] = sourcecaps.intersect(self.audiodata[x]['inputaudiocaps'])
                                    self.asourcecaps = audiointersect[x]
+
+                               if audiointersect[x].is_empty():
+                                   if len(self.audiopass)>=x+1:
+                                       self.audiopass[x]=False
+                                   else:
+                                       self.audiopass.append(False)
+                  
+                               else:
+                                   if len(self.audiopass)>=x+1:
+                                       self.audiopass[x]=True
+                                   else:
+                                       self.audiopass.append(True)
+                               x=x+1
+                                   
+               
+
                if videointersect.is_empty():
                    self.videopass=False
                else:
                    self.videopass=True
-               if audiointersect[x].is_empty():
-                   self.audiopass=False
-               else:
-                   self.audiopass=True
-               
+              
 
    # define the behaviour of the other buttons
    def on_FileChooser_file_set(self, widget):
        self.filename = self.builder.get_object ("FileChooser").get_filename()
-       self.audiodata = {}
+       self.audiodata = []
        if self.filename is not None: 
            self.haveaudio=False #make sure to reset these for each file
            self.havevideo=False #
@@ -795,20 +815,11 @@ class TransmageddonUI(Gtk.ApplicationWindow):
            vwidth=False
            ratenum=False
            ratednom=False
-       if self.haveaudio:
-           achannels = self.audiodata['self.audiochannels']
-           if self.audiopasstoggle == False:
-               audiocodec = self.AudioCodec
-           else:
-               audiocodec = self.asourcecaps
-       else:
-           audiocodec=False
-           achannels=False
 
        self._transcoder = transcoder_engine.Transcoder(filechoice, self.filename,
-                        self.outputdirectory, self.codeccontainer, audiocodec, 
+                        self.outputdirectory, self.codeccontainer, self.audiodata,
                         videocodec, self.devicename, 
-                        vheight, vwidth, ratenum, ratednom, achannels, 
+                        vheight, vwidth, ratenum, ratednom, 
                         self.multipass, self.passcounter, self.outputfilename,
                         self.timestamp, self.rotationvalue, self.audiopasstoggle, 
                         self.videopasstoggle, self.interlaced, self.inputvideocaps)
@@ -954,7 +965,7 @@ class TransmageddonUI(Gtk.ApplicationWindow):
            self.passcounter=int(1)
            self.StatusBar.push(context_id, (_("Pass %(count)d Progress") % {'count': self.passcounter}))
        if self.haveaudio:
-           if "samplerate" in self.audiodata:
+           if "samplerate" in self.audiodata[0]:
                # self.check_for_elements()
                if self.missingtoggle==False:
                    self._start_transcoding()
@@ -993,16 +1004,11 @@ class TransmageddonUI(Gtk.ApplicationWindow):
        self.houseclean=True # set this to avoid triggering events when cleaning out menus
        x=0
        while x <= self.audiostreamcounter:
-           #print("audiostream counter is " +str(self.audiostreamcounter))
-           #print("x er " +str(x))
-           #print("self.audiocodecs is " + str(self.audiocodecs))
            if self.audiocodecs:
                for c in self.audiocodecs[x]: # 
                    self.audiorows[x].remove(0)
                if x==self.audiostreamcounter:
                    self.audiocodecs=[]
-                   #print("is it clean " + str(self.audiocodecs))
-                   # print("is the menu clean " + str(self.audiorows))
            if self.havevideo==True:
                if self.codeccontainer != False:
                    for c in self.videocodecs:
@@ -1018,7 +1024,6 @@ class TransmageddonUI(Gtk.ApplicationWindow):
            x=0
            while x <= self.audiostreamcounter:
                self.audiocodecs.append([])
-               # print("self audiorows adding list " +str(self.audiocodecs))
                if self.usingpreset==True: # First fill menu based on presetvalue
                    testforempty = self.presetaudiocodec.to_string()
                    if testforempty != "EMPTY": 
@@ -1037,13 +1042,16 @@ class TransmageddonUI(Gtk.ApplicationWindow):
                else:
                        audiolist = []
                        audio_codecs = supported_audio_container_map[self.codeccontainer]
-                       # print("vi skal fylle meny")
                        for c in audio_codecs:
-                           #print("x is " +str(x))
-                           #print("c is " +str(c))
                            self.audiocodecs[x].append(Gst.caps_from_string(codecfinder.codecmap[c]))
                        for c in self.audiocodecs[x]: # Use codec descriptions from GStreamer
                            self.audiorows[x].append_text(GstPbutils.pb_utils_get_codec_description(c))
+
+               if self.audiopass[x]==True:
+                       self.audiorows[x].append_text(_("Audio passthrough"))
+                       self.audiocodecs[x].append("pass")
+                       self.audiopassmenuno=(len(self.audiocodecs[x]))-1 #FIXME
+
                self.audiorows[x].set_sensitive(True)
                self.audiorows[x].set_active(0)
                x=x+1
@@ -1080,11 +1088,6 @@ class TransmageddonUI(Gtk.ApplicationWindow):
                        self.videorows[0].append_text(_("Video passthrough"))
                        self.videocodecs.append("pass")
                        self.videopassmenuno=(len(self.videocodecs))-1
-                   
-                   if self.audiopass==True:
-                       self.audiorows[0].append_text(_("Audio passthrough"))
-                       self.audiocodecs[x].append("pass")
-                       self.audiopassmenuno=(len(self.audiocodecs[x]))-1
 
    def on_containerchoice_changed(self, widget):
        self.CodecBox.set_sensitive(True)
@@ -1099,7 +1102,7 @@ class TransmageddonUI(Gtk.ApplicationWindow):
                self.codeccontainer = self.builder.get_object ("containerchoice").get_active_text()
                # self.check_for_elements()
        if self.discover_done == True:
-           # self.check_for_passthrough(self.codeccontainer)
+           self.check_for_passthrough(self.codeccontainer)
            self.populate_menu_choices()
            self.transcodebutton.set_sensitive(True)
 
@@ -1137,14 +1140,22 @@ class TransmageddonUI(Gtk.ApplicationWindow):
        self.rotationvalue = self.rotationchoice.get_active()
 
    def on_audiocodec_changed(self, widget):
+       name=widget.get_name()
+       if name.startswith("audiorow"):
+          x=name[8:]
+          x=int(x)
        self.audiopasstoggle=False
        if (self.houseclean == False and self.usingpreset==False):
-           self.AudioCodec = self.audiocodecs[self.audiorows[0].get_active()]
-           if self.codeccontainer != False:
-               if self.audiorows[0].get_active() ==  self.audiopassmenuno:
-                   self.audiopasstoggle=True
-       elif self.usingpreset==True:
-           self.AudioCodec = self.presetaudiocodec    
+               no=self.audiorows[x].get_active()
+               self.audiodata[x]['outputaudiocaps'] = self.audiocodecs[x][no]
+               if self.codeccontainer != False:
+                   if self.audiorows[x].get_active() ==  self.audiopassmenuno:
+                       self.audiodata[x]['passthrough']= True
+                   else:
+                       self.audiodata[x]['passthrough']= False
+                   # print(self.audiodata)
+               elif self.usingpreset==True:
+                   self.audiodata[x]['outputaudiocaps'] = self.presetaudiocodec
 
    def on_videocodec_changed(self, widget):
        self.videopasstoggle=False



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