god_kane
god_kane

Reputation: 204

Gstreamer 1.0 - Creating custom message/event/signal

I am writing a custom plugin for gstreamer 1.0 in C.
This plugin perform some processing on frames and should send an event to the application whenever some conditions are met. It should not block the pipeline not interfere with it, just a signal so the application can trigger an action unrelated to the pipeline on the side.

The processing is working well but ... i don't know what to do next. There is a lot of already existing message like EOS or seek but how do i create my own? The message should contain custom data and therefore i must create one myself that i could send.

Either by sending events or signal i could not find any examples/documentations/explainations on how to handle custom events from a plugin.

I don't even have a sample code to start with.

Any insight would be appreciated.

Upvotes: 2

Views: 4934

Answers (2)

god_kane
god_kane

Reputation: 204

Thank you Florian for your insight which helped me a lot.
I ended up using gst_message_new and gst_post_bus.

For those who might be interested here is the code in python where i implemented a run loop.

def connect(bus, name):
    def _connect(f):
        bus.connect(name, f)
        return f
    return _connect

....
    bus = self.pipeline.get_bus()
    bus.add_signal_watch()

    ret = self.pipeline.set_state(Gst.State.PLAYING)
    if ret == Gst.StateChangeReturn.FAILURE:
        logger.error("ERROR: Unable to set the pipeline to the playing state")

    loop = GObject.MainLoop()

    print()

    @connect(bus, "message::"+Gst.MessageType.get_name(Gst.MessageType.ERROR))
    def on_error(bus, message):
        err, dbg = message.parse_error()
        print("ERROR:", message.src.get_name().encode('utf-8'), ":", err.message.encode('utf-8'))
        if dbg:
            print("debugging info:", dbg)

        loop.quit()

    @connect(bus, "message::"+Gst.MessageType.get_name(Gst.MessageType.EOS))
    def on_eos(bus, message):
        logger.info("End-Of-Stream reached")
        loop.quit()

    .... other events

    try:
        loop.run()
    except KeyboardInterrupt:
        pass

    print("START : Pipeline has stopped")
    self.pipeline.set_state(Gst.State.NULL)

Upvotes: 0

Florian Zwoch
Florian Zwoch

Reputation: 7383

Take a look at the fpsdisplaysink element:

https://github.com/GStreamer/gst-plugins-bad/blob/master/gst/debugutils/fpsdisplaysink.c

This one emits signals which the application can connect to. Most interesting probably the signal creation:

g_signal_new ("fps-measurements", G_TYPE_FROM_CLASS (klass),
      G_SIGNAL_RUN_LAST, 0, NULL, NULL, NULL,
      G_TYPE_NONE, 3, G_TYPE_DOUBLE, G_TYPE_DOUBLE, G_TYPE_DOUBLE);

and the periodically triggering of said signal:

g_signal_emit (G_OBJECT (self),
        fpsdisplaysink_signals[SIGNAL_FPS_MEASUREMENTS], 0, rr, dr,
        average_fps);

Detailed information should be found at the GLib signals documentation:

https://developer.gnome.org/gobject/stable/gobject-Signals.html

#

Alternatively you create your own GstMessage and post it on the bus. See the GstMessage documentation:

https://gstreamer.freedesktop.org/data/doc/gstreamer/head/gstreamer/html/GstMessage.html

GstMessage *gst_message_new_application (GstObject *src,
    GstStructure *structure);

You can then wrap your data inside the GstStructure. And then post the message to the bus with gst_bus_post().

Upvotes: 3

Related Questions