Hey there everyone,
I have been messing with gstreamer for a bit now, and have a strange experience. I managed to get a pipeline for a camera that goes through an appsink and appsrc to work temporarily. It tended to be flaky, and it seems to be a problem with pads, where in linking for some reason the elements are trying to link a src pad to another src pad, which not surprisingly does not work. I have tried to link the pads manually, and it does not work. What is strange is that the encoding, and putting into a buffer works a treat with a gst.element_link_many doing the correct thing. Where it is going wrong is on the other side with the appsrc, where it is then setting videorate, and decoding it. When all goes well the image from the camera displays in the wx window, with a bit of a lag, but at least it is working. I have been running this with --gst-debug-level=3 which is how I know about the pads problem. I would love any suggestions anyone has, because my experiments so far are not having any effect, and I fear I am once again missing something very obvious. The code for the script is below. The init has all the wx code, which is very straight forward, and as much as possible I have tried to put the various elements into their own bin, and own functions for building the bins. Thanks in advance for any help. Rohan P.S. This is very experimental, frankenstinian code with bits grafted on from all over the map, so any layout/organization improvements are also appreciated. P.P.S. The problems seem to lie presently in the video_display method. ------------------------------------------------------------------------- #!/usr/bin/env python import wx import pygst pygst.require("0.10") import gst import gobject gobject.threads_init() class WX_Main(wx.App): def OnInit(self): ### WX GUI STUFF window = wx.Frame(None) window.SetTitle("Video-Player") window.SetSize((500, 400)) window.Bind(wx.EVT_CLOSE,self.destroy) vbox = wx.BoxSizer(wx.VERTICAL) hbox = wx.BoxSizer(wx.HORIZONTAL) # self.entry = wx.TextCtrl(window) # hbox.Add(self.entry, 1, wx.ALL|wx.ALIGN_CENTER_VERTICAL, 4) self.vidstart = wx.Button(window,label="Start Video") hbox.Add(self.vidstart, 0, wx.ALL|wx.ALIGN_CENTER_VERTICAL, 4) self.vidstart.Bind(wx.EVT_BUTTON, self.video_toggle) self.soundstart = wx.Button(window, label="Start Sound") hbox.Add(self.soundstart, 0, wx.ALL|wx.ALIGN_CENTER_VERTICAL, 4) self.soundstart.Bind(wx.EVT_BUTTON, self.sound_toggle) self.bothstart = wx.Button(window, label="Start Both") hbox.Add(self.bothstart, 0, wx.ALL|wx.ALIGN_CENTER_VERTICAL, 4) self.bothstart.Bind(wx.EVT_BUTTON, self.both_start) self.bothstop = wx.Button(window, label="Stop Both") hbox.Add(self.bothstop, 0, wx.ALL|wx.ALIGN_CENTER_VERTICAL, 4) self.bothstop.Bind(wx.EVT_BUTTON, self.both_stop) self.quit = wx.Button(window, label="Quit") hbox.Add(self.quit, 0, wx.ALL|wx.ALIGN_CENTER_VERTICAL, 4) self.quit.Bind(wx.EVT_BUTTON, self.exit) vbox.Add(hbox, 0, wx.EXPAND, 0) self.display_window = wx.Panel(window) vbox.Add(self.display_window,1,wx.ALL|wx.EXPAND,4) window.SetSizer(vbox) window.Layout() window.Show() self.SetTopWindow(window) #### GSTREAMER STUFF self.streamheader = None self.requests = [] self.vidplayer = self.buildvidplayer() #-- appsink bus bus = self.vidplayer.get_bus() bus.add_signal_watch() bus.enable_sync_message_emission() bus.connect('message', self.on_message) bus.connect('sync-message::element', self.on_sync_message) #---------------- self.vidout = self.buildvidout() #-- appsrc bus bus2 = self.vidout.get_bus() bus2.add_signal_watch() bus2.enable_sync_message_emission() bus2.connect('message', self.on_message2) bus2.connect('sync-message::element', self.on_sync_message2) self.buffer=[] return True def debug(self, message): print message def buildvidplayer(self): player = gst.Pipeline('vidplayer') camera = gst.element_factory_make("v4l2src", 'camera') vidsrc = gst.element_factory_make("tee") player.add(camera, vidsrc) gst.element_link_many(camera, vidsrc) self.camcaps = camera.get_pad('src').get_caps() print "CAMERA CAPS: ", camera.get_pad('src').get_caps() # streamed video svidbin = self.stream_vidbin() player.add(svidbin) vidsrc.link(svidbin) return player def stream_vidbin(self): bin = gst.Bin("streamvid") # queue ! ffmpegcolorspace ! smokeenc keyframe=8 qmax=40 ! queue = gst.element_factory_make("queue", "queueSINK") colourconv = gst.element_factory_make("ffmpegcolorspace", "ffmpegcspSINK") videorate = gst.element_factory_make("videorate", "videorateSINK") videoscale = gst.element_factory_make("videoscale", "videoscaleSINK") theoraenc = gst.element_factory_make("theoraenc", "theoraencSINK") #create = gst.element_factory_make("oggmux", "ogg-create") out = self.vid_appsink() ## add and link bin.add(queue, colourconv, videorate,videoscale, theoraenc, out) gst.element_link_many(queue, colourconv, videorate,videoscale, theoraenc,out) # GhostPad for bin binsink = gst.GhostPad("binsink", queue.get_pad("sink")) bin.add_pad(binsink) return bin def vid_appsink(self): """ Inspired by https://coherence.beebits.net/svn/trunk/Coherence/coherence/transcoder.py""" out = gst.element_factory_make("appsink", "sink") out.set_property('emit-signals', True) out.connect("new-preroll", self.new_preroll) out.connect("new-buffer", self.new_buffer) out.connect("eos", self.eos) return out def new_preroll(self, appsink): print "prerolling" buffer = appsink.emit('pull-preroll') #print buffer print "BUFFER PREROLL LENGTH: ", len(buffer) self.streamheading(buffer) def new_buffer(self, appsink): print "new buffering" buffer = appsink.emit('pull-buffer') #print buffer print "NEW BUFFER LENGTH: ", len(buffer) self.streamheading(buffer) def streamheading(self, buffer): if not self.streamheader: # check caps for streamheader buffers caps = buffer.get_caps() print "CAPS: ", caps s = caps[0] if s.has_key("streamheader"): self.streamheader = s["streamheader"] self.debug("setting streamheader") for r in self.requests: self.debug("writing streamheader") for h in self.streamheader: r.write(h.data) print type(buffer) self.buffer.append(buffer) def need_image(self, src, length): print "needing image" #if self.buffer: if self.buffer: buffer = self.buffer.pop(0) buffer.set_caps (self.appsrc.get_property ("caps")) # buffer.timestamp = self._frame * 1000*1000*40 buffer.duration = 1000*1000*40 #buffer.surface = self.surface self.appsrc.emit ("push-buffer", buffer) #stream.emit ("end-of-stream") def buildvidout(self): player = gst.Pipeline('vidout') #video source vidsource = gst.element_factory_make("appsrc") vidsource.set_property("caps", gst.Caps(self.camcaps)) #vidsource.set_property ("max-bytes", 10*1024*1024) vidsource.connect ('need-data', self.need_image) player.add(vidsource) # video display vidbin = self.video_display() player.add(vidbin) vidsource.link(vidbin) self.appsrc=vidsource return player def video_display(self): bin = gst.Bin("vidbin") queue = gst.element_factory_make("queue", "queueSRC") videorate = gst.element_factory_make("videorate", "videorateSRC") videoscale = gst.element_factory_make("videoscale", "videoscaleSRC") theoradec = gst.element_factory_make("theoradec", "theoradecSRC") ffmpegcolorspace = gst.element_factory_make("ffmpegcolorspace", "ffmpegcspSRC") vidsink = gst.element_factory_make("ximagesink", "ximagesinkSRC") self.__display_videosink=vidsink bin.add(queue, theoradec,videoscale,videorate, ffmpegcolorspace, vidsink) gst.element_link_many(queue, theoradec) # this is giving a cannot link pads error #theoradec.link_pads('sink', videoscale, 'src') ### ### This is where the problems seem to lie ### # this is sometimes working, and other times giving the # cannot connect src pad to src pad theoradec.link(videoscale) # need to link videoscaleSRC to videorateSRC pads manually videoscale.link(videorate) # need to link videorate and ffmpegcolorspace pads manually videorate.link(ffmpegcolorspace) ffmpegcolorspace.link(vidsink) # ghostpad binsink = gst.GhostPad("binsink", queue.get_pad("sink")) bin.add_pad(binsink) return bin def eos(self, appsink): self.debug("eos") for r in self.requests: r.finish() ###### Mostly wx related stuff, but calling and triggering gstreamer ###### stuff def video_toggle(self, event): self.toggle_media(self.vidstart, self.vidplayer) def both_start(self, event): self.toggle_media(self.vidstart, self.vidplayer, "Start") self.toggle_media(self.soundstart, self.soundplayer, "Start") def both_stop(self, event): self.toggle_media(self.vidstart, self.vidplayer, "Stop") self.toggle_media(self.soundstart, self.soundplayer, "Stop") def on_message(self, bus, message): t = message.type if t == gst.MESSAGE_EOS: self.vidplayer.set_state(gst.STATE_NULL) self.vidstart.SetLabel("Start") elif t == gst.MESSAGE_ERROR: self.vidplayer.set_state(gst.STATE_NULL) self.vidstart.SetLabel("Start") def on_sync_message(self, bus, message): if message.structure is None: return message_name = message.structure.get_name() if message_name == 'prepare-xwindow-id': imagesink = message.src imagesink.set_property('force-aspect-ratio', True) imagesink.set_xwindow_id(self.display_window.GetHandle()) def destroy(self,event): #Stop the player pipeline to prevent a X Window System error self.debug("pipeline cleanup") self.vidplayer.set_state(gst.STATE_NULL) self.requests = [] self.streamheader = None event.Skip() def exit(self, event): self.debug("pipeline cleanup and exitting") # Stop the player pipeline and close the App self.vidplayer.set_state(gst.STATE_NULL) self.requests = [] self.streamheader = None self.Exit() if __name__ == "__main__": app = WX_Main() app.MainLoop() ------------------------------------------------------------------------------ Let Crystal Reports handle the reporting - Free Crystal Reports 2008 30-Day trial. Simplify your report design, integration and deployment - and focus on what you do best, core application coding. Discover what's new with Crystal Reports now. http://p.sf.net/sfu/bobj-july _______________________________________________ gstreamer-devel mailing list [hidden email] https://lists.sourceforge.net/lists/listinfo/gstreamer-devel |
Free forum by Nabble | Edit this page |