Gstreamer Appsink 没有从管道获取数据
Gstreamer Appsink not getting Data from the Pipeline
我正在设计一个管道,将来自 opencv 应用程序(从网络摄像头获取)的视频帧编码为 video/x-h264 格式,通过网络发送并在另一台不同类型的设备(可能是raspberry pi ) 到适合我的项目的 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
Appsrc 部分运行良好,而 appsink 部分出现一些问题。
此管道的 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;
}
启动管道并检查我的 appsink 中是否已填满缓冲区后,我无限期地卡在下面所说的代码行中:
sample = gst_app_sink_pull_sample (GST_APP_SINK(applicationSink));
我有以下问题:
1) 我的 appsink 上限是否正确?如果不是,我如何确定它们的上限?
2)我上面的管道有问题吗?
如何解决 Appsink 的这个问题??
任何形式的帮助都是有用的!
谢谢!!
只是一个猜测(我有类似的问题)appsink 和 appsrc 在同一个管道中的问题可能是当你 fill/empty 其中一个时它会阻塞另一个(下面有更多内容)。
appsink 和 appsrc 在 full/empty 时会阻塞 - 这是正常的预期行为。对于 appsink 或 appsrc 有选项 drop
,有选项 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 以查看首先填充哪个队列等。这在调试 "data-deadlock" 时总是很有帮助。
我正在设计一个管道,将来自 opencv 应用程序(从网络摄像头获取)的视频帧编码为 video/x-h264 格式,通过网络发送并在另一台不同类型的设备(可能是raspberry pi ) 到适合我的项目的 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
Appsrc 部分运行良好,而 appsink 部分出现一些问题。
此管道的 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;
}
启动管道并检查我的 appsink 中是否已填满缓冲区后,我无限期地卡在下面所说的代码行中:
sample = gst_app_sink_pull_sample (GST_APP_SINK(applicationSink));
我有以下问题: 1) 我的 appsink 上限是否正确?如果不是,我如何确定它们的上限? 2)我上面的管道有问题吗?
如何解决 Appsink 的这个问题??
任何形式的帮助都是有用的!
谢谢!!
只是一个猜测(我有类似的问题)appsink 和 appsrc 在同一个管道中的问题可能是当你 fill/empty 其中一个时它会阻塞另一个(下面有更多内容)。
appsink 和 appsrc 在 full/empty 时会阻塞 - 这是正常的预期行为。对于 appsink 或 appsrc 有选项 drop
,有选项 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 以查看首先填充哪个队列等。这在调试 "data-deadlock" 时总是很有帮助。