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

为此,我应该使用硬件加速的编码器和解码器。
由于整个方案非常庞大,因此当前的开发是使用gstreamer VAAPI插件(vaapiencode_h264和vaapidecode)在Intel机器上进行的。还有一个事实,我们不需要使用任何网络插件,例如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

当appsink部分出现问题时,Appsrc部分可以很好地工作。

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

“video / x-h264,format =(string){avc,avc3,byte-stream},alignment =(string){au,nal}; video / mpeg,mpegversion =(int)2,profile =(string)简单”

我的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;
}

在启动管道并检查是否在我的appsink中填满了缓冲区之后,我被无限期地困在下面所说的代码行中:
sample = gst_app_sink_pull_sample (GST_APP_SINK(applicationSink));

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

如何使用Appsink解决此问题?

任何帮助都是有用的!

谢谢 !!

最佳答案

只是一个猜测(我有类似的问题),在同一管道中包含appsink和appsrc的问题可能是,当您填充/清空其中一个时,它将阻塞另一个(在下面进行更多介绍)。

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

您可以对appsrc信号enough-dataneed-data使用react-这是我们的方法。另外,我们还摆弄了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。当一个appink / appsrc阻塞线程时,没有人可以处理另一个线程的处理。因此,当appsink因为没有任何数据而被阻止时,没有人可以使用新数据来向appsrc馈送-因此死锁无穷。

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

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

关于c++ - Gstreamer Appsink无法从管道获取数据,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/33947284/

10-09 04:59