參考資料:
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;
}
從打印結果中,可以看到,回調方法被調用了