4. Element 详解:类型、属性与 Pad

GStreamer 里的 Element(元素),说白了就是管线里的积木块。你搭一条管线,本质上就是把各种 Element 串起来。我刚开始接触 GStreamer 时,总觉得这东西很玄乎,后来发现它其实就三种角色:Source(源头)、Filter(过滤器)、Sink(接收器)。

嗯,咱们今天就把它彻底讲透。

4.1 三种核心类型

每个 Element 在管线里都有自己的「岗位」。我习惯用一句话来记:Source 只管往外吐数据,Sink 只管往里收数据,Filter 夹在中间做处理。

类型 角色 典型例子 Pad 特点
Source 数据生产者 filesrc、audiotestsrc、v4l2src 只有 src pad(输出)
Filter 数据处理者 videoconvert、capsfilter、volume 既有 sink pad(输入),也有 src pad(输出)
Sink 数据消费者 autovideosink、filesink、alsasink 只有 sink pad(输入)

关键认知:Source 和 Sink 是管线的「边界」。Filter 是管线的「内脏」。你想想看,没有 Source 数据从哪来?没有 Sink 数据去哪了?Filter 再多,也得靠两头撑着。

我在项目中遇到过一个问题:有人把 filesrc 当 Filter 用,试图在它后面接两个 Sink。结果呢?管线直接报错。因为 Source 只有一个 src pad,它没法同时把数据分给两个下游。这就是不理解 Element 类型的后果。

4.2 用 gst-inspect 查看 Element

光知道类型还不够。实际开发中,你拿到一个 Element,得知道它有哪些属性可以调,有哪些 Pad 可以连。这时候 gst-inspect 就是你的「照妖镜」。

4.2.1 基本用法

# 查看某个 Element 的详细信息
gst-inspect-1.0 filesrc

# 列出所有已安装的 Element
gst-inspect-1.0 | grep src

我个人习惯先跑 gst-inspect-1.0 filesrc,然后直接看输出里的几个关键段落。输出内容很多,但咱们只抓重点。

4.2.2 输出结构解读

拿 filesrc 举例,输出大概长这样(我简化了):

Factory Details:
  Rank: none (0)
  Long-name: File Source
  Class: Source/File
  ...

Pad Templates:
  SRC template: 'src'
    Availability: Always
    Capabilities:
      video/mpeg
      audio/mpeg
      ...

Element Properties:
  name                : The name of the object
  location            : Location of the file to read
  blocksize           : Size of blocks to read (default: 4096)
  ...

咱们拆开来看:

  • Factory Details:告诉你这个 Element 叫什么、属于哪一类。比如 Class: Source/File,一眼就知道它是 Source 类型。
  • Pad Templates:这是最核心的部分。它列出了这个 Element 有哪些 Pad,每个 Pad 支持什么格式(Capabilities)。filesrc 只有一个 src Pad,而且 Availability: Always,意思是这个 Pad 一直存在。
  • Element Properties:属性列表。每个属性都有名字、类型、默认值、描述。比如 location 就是你要读取的文件路径。

小技巧:如果你想知道某个属性支持哪些值,可以用 gst-inspect-1.0 元素名 属性名。比如 gst-inspect-1.0 x264enc bitrate,它会单独显示这个属性的详细约束。

4.2.3 查看 Pad 的 Capabilities

Pad 的 Capabilities 决定了这个 Element 能处理什么格式的数据。我曾经调试一个视频管线,画面一直出不来,最后发现是 videoconvert 的 src pad 输出的格式跟下游 Sink 不匹配。

用 gst-inspect 可以清楚看到:

gst-inspect-1.0 videoconvert

Pad Templates:
  SINK template: 'sink'
    Availability: Always
    Capabilities:
      video/x-raw
                 format: { I420, YV12, NV12, NV21, ... }
                 width:  [ 1, 2147483647 ]
                 height: [ 1, 2147483647 ]
  SRC template: 'src'
    Availability: Always
    Capabilities:
      video/x-raw
                 format: { I420, YV12, NV12, NV21, ... }
                 width:  [ 1, 2147483647 ]
                 height: [ 1, 2147483647 ]

看到 format: { I420, YV12, ... } 了吗?这就是它支持的像素格式列表。如果你的 Source 输出的是 RGB,而 videoconvert 的 sink pad 不支持,那管线就会协商失败。

4.3 属性操作实战

光看不行,还得会改。属性操作有两种方式:

  1. 命令行:用 gst-launch-1.0 的 属性名=值 语法。
  2. 代码中:用 g_object_set() 或 GStreamer 的 gst_element_set_property()。

4.3.1 命令行示例

# 设置 filesrc 的 location 属性
gst-launch-1.0 filesrc location=/path/to/video.mp4 ! decodebin ! autovideosink

# 设置 volume 的 volume 属性(0.0 ~ 1.0)
gst-launch-1.0 audiotestsrc ! volume volume=0.5 ! autoaudiosink

这里要注意:属性名是大小写敏感的。我曾经手滑把 location 写成 Location,结果管线直接罢工。嗯,这种低级错误犯过一次就记住了。

4.3.2 代码中操作

// C 语言示例
GstElement *volume = gst_element_factory_make("volume", "my_volume");
g_object_set(volume, "volume", 0.5, NULL);

// 或者用 GStreamer 专用 API
gst_element_set_property(volume, "volume", 0.5);

避坑指南:我曾经在 Python 绑定里用 set_property("volume", 0.5),结果发现音量没变。查了半天,原来是属性类型是 double,而我传了整数 0。GStreamer 不会帮你做隐式类型转换,传错类型它就直接忽略。所以,一定要用 gst-inspect 确认属性类型。

4.4 知识体系图

下面这张图总结了 Element 的类型、Pad 和属性的关系。我建议你把它存下来,以后遇到 Element 相关的问题,先看这张图定位。

GStreamer Element 类型与 Pad 关系图 GStreamer Element 类型与 Pad 关系 Source Element 只有 src pad Filter Element sink pad + src pad Sink Element 只有 sink pad 数据流 数据流 每个 Element 都有属性(Properties) 用 gst-inspect 查看属性名、类型、默认值 用 g_object_set() 或 gst-launch 属性名=值 来设置 属性类型必须匹配:double、int、string、boolean 等 Pad 的三种 Availability Always:Pad 一直存在 Sometimes:Pad 可能不存在(如 parsebin) On request:Pad 需要主动请求(如 tee) Capabilities 决定 Pad 能处理什么格式 格式不匹配 → 管线协商失败 用 gst-inspect 查看 Capabilities 列表

4.5 实战:用 gst-inspect 诊断问题

最后分享一个真实案例。有一次我在调试 RTSP 推流,画面一直黑屏。我怀疑是编码器参数不对,于是:

  1. 先用 gst-inspect-1.0 x264enc 查看所有属性。
  2. 发现 bitrate 属性的范围是 [0, 100000],单位是 kbps。
  3. 又看了 key-int-max 属性,默认值是 250。
  4. 最后发现是 pass 属性设成了 qual(质量模式),而接收端只支持 cbr(恒定码率)。

改完 pass=cbr,画面就出来了。你看,gst-inspect 就是你的调试利器。遇到问题别瞎猜,先 inspect 一下。

我的习惯:每次引入一个新的 Element,第一件事就是跑 gst-inspect-1.0 元素名 | grep -i "property\|pad\|cap",快速定位关键信息。省时省力。