Gstreamer Appsink 未从管道获取数据

2024-03-18

我正在设计一个管道,将来自 opencv 应用程序(从网络摄像头获取)的视频帧编码为 video/x-h264 格式,通过网络发送并在另一台不同类型的设备(可能是树莓派)上将其解码到适合我的项目的 RGB 流。

为此,我应该使用硬件加速编码器和解码器。 由于整个场景非常庞大,当前的开发是在 Intel 机器上使用 gstreamer VAAPI 插件(vaapiencode_h264 和 vaapidecode)进行的。而且,我们不需要使用任何网络插件,如 TCPServer 或 UDPServer

为此,我使用了以下管道来达到我的目的: 在编码器端:

appsrc name=applicationSource ! videoconvert ! video/x-raw, format=I420, width=640, height=480,framerate=30/1, pixel-aspect-ratio=1/1,interlace-mode=progressive ! vaapiencode_h264 bitrate=600 tune=high-compression ! h264parse config-interval=1 ! appsink name=applicationSink sync=false

Appsrc 部分工作得很好,而 appsink 部分则有一些问题。

该管道的 appsink 部分已设置以下上限:

“视频/x-h264,格式=(字符串){avc,avc3,字节流},对齐=(字符串){au,nal};视频/mpeg,mpeg版本=(int)2,配置文件=(字符串)简单”

我的appsink的数据提取代码是

    bool HWEncoder::grabData()
{

    // initial checks..

    if (!cameraPipeline)
    {

        GST_ERROR("ERROR AS TO NO PIPE FOUND ... Stopping FRAME GRAB HERE !! ");
        return false;
    }


    if (gst_app_sink_is_eos (GST_APP_SINK(applicationSink)))
    {

        GST_WARNING("APP SINK GAVE US AN EOS! BAILING OUT ");
        return false;
    }

    if (sample)
    {
        cout << "sample available ... unrefing it ! "<< endl;
        gst_sample_unref(sample);
    }


    sample = gst_app_sink_pull_sample (GST_APP_SINK(applicationSink));

    if (!sample)
    {
        GST_WARNING("No valid sample");
        return false; // no valid sample pulled !
    }

    sink_buffer = gst_sample_get_buffer(sample);

    if (!sink_buffer)
    {
        GST_ERROR("No Valid Buffer ");return false;
    }

    return true;
}

打开管道并检查应用程序接收器中的缓冲区填充后,我无限期地陷入了下面所说的代码行:

sample = gst_app_sink_pull_sample (GST_APP_SINK(applicationSink));

我有以下问题: 1)我的appsink Caps正确吗?如果不是,我如何确定它们的上限? 2)我上面的管道有问题吗?

如何使用 Appsink 解决此问题?

任何形式的帮助都会很有用!

谢谢 !!


只是猜测(我遇到了类似的问题)appsink 和 appsrc 在同一管道中的问题可能是,当您填充/清空其中一个时,它会阻塞另一个(更多内容见下文)。

appsink 和 appsrc 在满/空时会阻塞 - 这是正常的期望行为。有选项drop对于 appsink 或 appsrc 有选项block- 但使用这些可能只是解决方法,您的流中会出现故障。正确的解决方案是以更好的方式处理 appsrc 和 appsink 之间的同步。

您可以对 appsrc 信号做出反应enough-data and need-data- 这是我们的方式。我们还摆弄了 appsrc 的属性:is-live, do-timestamp和缓冲区大小(这可能对您有帮助,也可能没有帮助):

g_object_set(src->appsrc,
    "stream-type", GST_APP_STREAM_TYPE_STREAM,
    "format", GST_FORMAT_TIME,
    "do-timestamp", TRUE,
    "is-live", TRUE,
    "block", TRUE,
    NULL);

他们为什么要互相阻止? 因为(我猜)您在主应用程序线程中处理 appsink 并同时处理 appsrc 。当 appsink/appsrc 之一阻塞线程时,没有人可以处理另一个线程的处理。因此,当 appsink 因为没有任何数据而被阻塞时,没有人可以为 appsrc 提供新数据 - 因此陷入无尽的死锁。

我们还实现了 appsink *pull_sample 方法的 noblock 版本,但这只是一种解决方法,导致的问题多于解决方案。

如果你想调试正在发生的事情,你可以为 appsrc/appsink 添加 GST_DEBUG 条目(我不记得它们是什么),你可以添加提到的回调enough-data and need-data信号或者您可以添加队列并启用 GST_DEBUG=queue_dataflow:5 以查看哪个队列首先被填充等等。这在调试“数据死锁”时总是有帮助的。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Gstreamer Appsink 未从管道获取数据 的相关文章

随机推荐