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-data
和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
和 need-data
信号上添加回调,或者您可以添加队列和启用 GST_DEBUG=queue_dataflow:5 以查看首先填充哪个队列等。这在调试“数据死锁”时总是很有帮助。
【讨论】:
如何在我的代码中添加特定于我的 appsrc 的调试?我一直在网上搜索以执行此操作,但是,没有运气......你能帮我吗?? 非常感谢!那行得通...我的管道存在同步问题...在下一个appsrc中进行了更改并且一切正常! :)以上是关于Gstreamer Appsink 未从管道获取数据的主要内容,如果未能解决你的问题,请参考以下文章
gstreamer中tee如何实现动态增减支路(预览+截图+录像)