Gstreamer 1.0 - 创建自定义消息/事件/信号

Posted

技术标签:

【中文标题】Gstreamer 1.0 - 创建自定义消息/事件/信号【英文标题】:Gstreamer 1.0 - Creating custom message/event/signal 【发布时间】:2017-12-12 16:30:55 【问题描述】:

我正在用 C 语言为 gstreamer 1.0 编写一个自定义插件。 该插件对帧执行一些处理,并应在满足某些条件时向应用程序发送事件。 它不应该阻塞管道不干扰它,只是一个信号,以便应用程序可以触发与管道无关的操作。

处理运行良好,但...我不知道下一步该做什么。 有很多已经存在的消息,例如 EOS 或 seek 但我如何创建自己的消息? 该消息应包含自定义数据,因此我必须自己创建一个可以发送的消息。

通过发送事件或信号,我找不到任何关于如何处理来自插件的自定义事件的示例/文档/说明。

我什至没有示例代码可以开始。

任何见解都将不胜感激。

【问题讨论】:

【参考方案1】:

看看fpsdisplaysink元素:

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

这个会发出应用程序可以连接的信号。最有趣的可能是信号创建:

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);

以及所述信号的周期性触发:

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

详细信息应在 GLib 信号文档中找到:

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

#

或者,您也可以创建自己的GstMessage 并将其发布到公共汽车上。请参阅 GstMessage 文档:

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

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

然后您可以将您的数据包装在GstStructure 中。然后用gst_bus_post()将消息发布到总线上。

【讨论】:

非常感谢您的回答。我开始使用自己的 GstStructure 和 gst_bus_post 创建自己的 GstMessage。它有效,但我不知道每次触发时如何从应用程序本身获取回调。 gst_bus_add_watch 是正确的方式吗? 我也查看了 gst_bus_pop_filtered 但它应该在我的事件的某种 runLoop 中,如果收到错误或 EOS 事件则停止程序。是否有某个地方的 runLoop 捕获应用程序事件的示例?我的主要应用程序是在 python 中,我找到了gstreamer.freedesktop.org/documentation/application-development/…,但我真的不知道如何在 python 中翻译它。 一般有三种方式。 1) 你有一个运行的 GMainLoop,你可以通过 gst_bus_add_watch() 添加一个总线监视。 2) 您通过 gst_bus_poll() 定期轮询应用程序中的总线。 3) 您通过 gst_bus_set_sync_handler() 设置同步处理程序。无论您采用哪种方式 - 您绝对应该拥有它,因为管道运行时的所有错误/eos/etc 报告都结束了。抱歉,我不会说 python。【参考方案2】:

感谢弗洛里安的洞察力,这对我帮助很大。 我最终使用了 gst_message_new 和 gst_post_bus。

对于那些可能对这里感兴趣的人,我在 python 中实现了一个运行循环的代码。

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)

【讨论】:

以上是关于Gstreamer 1.0 - 创建自定义消息/事件/信号的主要内容,如果未能解决你的问题,请参考以下文章

GStreamer 1.0 在 C 中将原始编码为 H.264

sh GStreamer-1.0个人备忘单

sh GStreamer-1.0个人备忘单

如何自定义xml文件

GStreamer基础教程12 - 常用命令工具

gstreamer开发之--- gst-inspect-1.0