gstreamer使用hook的简单示例
测试代码功能:
生成RTP流:gst-launch-1.0 -v filesrc location=1080.mp4 ! qtdemux name=demux demux.video_0 ! queue ! h264parse ! rtph264pay config-interval=1 pt=96 ! udpsink host=127.0.0.1 port=8000
显示这个RTP流:gst-launch-1.0 -v udpsrc port=8000 ! capsfilter caps="application/x-rtp, media=(string)video, clock-rate=(int)90000, encoding-name=(string)H264, packetization-mode=(string)1" ! queue ! rtph264depay ! h264parse ! avdec_h264 ! autovideoconvert ! glimagesink sync=false
将显示管道,写成代码,并增加hook,用于打印图片大小信息:
#include <gst/gst.h>
#include <gst/video/video.h>static GstPadProbeReturn
on_decoded_frame(GstPad *pad, GstPadProbeInfo *info, gpointer user_data) {GstBuffer *buffer = GST_PAD_PROBE_INFO_BUFFER(info);if (!buffer)return GST_PAD_PROBE_OK;// 增加引用,防止buffer被释放buffer = gst_buffer_ref(buffer);// 获取buffer中的视频帧信息GstCaps *caps = gst_pad_get_current_caps(pad);if (!caps) {g_print("No caps on pad\n");gst_buffer_unref(buffer);return GST_PAD_PROBE_OK;}GstStructure *s = gst_caps_get_structure(caps, 0);int width = 0, height = 0;if (!gst_structure_get_int(s, "width", &width) ||!gst_structure_get_int(s, "height", &height)) {g_print("Failed to get width/height from caps\n");}// 打印buffer大小和图片尺寸g_print("Decoded frame: size=%zu bytes, width=%d, height=%d\n",gst_buffer_get_size(buffer), width, height);gst_caps_unref(caps);gst_buffer_unref(buffer);return GST_PAD_PROBE_OK;
}int main(int argc, char *argv[]) {gst_init(&argc, &argv);GstElement *pipeline, *udpsrc, *capsfilter, *queue, *depay, *parser, *decoder, *conv, *sink;GstPad *decoder_src_pad;pipeline = gst_pipeline_new("rtp-h264-pipeline");udpsrc = gst_element_factory_make("udpsrc", "udp-source");capsfilter = gst_element_factory_make("capsfilter", "capsfilter");queue = gst_element_factory_make("queue", "queue");depay = gst_element_factory_make("rtph264depay", "depay");parser = gst_element_factory_make("h264parse", "parser");decoder = gst_element_factory_make("avdec_h264", "decoder");conv = gst_element_factory_make("autovideoconvert", "converter");sink = gst_element_factory_make("glimagesink", "video-output");if (!pipeline || !udpsrc || !capsfilter || !queue || !depay || !parser || !decoder || !conv || !sink) {g_printerr("Failed to create elements\n");return -1;}// 设置udpsrc监听端口g_object_set(udpsrc, "port", 8000, NULL);// 设置capsfilter的capsGstCaps *caps = gst_caps_from_string("application/x-rtp, media=video, clock-rate=90000, encoding-name=H264, packetization-mode=1");g_object_set(capsfilter, "caps", caps, NULL);gst_caps_unref(caps);// 设置sink属性 sync=falseg_object_set(sink, "sync", FALSE, NULL);// 添加元素到管道gst_bin_add_many(GST_BIN(pipeline), udpsrc, capsfilter, queue, depay, parser, decoder, conv, sink, NULL);// 连接元素if (!gst_element_link_many(udpsrc, capsfilter, queue, depay, parser, decoder, conv, sink, NULL)) {g_printerr("Failed to link elements\n");gst_object_unref(pipeline);return -1;}// 在decoder的src pad上添加probe hook,获取解码后帧decoder_src_pad = gst_element_get_static_pad(decoder, "src");gst_pad_add_probe(decoder_src_pad, GST_PAD_PROBE_TYPE_BUFFER, on_decoded_frame, NULL, NULL);gst_object_unref(decoder_src_pad);// 运行管道gst_element_set_state(pipeline, GST_STATE_PLAYING);// 进入主循环GMainLoop *loop = g_main_loop_new(NULL, FALSE);g_main_loop_run(loop);// 清理gst_element_set_state(pipeline, GST_STATE_NULL);gst_object_unref(pipeline);g_main_loop_unref(loop);return 0;
}