本节摘要:Pad 是元件两端的数据接口,带方向(源垫出水、汇垫进水)、带能力集模板(宣称自己能收发什么格式)、分推与拉两种供水模式。本节把这三项规格讲透,并解释"有时存在、有时不存在"的动态衬垫——它是第四章动态管线的伏笔。本节承接元件一节,输出的名词表直接服务第三章的协商机制。
元件之间的连接,本质是源垫与汇垫的对接:上游元件的源垫连到下游元件的汇垫,方向永远单向。一条管线上流动的不只是数据缓冲,还有事件与查询,它们同样经过衬垫进出元件。所以衬垫要理解成一个"三线合一"的接口面:数据线、事件线、查询线共用同一个对接点。
判断一个衬垫的规格,看三样。第一看方向:源垫在元件输出侧,汇垫在输入侧,连接必须源对汇,方向接反是低级但高发的接线错误。第二看可用性:衬垫分"始终存在、偶尔出现、按需创建"三档——文件源那条输出垫永远存在;解封装器的输出垫要等读到流信息才出现;某些多路复用器的输入垫则要显式请求才生成。第三看能力集模板:衬垫出厂时带一张格式清单,宣告自己能接受的媒体类型与参数范围,第三章的协商就在两张清单之间撮合。

元件目录里每个衬垫模板一段,格式固定,值得逐行读懂。
gst-inspect-1.0 x264enc # 输出节选(注释为讲解) # SINK template: This element has 1 sink pad # video/x-raw: 格式名 斜杠后是具体排布 # width: [ 16, 8192 ] 宽度范围 # framerate: [ 0/1, 2147483647/1 ] 帧率范围 # SRC template: This element has 1 source pad # video/x-h264: 编码后输出 # profile: { baseline, main, high } 可选档位
读模板的要点:范围表示可能性,枚举表示清单,固定值表示硬约束。模板里出现固定值(比如某解码器只声明一种色彩排布)意味着协商空间小,管线里往往要配转换元件;模板范围宽的元件则"好相处",接哪儿都行。
静态衬垫在元件创建时就固定,动态衬垫则分两种情况。偶发衬垫(sometimes pad):解封装器读完文件头才知道里面有几路流,每识别一路就长出一个源垫并广播"衬垫新增"信号——播放器代码必须监听这个信号、在回调里接线,这是第四章动态管线的核心场景。请求衬垫(request pad):多路复用器这类元件,你要几路输入就向它请求几个汇垫,比如把视频音频两支流合进一个封装器。
// 监听解封装器的衬垫新增信号:回调里完成接线 g_signal_connect(demuxer, "pad-added", G_CALLBACK(on_pad_added), converter); // 回调骨架:新垫出现 先问能力 再尝试对接 static void on_pad_added(GstElement *demux, GstPad *new_pad, gpointer user_data) { GstPad *sink_pad = gst_element_get_static_pad( GST_ELEMENT(user_data), "sink"); if (gst_pad_is_linked(sink_pad)) { // 已接则忽略 gst_object_unref(sink_pad); return; } // 真正的接法与能力判断在第四章展开 }
⚠️ 常见坑:把解封装器当静态元件直接链接。命令行里写
demux ! decoder能通水,是因为描述工具在底层替你监听了衬垫新增;但换成 C 代码直接静态链接,运行时会得到"衬垫不存在"或"未链接"的报错。命令行的宽容容易掩盖机制,自己写代码时必须补上监听这一课。
把衬垫对接起来时,失败无非三类,每类对应一种检查动作。
| 失败原因 | 典型报错 | 检查动作 |
|---|---|---|
| 方向不匹配 | 无法链接 源垫对源垫 | 核对两端方向 |
| 能力无交集 | 协商失败 无公共格式 | 读两边模板 补转换元件 |
| 垫不存在 | 元件没有该衬垫 | 确认衬垫是静态还是动态 |
第三类在动态衬垫场景最隐蔽——不是"接错了",而是"接早了"。第八章的排错实录会把"接早了"的完整事故展开。
请求垫在命令行里有专门的引用写法:多路复用器的输入垫用带序号模板命名,描述工具会自动请求并接好。看一个最小例子:把测试视频与测试音频合进一个封装器,封装器的两个输入垫都是请求垫,命令行里以名字模板引用即可;换成 C 代码则要先请求垫、再链接,用完释放。
# 请求垫演示:复用器的两路输入垫按需生成 gst-launch-1.0 videotestsrc ! queue ! mux. audiotestsrc ! queue ! mux. mp4mux name=mux ! filesink location=out.mp4
可用性判别口诀:目录条目里衬垫模板一段标着 always、sometimes 或 request——恒有垫直接链接;偶发垫等信号;请求垫先申请。判别永远是第一步,链接方式由它决定,接错方式的报错形态(垫不存在、未链接)在第八章实录里逐一见分晓。
推拉两种模式不只是风格差异,各有工程站位。推模式是默认:上游推、下游被动收,适合实时流——数据到了就得处理,没有讨价还价。拉模式让下游按需取数:解封装器从文件源拉数据,读到哪取到哪,好处是节奏由消费侧决定——播放器暂停时解封装器自然停止取数,不需要额外的闸门;随机访问(跳转)也天然高效,按目标位置直接取。
两种模式在一条管线里可以共存:文件源到解封装器走拉模式,解封装器之后走推模式——这正是"离线源走拉、实时源走推"的惯例来源。自写元件时基类已经把模式细节包掉,你只需要知道自己在哪种模式下工作,避免在推模式的处理函数里做"等待取数"式的假设。
有了元件与衬垫,最后一类对象把零件组织成整机:Bin 负责装配,Pipeline 负责总管。下一节把容器树讲完,第二章收工。