GStreamer中Pad(连接点)

Pad 是 GStreamer 中元素之间数据流动的连接点,理解 Pad 的工作原理对于构建复杂管道至关重要。以下是 Pad 的全面解析:

1. Pad 基本概念

1.1 Pad 的类型

类型 方向 说明
Src Pad 输出 (→) 元素的数据出口
Sink Pad 输入 (←) 元素的数据入口
Always Pad 固定 元素创建时即存在
Sometimes Pad 动态 运行时才创建(如 demuxer 的流输出)
Request Pad 按需 需显式请求创建(如 tee 的分支)

1.2 Pad 的能力(Capabilities)

Pad 通过 Caps (Capabilities) 描述支持的数据格式:

bash

复制代码
# 示例 Caps 描述
video/x-raw, format=RGB, width=640, height=480, framerate=30/1
audio/x-raw, format=S16LE, rate=44100, channels=2

2. Pad 操作实战

2.1 获取 Pad 的三种方式

(1) 静态获取
复制代码
// 获取元素的静态Pad
GstPad *sink_pad = gst_element_get_static_pad(decoder, "sink");
(2) 动态Pad连接(信号方式)
复制代码
// 处理demuxer的动态Pad
static void on_pad_added(GstElement *src, GstPad *new_pad, gpointer user_data) {
    GstPadLinkReturn ret;
    GstPad *sink_pad = gst_element_get_static_pad(decoder, "sink");
    
    // 检查Pad兼容性
    GstCaps *new_pad_caps = gst_pad_get_current_caps(new_pad);
    GstStructure *new_pad_struct = gst_caps_get_structure(new_pad_caps, 0);
    const gchar *new_pad_type = gst_structure_get_name(new_pad_struct);
    
    if (g_str_has_prefix(new_pad_type, "video/x-h264")) {
        ret = gst_pad_link(new_pad, sink_pad);
        if (GST_PAD_LINK_FAILED(ret)) {
            g_print("Pad链接失败\n");
        }
    }
    gst_object_unref(sink_pad);
}

// 连接信号
g_signal_connect(demux, "pad-added", G_CALLBACK(on_pad_added), NULL);
(3) 请求Pad(用于tee/muxer等)
复制代码
GstPad *tee_src_pad = gst_element_get_request_pad(tee, "src_%u");
gst_pad_link(tee_src_pad, encoder_sink_pad);

2.2 Pad 能力协商流程

2.3 手动能力设置(高级)

复制代码
// 强制设置特定格式
GstCaps *caps = gst_caps_new_simple("video/x-raw",
    "format", G_TYPE_STRING, "I420",
    "width", G_TYPE_INT, 640,
    "height", G_TYPE_INT, 480,
    "framerate", GST_TYPE_FRACTION, 30, 1,
    NULL);

// 在Pad之间插入capsfilter
GstElement *filter = gst_element_factory_make("capsfilter", "filter");
g_object_set(filter, "caps", caps, NULL);
gst_bin_add(GST_BIN(pipeline), filter);
gst_element_link_many(decoder, filter, converter, NULL);

3. 高级 Pad 操作

3.1 Ghost Pad(幽灵Pad)

复制代码
// 创建bin并对外暴露Pad
GstElement *bin = gst_bin_new("my-bin");
GstElement *convert = gst_element_factory_make("videoconvert", "convert");
GstElement *sink = gst_element_factory_make("autovideosink", "sink");

gst_bin_add_many(GST_BIN(bin), convert, sink, NULL);
gst_element_link(convert, sink);

// 创建Ghost Pad
GstPad *pad = gst_element_get_static_pad(convert, "sink");
GstPad *ghost_pad = gst_ghost_pad_new("sink", pad);
gst_element_add_pad(bin, ghost_pad);
gst_object_unref(pad);

3.2 Pad 探针(Probe)

复制代码
// 添加缓冲探针
static GstPadProbeReturn buffer_probe(GstPad *pad, GstPadProbeInfo *info, gpointer user_data) {
    GstBuffer *buffer = GST_PAD_PROBE_INFO_BUFFER(info);
    
    if (buffer) {
        g_print("收到缓冲区,大小: %" G_GSIZE_FORMAT "\n",
                gst_buffer_get_size(buffer));
    }
    return GST_PAD_PROBE_OK;
}

GstPad *sinkpad = gst_element_get_static_pad(convert, "sink");
gst_pad_add_probe(sinkpad, GST_PAD_PROBE_TYPE_BUFFER, buffer_probe, NULL, NULL);
gst_object_unref(sinkpad);

4. 常见问题解决方案

4.1 Pad 连接失败

  1. 检查Caps兼容性

    bash

    复制代码
    GST_DEBUG=2 gst-launch-1.0 ...  # 查看详细的Caps协商过程
  2. 插入格式转换

    bash

    复制代码
    ... ! videoconvert ! video/x-raw,format=NV12 ! ...

4.2 动态Pad未触发

  • 确保元素状态为 READYPAUSED

  • 检查信号连接是否正确:

    复制代码
    g_signal_connect(element, "pad-added", G_CALLBACK(callback), NULL);

4.3 内存泄漏排查

复制代码
// 检查Pad引用计数
g_print("Pad引用计数: %d\n", GST_OBJECT_REFCOUNT_VALUE(pad));

// 正确释放Pad
gst_object_unref(pad);

5. 性能优化技巧

  1. 减少Pad探针开销

    复制代码
    // 仅在需要时保持探针
    gulong probe_id = gst_pad_add_probe(pad, ...);
    gst_pad_remove_probe(pad, probe_id);
  2. 批量处理数据

    复制代码
    // 设置聚合器参数
    g_object_set(aggregator,
        "latency", 50 * GST_MSECOND,
        "max-size-time", 100 * GST_MSECOND,
        NULL);
  3. 零拷贝优化

    bash

    复制代码
    # 使用DMA-BUF格式
    video/x-raw,format=DMABUF ! ...
相关推荐
长沙红胖子Qt2 天前
GStreamer开发笔记(九):gst-rtcp-server安装和部署实现简单的rtsp-server服务器推流Demo
gstreamer·截屏推流·延迟测试
长沙红胖子Qt2 个月前
GStreamer开发笔记(四):ubuntu搭建GStreamer基础开发环境以及基础Demo
ubuntu·流媒体·gstreamer
2739920292 个月前
GStreamer (三)常⽤插件
gstreamer
长沙红胖子Qt3 个月前
GStreamer开发笔记(三):测试gstreamer/v4l2+sdl2/v4l2+QtOpengl打摄像头延迟和内存
流媒体·性能·gstreamer·实时性·延迟与内存
林政硕(Cohen0415)3 个月前
RK3568 基于Gstreamer的多媒体调试记录
linux·rk3568·多媒体·gstreamer
长沙红胖子Qt4 个月前
GStreamer开发笔记(一):GStreamer介绍,在windows平台部署安装,打开usb摄像头对比测试
gstreamer·windows部署gs
芝麻别开门4 个月前
gstreamer之GstVideoDecoder源码剖析
gstreamer
信必诺5 个月前
GStreamer —— 2.2、Windows下Qt加载GStreamer库后运行 - “教程2:GStreamer 概念“(附:完整源码)
qt·gstreamer
张三和李四的家5 个月前
GStreamer源码安装1.24版本
gstreamer