Gstreamer Appsink 未从管道获取数据

Posted

技术标签:

【中文标题】Gstreamer Appsink 未从管道获取数据【英文标题】:Gstreamer Appsink not getting Data from the Pipeline 【发布时间】:2015-11-26 21:32:20 【问题描述】:

我正在设计一个管道,将来自 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 部分存在一些问题。

此管道的应用程序部分已设置为以下上限:

"video/x-h264, format=(string)avc,avc3,byte-stream ,alignment=(string)au,nal;video/mpeg, mpegversion=(int)2, profile=(string)simple"

我的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上限是否正确?如果不是,我如何确定他们的上限? 2)我上面的管道有问题吗?

如何使用 Appsink 解决此问题?

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

谢谢!!

【问题讨论】:

所以你甚至不能使用 udpsrc?一定是appsrc? 是的,因为我正在从 Opencv 应用程序获取输入... 【参考方案1】:

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

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

您可以对appsrc 信号enough-dataneed-data 做出反应——这是我们的方式。我们还修改了 appsrc 的属性:is-livedo-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-dataneed-data 信号上添加回调,或者您可以添加队列和启用 GST_DEBUG=queue_dataflow:5 以查看首先填充哪个队列等。这在调试“数据死锁”时总是很有帮助。

【讨论】:

如何在我的代码中添加特定于我的 appsrc 的调试?我一直在网上搜索以执行此操作,但是,没有运气......你能帮我吗?? 非常感谢!那行得通...我的管道存在同步问题...在下一个appsrc中进行了更改并且一切正常! :)

以上是关于Gstreamer Appsink 未从管道获取数据的主要内容,如果未能解决你的问题,请参考以下文章

gstreamer中tee如何实现动态增减支路(预览+截图+录像)

如何结合gstreamer和opencv?

将管道设置为播放状态后,Gstreamer 回调未命中

管道stdout到gstreamer

在 EOS 上用 Python 重启 GStreamer 管道

从 python 中的 opencv 写入 Gstreamer 管道