11.自定义 Playbin 音频 Sink
2026/1/28大约 4 分钟playbincustom-sink
GStreamer学习笔记:11.自定义 Playbin 音频 Sink
本示例尝试为 playbin 创建自定义的音频 sink,试图通过使用 GstBin 封装多个元素,实现自定义的音频处理链(如均衡器)。
核心概念
1. GstBin - 自定义元素容器
GstBin 是一个逻辑上的 element,可以将多个 elements 组合成一个单独的 element。
创建自定义 Bin
bin = gst_bin_new("audio_sink_bin");2. Ghost Pad - 幽灵 Pad
Ghost Pad 允许 Bin 内部的某个 Pad 暴露给外部,使得 Bin 可以像一个普通 element 一样被连接。
创建 Ghost Pad
// 获取 equalizer.sink_pad
pad = gst_element_get_static_pad(equalizer, "sink");
// 创建 ghost_pad,名为 sink,实际指向 equalizer.sink_pad
ghost_pad = gst_ghost_pad_new("sink", pad);
// 激活 ghost_pad
gst_pad_set_active(ghost_pad, TRUE);
// 添加到 bin
gst_element_add_pad(bin, ghost_pad);
gst_object_unref(pad);Ghost Pad 的作用
外部视角:
playbin -> audio_sink_bin (ghost pad: sink)
|
v
audio_sink_bin 内部:
equalizer.sink (实际 pad)Ghost Pad 使得 audio_sink_bin 可以像一个普通的 sink element 一样被 playbin 使用。
3. 音频处理链
创建元素
equalizer = gst_element_factory_make("equalizer-3bands", "equalizer");
convert = gst_element_factory_make("audioconvert", "convert");
sink = gst_element_factory_make("autoaudiosink", "audio_sink");构建处理链
GstBin audio_sink_bin = [equalizer-3bands => audioconvert => autoaudiosink]bin = gst_bin_new("audio_sink_bin");
gst_bin_add_many(GST_BIN(bin), equalizer, convert, sink, NULL);
gst_element_link_many(equalizer, convert, sink, NULL);4. 三段均衡器
equalizer-3bands 元素提供三个频段的音量调节:
- band0(100Hz):低频增益,范围
[-24, +12],默认 0 - band1(1100Hz):中频增益,范围
[-24, +12],默认 0 - band2(11000Hz):高频增益,范围
[-24, +12],默认 0
配置均衡器
// 保留低频,完全衰减中高频
g_object_set(G_OBJECT(equalizer), "band0", (gdouble)0, NULL);
g_object_set(G_OBJECT(equalizer), "band1", (gdouble)-24.0, NULL);
g_object_set(G_OBJECT(equalizer), "band2", (gdouble)-24.0, NULL);5. 设置 Playbin 音频 Sink
将 playbin 播放器的音频部分修改为用自定义的音频播放器来播放:
g_object_set(GST_OBJECT(pipeline), "audio-sink", bin, NULL);Pipeline 结构
playbin (内部自动构建)
video -> autoaudiosink (默认)
audio -> audio_sink_bin (自定义)
|
+-> equalizer-3bands
|
+-> audioconvert
|
+-> autoaudiosink6. 完整流程
步骤 1:创建 playbin
pipeline = gst_parse_launch("playbin uri=https://www.freedesktop.org/software/gstreamer-sdk/data/media/sintel_trailer-480p.webm", NULL);步骤 2:创建音频处理元素
equalizer = gst_element_factory_make("equalizer-3bands", "equalizer");
convert = gst_element_factory_make("audioconvert", "convert");
sink = gst_element_factory_make("autoaudiosink", "audio_sink");步骤 3:构建自定义 Bin
bin = gst_bin_new("audio_sink_bin");
gst_bin_add_many(GST_BIN(bin), equalizer, convert, sink, NULL);
gst_element_link_many(equalizer, convert, sink, NULL);步骤 4:创建 Ghost Pad
pad = gst_element_get_static_pad(equalizer, "sink");
ghost_pad = gst_ghost_pad_new("sink", pad);
gst_pad_set_active(ghost_pad, TRUE);
gst_element_add_pad(bin, ghost_pad);
gst_object_unref(pad);步骤 5:配置均衡器
g_object_set(G_OBJECT(equalizer), "band0", (gdouble)0, NULL);
g_object_set(G_OBJECT(equalizer), "band1", (gdouble)-24.0, NULL);
g_object_set(G_OBJECT(equalizer), "band2", (gdouble)-24.0, NULL);步骤 6:设置 playbin 音频 sink
g_object_set(GST_OBJECT(pipeline), "audio-sink", bin, NULL);步骤 7:开始播放
gst_element_set_state(pipeline, GST_STATE_PLAYING);为什么需要 Ghost Pad?
没有 Ghost Pad 的情况:
// 这是不行的!
// playbin 不知道应该连接到 audio_sink_bin 的哪个 pad
gst_element_link(playbin, bin); // 失败有 Ghost Pad 的情况:
// audio_sink_bin 暴露了一个名为 "sink" 的 ghost pad
// 它指向 equalizer.sink
// playbin 可以像连接普通 element 一样连接 audio_sink_bin
g_object_set(GST_OBJECT(pipeline), "audio-sink", bin, NULL); // 成功扩展自定义 Sink
你可以构建更复杂的音频处理链:
// 例如:添加音量控制、回声效果等
volume = gst_element_factory_make("volume", "volume");
echo = gst_element_factory_make("audioecho", "echo");
bin = gst_bin_new("audio_sink_bin");
gst_bin_add_many(GST_BIN(bin), equalizer, volume, echo, convert, sink, NULL);
gst_element_link_many(equalizer, volume, echo, convert, sink, NULL);
// 创建 ghost pad
pad = gst_element_get_static_pad(equalizer, "sink");
ghost_pad = gst_ghost_pad_new("sink", pad);
gst_pad_set_active(ghost_pad, TRUE);
gst_element_add_pad(bin, ghost_pad);
gst_object_unref(pad);
// 设置效果参数
g_object_set(volume, "volume", 0.5, NULL);
g_object_set(echo, "delay", 500000000, "intensity", 0.5, NULL);
g_object_set(GST_OBJECT(pipeline), "audio-sink", bin, NULL);完整代码
#include <gst/gst.h>
int main(int argc, char *argv[])
{
GstElement *pipeline, *bin, *equalizer, *convert, *sink;
GstPad *pad, *ghost_pad;
GstBus *bus;
GstMessage *msg;
gst_init(&argc, &argv);
pipeline = gst_parse_launch("playbin uri=https://www.freedesktop.org/software/gstreamer-sdk/data/media/sintel_trailer-480p.webm", NULL);
equalizer = gst_element_factory_make("equalizer-3bands", "equalizer");
convert = gst_element_factory_make("audioconvert", "convert");
sink = gst_element_factory_make("autoaudiosink", "audio_sink");
if (!equalizer || !convert || !sink)
{
g_printerr("Not all elements could be created.\n");
return -1;
}
bin = gst_bin_new("audio_sink_bin");
gst_bin_add_many(GST_BIN(bin), equalizer, convert, sink, NULL);
gst_element_link_many(equalizer, convert, sink, NULL);
pad = gst_element_get_static_pad(equalizer, "sink");
ghost_pad = gst_ghost_pad_new("sink", pad);
gst_pad_set_active(ghost_pad, TRUE);
gst_element_add_pad(bin, ghost_pad);
gst_object_unref(pad);
g_object_set(G_OBJECT(equalizer), "band0", (gdouble)0, NULL);
g_object_set(G_OBJECT(equalizer), "band1", (gdouble)-24.0, NULL);
g_object_set(G_OBJECT(equalizer), "band2", (gdouble)-24.0, NULL);
g_object_set(GST_OBJECT(pipeline), "audio-sink", bin, NULL);
gst_element_set_state(pipeline, GST_STATE_PLAYING);
bus = gst_element_get_bus(pipeline);
msg = gst_bus_timed_pop_filtered(bus, GST_CLOCK_TIME_NONE, GST_MESSAGE_ERROR | GST_MESSAGE_EOS);
if (msg != NULL)
gst_message_unref(msg);
gst_object_unref(bus);
gst_element_set_state(pipeline, GST_STATE_NULL);
gst_object_unref(pipeline);
return 0;
}编译和运行
gcc main.c -o main.out $(pkg-config --cflags --libs gstreamer-1.0)
./main.out应用场景
自定义 playbin 音频 sink 的典型应用场景包括:
- 音频效果处理:添加均衡器、混响、回声等效果
- 音频分析:实时分析音频频谱、音量等
- 音频录制:在播放的同时录制音频
- 多路输出:同时输出到多个设备
- 音频可视化:生成音频可视化数据
- 音频增强:降噪、音量自动调节等
总结
本示例展示了:
- GstBin:将多个元素组合成一个逻辑单元
- Ghost Pad:将 Bin 内部的 Pad 暴露给外部
- 自定义 Sink:为 playbin 创建自定义的音频处理链
- 音频处理:使用均衡器等元素实现音频效果
通过使用 GstBin 和 Ghost Pad,你可以构建复杂的自定义元素,并将其无缝集成到 playbin 中,从而实现高度定制化的媒体播放应用。