参考资料:
gstreamer中如何使用probe(探针)获取帧数据_gstreamer 视频编码时获取视频关键帧信息-CSDN博客
Gstreamer中可以使用AppSink作为一个分支来查看管线中的数据,还可以使用probe去处理。
在GStreamer中,probe
是一种强大的机制,用于在管道(pipeline)的不同点上检查、修改或拦截数据流。当数据流经管道中的元素时,probe允许开发者在特定的pad(输入或输出端口)上设置监听器,从而可以捕获或处理正在通过的数据。
GStreamer提供了几种不同类型的probe:
-
Buffer Probe (
GST_PAD_PROBE_TYPE_BUFFER
): 这是最常见的类型,它会在缓冲区(buffer)到达指定pad时被触发。缓冲区通常包含了一帧音频或视频数据。 -
Event Probe (
GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM
或GST_PAD_PROBE_TYPE_EVENT_UPSTREAM
): 这种probe会在事件(event)通过pad时触发。事件可以是各种各样的信号,如标记(mark)、缓冲区开始(buffer start)或结束(buffer end)等。 -
Block Probe (
GST_PAD_PROBE_TYPE_BLOCK_DOWNSTREAM
或GST_PAD_PROBE_TYPE_BLOCK_UPSTREAM
): 这种probe可以阻止数据流,直到回调函数返回一个非阻塞的状态。 -
Latency Probe (
GST_PAD_PROBE_TYPE_LATENCY
): 这种probe用于测量数据从进入管道到离开管道所花费的时间。 -
Buffer List Probe (
GST_PAD_PROBE_TYPE_BUFFER_LIST
): 类似于Buffer Probe,但可以处理多个连续的缓冲区。
为了在GStreamer中添加probe,你需要调用gst_pad_add_probe()
函数,传入你想要监控的pad以及一个回调函数,当probe被触发时将执行此回调。回调函数的原型通常如下:
C
深色版本
1gboolean probe_callback (GstPad *pad,
2 GstPadProbeInfo *info,
3 gpointer user_data);
在回调函数中,你可以访问和操作GstPadProbeInfo
结构,这包含了触发probe的数据(如缓冲区或事件)。你可以选择是否让数据继续通过管道,或者修改数据并让它通过,甚至完全阻止数据。
例如,一个简单的Buffer Probe回调函数可能如下所示:
C
深色版本
1static GstPadProbeReturn
2cb_have_data (GstPad *pad,
3 GstPadProbeInfo *info,
4 gpointer data)
5{
6 GstBuffer *buf;
7
8 /* Cast the info to a buffer probe info */
9 buf = GST_PAD_PROBE_INFO_BUFFER (info);
10
11 /* Do something with the buffer here... */
12
13 /* Let the buffer pass through */
14 return GST_PAD_PROBE_OK;
15}
通过使用probe,开发者可以在不打断数据流的情况下进行调试、性能分析或实时数据处理,这在开发复杂的流媒体应用程序时非常有用。
一个例子
添加probe
//date probe
GstPad* pad = gst_element_get_static_pad(videosink, "sink");
gst_pad_add_probe(pad, GST_PAD_PROBE_TYPE_BUFFER,
(GstPadProbeCallback)cb_have_data, NULL, NULL);
gst_object_unref(pad);
回调方法
static GstPadProbeReturn
cb_have_data(GstPad* pad,
GstPadProbeInfo* info,
gpointer user_data) {
GstBuffer* buffer = NULL;
GstMapInfo map_info;
GstStructure* s;
gint width, height; //图片的尺寸
GstCaps* sink_caps = gst_pad_get_current_caps(pad);
s = gst_caps_get_structure(sink_caps, 0);
gboolean res;
res = gst_structure_get_int(s, "width", &width); //获取图片的宽
res |= gst_structure_get_int(s, "height", &height); //获取图片的高
if (!res) {
g_print("gst_structure_get_int fail\n");
return GST_PAD_PROBE_DROP;
}
g_print("width=%d, height=%d \n", width, height);
return GST_PAD_PROBE_OK;
}
完整例子
static GstPadProbeReturn
cb_have_data(GstPad* pad,GstPadProbeInfo* info,gpointer user_data) {GstBuffer* buffer = NULL;GstMapInfo map_info;GstStructure* s;gint width, height; //图片的尺寸GstCaps* sink_caps = gst_pad_get_current_caps(pad);s = gst_caps_get_structure(sink_caps, 0);gboolean res;res = gst_structure_get_int(s, "width", &width); //获取图片的宽res |= gst_structure_get_int(s, "height", &height); //获取图片的高if (!res) {g_print("gst_structure_get_int fail\n");return GST_PAD_PROBE_DROP;}g_print("width=%d, height=%d \n", width, height);return GST_PAD_PROBE_OK;
}
从打印结果中,可以看到,回调方法被调用了