sending data from one pipeline to another via appsink and appsrc

Brian Quandt brian.quandt at gmail.com
Sun Aug 5 23:50:21 PDT 2012


I'm getting the following error:
(s11.py:12310): GStreamer-CRITICAL **: gst_segment_set_newsegment_full:
assertion `segment->format == format' failed

When I try to use input-select to choose an appsrc which has it's data
coming from another pipeline.  I think this is a caps issue, but I can't
seem to locate it.  I'm pushing data directly from the appsink to the
appsrc (intention is to allow the sink to dynamically die or change rather
then having appsrc pull from the appsink).   I do know data is moving
between the two, as if I set the starting input-selector to be this src, it
plays fine, it just dies with the above error is I switch between the two
bins.

Maybe I'm just missing some caps, which I don't know I need to set as
well   (what others are there for video beyond what I've included?)


Here's the src (it's just a modified switch.py script) :


#!/usr/bin/env python
# -*- Mode: Python -*-
# vi:si:et:sw=4:sts=4:ts=4

import pygtk
pygtk.require('2.0')

import sys

import gobject
gobject.threads_init()

import pygst
pygst.require('0.10')
import gst
import gst.interfaces
import gtk
gtk.gdk.threads_init()

class SwitchTest:
    def __init__(self, videowidget):
        self.buffers = []
        self.playing = False


        caps =
gst.Caps("video/x-raw-yuv,framerate=30/1,pixel-aspect-ratio=1/1,width=320,height=240,color-matrix=sdtv,chroma-site=jpeg,format=(fourcc)YUY2")

        self.pipeline2 = gst.Pipeline("pipeline2")

        uri2 = gst.element_factory_make("videotestsrc","uri2")
        filter2 = gst.element_factory_make("capsfilter","filter2")
        filter2.set_property("caps",caps)
        sink = gst.element_factory_make("appsink","sink")
        sink.set_property("caps",caps)
        sink.set_property('emit-signals', True)
        sink.set_property('sync', False)


        self.pipeline2.add(uri2,filter2,sink)
        gst.element_link_many(uri2,filter2,sink)


        #Now set up the master pipeline
        pipestr = ('videotestsrc name=uri !  s.sink0'
                   ' appsrc  name=source
caps=video/x-raw-yuv,framerate=30/1,pixel-aspect-ratio=1/1,width=320,height=240,color-matrix=sdtv,chroma-site=jpeg,format=\(fourcc\)YUY2
!  ffmpegcolorspace ! s.sink1'
                   ' videotestsrc name=blah ! s.sink2'
                   ' input-selector sync-streams=true name=s !
autovideosink name=blah2
filter-sink-caps=video/x-raw-yuv,format=\(fourcc\)YUY2 ')
        self.pipeline = gst.parse_launch(pipestr)
        self.videowidget = videowidget

        source = self.pipeline.get_by_name("source")
        #Not going to pull buffer, instead pushing them
        #directly from the sink in pipeline2
        #source.connect('need-data', self.source_pull_buffer)
        #source.connect('push-buffer', self.source_pull_buffer)
        self.source = source

        # attach some of the call backs now that both pipelines are up
        sink.connect('new-preroll', self.sink_new_preroll, self.pipeline)
        sink.connect('new-buffer', self.sink_new_buffer, self.pipeline)
        sink.connect('eos', self.eos)

        bus = self.pipeline.get_bus()
        bus.enable_sync_message_emission()
        bus.add_signal_watch()
        bus.connect('sync-message::element', self.on_sync_message)
        bus.connect('message', self.on_message)

        self.pipeline2.set_state(gst.STATE_PLAYING)

    def on_sync_message(self, bus, message):
        if message.structure is None:
            return
        if message.structure.get_name() == 'prepare-xwindow-id':
            # Sync with the X server before giving the X-id to the sink
            gtk.gdk.threads_enter()
            gtk.gdk.display_get_default().sync()
            self.videowidget.set_sink(message.src)
            message.src.set_property('force-aspect-ratio', True)
            gtk.gdk.threads_leave()

    def on_message(self, bus, message):
        t = message.type
        if t == gst.MESSAGE_ERROR:
            err, debug = message.parse_error()
            print "Error: %s" % err, debug
            if self.on_eos:
                self.on_eos()
            self.playing = False
        elif t == gst.MESSAGE_EOS:
            if self.on_eos:
                self.on_eos()
            self.playing = False

    def play(self):
        self.playing = True
        gst.info("playing player")
        self.pipeline.set_state(gst.STATE_PLAYING)

    def stop(self):
        self.pipeline.set_state(gst.STATE_NULL)
        gst.info("stopped player")
        self.playing = False

    def get_state(self, timeout=1):
        return self.pipeline.get_state(timeout=timeout)

    def is_playing(self):
        return self.playing

    def switch(self, padname):
        switch = self.pipeline.get_by_name('s')
        stop_time = switch.emit('block')
        newpad = switch.get_static_pad(padname)
        start_time = newpad.get_property('running-time')

        gst.warning('stop time = %d' % (stop_time,))
        gst.warning('stop time = %s' % (gst.TIME_ARGS(stop_time),))

        gst.warning('start time = %d' % (start_time,))
        gst.warning('start time = %s' % (gst.TIME_ARGS(start_time),))

        gst.warning('switching from %r to %r'
                    % (switch.get_property('active-pad'), padname))
        switch.emit('switch', newpad, stop_time, start_time)

    def sink_new_preroll(self, sink, pipe):
         #print "Prerolling sink"
         buf = sink.emit('pull-preroll')
         #self.buffers.append(buf)
         #print "PREROLL BUFFERS: ", len(self.buffers)
         mysrc = pipe.get_by_name("source")
         mysrc.emit('push-buffer', buf)
         return True

    def sink_new_buffer(self, sink, pipe):
         #print "new buffer from sink"
         buf = sink.emit('pull-buffer')
         #self.buffers.append(buf)
         #print "NEW BUFFER BUFFERS: ", len(self.buffers)
         #test of directly emitting the buffer
         mysrc = pipe.get_by_name("source")
         mysrc.emit('push-buffer', buf)
         return True

    def eos(self, sink):
         return True

    def source_pull_buffer(self, source, length):
         print "PULLING BUFER"
         if self.buffers:
             buf = self.buffers.pop(0)
             source.emit('push-buffer', buf)
         return True

    def pull_next_buffer(self):
         print "PULLING NEXT BUFER"
         self.source.emit('push-buffer', self.buffers.pop(0))
         return True


class VideoWidget(gtk.DrawingArea):
    def __init__(self):
        gtk.DrawingArea.__init__(self)
        self.imagesink = None
        self.unset_flags(gtk.DOUBLE_BUFFERED)

    def do_expose_event(self, event):
        if self.imagesink:
            self.imagesink.expose()
            return False
        else:
            return True

    def set_sink(self, sink):
        assert self.window.xid
        self.imagesink = sink
        self.imagesink.set_xwindow_id(self.window.xid)

class SwitchWindow(gtk.Window):
    UPDATE_INTERVAL = 500
    def __init__(self):
        gtk.Window.__init__(self)
        self.set_default_size(410, 325)

        self.create_ui()
        self.player = SwitchTest(self.videowidget)
        self.populate_combobox()

        self.update_id = -1
        self.changed_id = -1
        self.seek_timeout_id = -1

        self.p_position = gst.CLOCK_TIME_NONE
        self.p_duration = gst.CLOCK_TIME_NONE

        def on_delete_event():
            self.player.stop()
            gtk.main_quit()
        self.connect('delete-event', lambda *x: on_delete_event())

    def load_file(self, location):
        self.player.set_location(location)

    def play(self):
        self.player.play()

    def populate_combobox(self):
        switch = self.player.pipeline.get_by_name('s')
        for i, pad in enumerate([p for p in switch.pads()
                                 if p.get_direction() == gst.PAD_SINK]):
            self.combobox.append_text(pad.get_name())
            if switch.get_property('active-pad') == pad.get_name():
                self.combobox.set_active(i)
        if self.combobox.get_active() == -1:
            self.combobox.set_active(0)

    def combobox_changed(self):
        model = self.combobox.get_model()
        row = model[self.combobox.get_active()]
        padname, = row
        self.player.switch(padname)

    def enter_callback(self, widget, entry):

        entry_text = entry.get_text()
        print "Entry contents: %s\n" % entry_text

    def create_ui(self):
        vbox = gtk.VBox()
        self.add(vbox)

        self.videowidget = VideoWidget()
        vbox.pack_start(self.videowidget)

        hbox = gtk.HBox()
        vbox.pack_start(hbox, fill=False, expand=False)

        self.combobox = combobox = gtk.combo_box_new_text()
        combobox.show()
        hbox.pack_start(combobox)

        self.combobox.connect('changed',
                              lambda *x: self.combobox_changed())

        self.videowidget.connect_after('realize',
                                       lambda *x: self.play())
        entry = gtk.Entry()
        entry.set_max_length(50)
        entry.connect("activate", self.enter_callback, entry)
        entry.set_text("hello")
        entry.insert_text(" world", len(entry.get_text()))
        entry.select_region(0, len(entry.get_text()))
        hbox.pack_start(entry)
        entry.show()

def main(args):
    def usage():
        sys.stderr.write("usage: %s\n" % args[0])
        return 1

    # Need to register our derived widget types for implicit event
    # handlers to get called.
    gobject.type_register(SwitchWindow)
    gobject.type_register(VideoWidget)

    if len(args) != 1:
        return usage()

    w = SwitchWindow()
    w.show_all()
    gtk.main()
    return 0

if __name__ == '__main__':
    sys.exit(main(sys.argv))
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.freedesktop.org/archives/gstreamer-devel/attachments/20120805/c17f69a2/attachment-0001.html>


More information about the gstreamer-devel mailing list