4、Element详解:Element的分类(源、过滤器、汇),如何用gst-inspect查看element的属性和pad,动手修改属性

好,咱们进入第四讲。前面几章我们把GStreamer的框架搭起来了,也跑通了几个简单的管道。但说实话,那时候的管道就像个黑盒子——你知道它能把音频从A送到B,但中间到底发生了什么,你并不清楚。

这一章,我们就来拆开这个黑盒子。聊聊Element的分类,以及怎么用gst-inspect这个神器,把每个元件扒个底朝天。

4.1 Element的三大分类:源、过滤器、汇

GStreamer里的Element,说白了就三种角色。我刚开始学的时候,觉得这分类太简单了,后来才发现,理解透这三种角色,是搭复杂管道的基础。

分类 英文名 作用 典型例子
源元件 Source Element 产生数据,只有源垫(Src Pad) filesrc, audiotestsrc, v4l2src
过滤器元件 Filter Element 处理数据,既有源垫又有汇垫 videoconvert, volume, capsfilter
汇元件 Sink Element 消费数据,只有汇垫(Sink Pad) autoaudiosink, filesink, fakesink

你想想看,一个管道就是「源 → 过滤器 → 汇」这样的链条。源只管往外吐数据,过滤器在中间做各种变换,汇则负责把数据输出到设备或文件。就这么简单。

核心概念:一个Element可以有多个Pad,但源元件只有Src Pad,汇元件只有Sink Pad。过滤器元件两者都有。这是判断元件类型的最直接方法。

4.2 用gst-inspect查看Element的属性和Pad

好,理论说完了,咱们来点实战。怎么知道一个元件有哪些属性?有哪些Pad?能接什么格式的数据?

答案就是gst-inspect-1.0。这个工具,我几乎每天都要用。它就像元件的「身份证」加「说明书」。

4.2.1 基本用法

打开终端,输入:

gst-inspect-1.0 videotestsrc

你会看到一大段输出。别慌,我带你逐段看。

第一段是基本信息:

Factory Details:
  Rank: none (0)
  Long-name: Video test source
  Klass: Source/Video
  Description: Creates a test video stream
  Author: David A. Schleef <ds@schleef.org>

注意看Klass字段,它告诉你这个元件属于Source/Video类。嗯,源元件,没错。

接下来是Pad模板:

Pad Templates:
  SRC template: 'src'
    Availability: Always
    Capabilities:
      video/x-raw
                 format: { I420, YV12, YUY2, ... }
                  width: [ 1, 2147483647 ]
                 height: [ 1, 2147483647 ]
              framerate: [ 0/1, 2147483647/1 ]
      video/x-raw(meta:video/x-raw-meta)
                 ...

这里信息量很大。它告诉你这个源垫支持哪些格式、分辨率范围、帧率范围。说白了,就是「我能吐出什么样的数据」。

我的小技巧:当你看到Availability: Always,表示这个Pad是固定存在的。如果是Sometimes,那它可能在某些条件下才出现,比如oggdemux的解复用器,数据解析完才知道有几个输出流。

再往下翻,是元件属性:

Element Properties:
  name                : The name of the object
                        flags: readable, writable
                        String. Default: "videotestsrc0"
  num-buffers         : Number of buffers to output before sending EOS
                        flags: readable, writable
                        Unsigned Integer. Default: -1, Min: -1, Max: 2147483647
  pattern             : Test pattern to generate
                        flags: readable, writable
                        Enum "GstVideoTestSrcPattern" Default: 0, "smpte"
                           (0): smpte           - SMPTE 100% color bars
                           (1): snow            - Random (television snow)
                           (2): black           - 100% Black
                           ...

看到了吗?pattern属性可以设置不同的测试图案。默认是smpte彩条,你也可以改成snow雪花或者black纯黑。

4.2.2 快速查看特定信息

有时候你不想看全部输出,只想查某个属性或Pad。可以用grep过滤:

# 只看属性
gst-inspect-1.0 videotestsrc | grep -A 5 "Element Properties"

# 只看Pad模板
gst-inspect-1.0 videotestsrc | grep -A 20 "Pad Templates"

我个人习惯把常用元件的输出保存成文件,方便查阅:

gst-inspect-1.0 videotestsrc > videotestsrc_info.txt

4.3 动手修改属性

光看不动,那是纸上谈兵。咱们来改改属性,看看效果。

4.3.1 通过命令行修改

最简单的办法,就是在gst-launch-1.0里直接设置:

gst-launch-1.0 videotestsrc pattern=2 ! autovideosink

这条命令把pattern设为2,也就是纯黑画面。你运行一下,窗口里应该是一片黑。

再试试雪花效果:

gst-launch-1.0 videotestsrc pattern=1 ! autovideosink

嗯,满屏的雪花,是不是有点老电视的感觉?

注意:属性值可以是数字,也可以是字符串。具体用哪种,看gst-inspect输出的类型。如果是Enum类型,你可以用数字索引,也可以用字符串名称。比如pattern=1和pattern=snow效果一样。

4.3.2 通过代码修改

在C代码里,修改属性用g_object_set:

#include <gst/gst.h>

int main(int argc, char *argv[]) {
    GstElement *pipeline, *source;
    
    gst_init(&argc, &argv);
    
    pipeline = gst_pipeline_new("test-pipeline");
    source = gst_element_factory_make("videotestsrc", "source");
    
    // 修改属性:设置图案为雪花,输出10帧后结束
    g_object_set(source, "pattern", 1, "num-buffers", 10, NULL);
    
    gst_bin_add(GST_BIN(pipeline), source);
    // ... 连接其他元件并启动
    
    return 0;
}

这里要注意,g_object_set的参数是可变参数列表,以NULL结尾。属性名和值成对出现。

4.3.3 运行时动态修改

管道跑起来之后,能不能改属性?当然可以。用gst-launch-1.0的--eos-on-signal参数,或者通过总线消息机制。

更常用的方式是用gst-launch-1.0的交互模式:

gst-launch-1.0 -v videotestsrc ! autovideosink

加上-v参数后,你会看到管道状态变化的信息。但真正动态修改,我建议用Python或者写个小程序,监听键盘事件来切换属性。

我曾经在一个项目中需要实时切换视频源的分辨率。一开始我重建了整个管道,后来发现直接用g_object_set修改videoscale的width和height属性,配合capsfilter,就能无缝切换。省了不少事。

4.4 知识体系图

下面这张图,帮你把本章的核心逻辑串起来:

Element分类与gst-inspect知识体系 Element分类与gst-inspect知识体系 源元件 (Source) 过滤器 (Filter) 汇元件 (Sink) 只有 Src Pad Src Pad + Sink Pad 只有 Sink Pad gst-inspect-1.0 元件名 基本信息 (Klass, Rank) Pad模板 (格式/范围) 属性列表 (可读写) 动手修改:gst-launch-1.0 属性=值 或 g_object_set()

4.5 实战:用gst-inspect排查问题

最后,分享一个我实际遇到的案例。

有一次,我需要把摄像头采集的MJPEG流解码并显示。我搭了这么个管道:

gst-launch-1.0 v4l2src ! jpegdec ! autovideosink

结果报错了,说Pad不兼容。我第一反应就是查v4l2src的输出格式:

gst-inspect-1.0 v4l2src | grep -A 30 "SRC template"

输出显示,v4l2src的源垫支持video/x-raw和image/jpeg两种格式。但默认情况下,它可能输出video/x-raw,而jpegdec需要image/jpeg输入。

解决办法是在中间加一个capsfilter,强制指定格式:

gst-launch-1.0 v4l2src ! video/x-raw,format=YUY2 ! videoconvert ! autovideosink

或者直接用jpegdec能识别的格式:

gst-launch-1.0 v4l2src ! image/jpeg ! jpegdec ! videoconvert ! autovideosink

避坑指南:我曾经花了一下午调试一个管道,怎么都连不上。最后发现是capsfilter里写错了属性名——把format写成了fmt。记住,属性名必须和gst-inspect输出的一模一样,大小写敏感。

嗯,这一章的内容就到这。记住,gst-inspect是你调试GStreamer管道的左膀右臂。遇到问题,先查它,准没错。