GStreamer:构建媒体处理管道
bash
Debian/Ubuntu
sudo apt update
sudo apt install gstreamer1.0-tools gstreamer1.0-plugins-base
gstreamer1.0-plugins-good gstreamer1.0-plugins-bad
gstreamer1.0-plugins-ugly libgstreamer1.0-dev
macOS 可使用 Homebrew:
```bash
brew install gstreamer gst-plugins-base gst-plugins-good \
gst-plugins-bad gst-plugins-ugly
Windows 用户可从 GStreamer 官网 下载安装包。
核心概念
理解 GStreamer 的四个核心概念是构建管道的基石。
元素
元素是处理媒体数据的最小功能单元。每个元素执行一个特定操作,例如:
- source:产生数据(从文件、网络、摄像头)
- filter/transform:处理数据(编码、解码、缩放)
- sink:消耗数据(播放到声卡、写入文件)
元素通过衬垫 (pad) 进行连接。
衬垫
衬垫是元素的输入或输出接口。源衬垫(src pad)产生数据,接收衬垫(sink pad)消费数据。只有具兼容能力的衬垫才能相互连接(协商 caps)。
箱柜
箱柜 (bin) 是元素的容器,可将多个元素组合成一个逻辑整体。它可以像单个元素一样操作状态,其中最常用的两个箱柜是:
- 管道 (pipeline):顶层的箱柜,通常代表整个应用的处理流程。
- 播放仓 (playbin):一个自动化的播放元素,内部封装了完整的解码与渲染管道。
总线与消息
管道拥有一个总线 (bus),用于异步通知应用事件(如错误、结束、状态变化)。通过监听总线消息,应用可以获取管道运行时的反馈。
命令行快速入门
gst-launch-1.0 是测试和构建管道的命令行工具。其基本语法为:
gst-launch-1.0 [元素1] ! [元素2] ! [元素3] ...
感叹号 ! 连接元素,数据从左向右流动。
播放本地音频文件
gst-launch-1.0 filesrc location=song.mp3 ! decodebin ! audioconvert ! autoaudiosink
filesrc读取文件decodebin自动检测格式并解码audioconvert转换音频格式autoaudiosink自动选择音频输出设备
播放视频文件
gst-launch-1.0 playbin uri=file:///path/to/video.mp4
playbin 封装了完整播放流程,一行搞定。
创建测试音视频
生成一段 440Hz 正弦波测试音,持续5秒:
gst-launch-1.0 audiotestsrc freq=440 ! audioconvert ! autoaudiosink
显示测试视频图案:
gst-launch-1.0 videotestsrc ! autovideosink
捕获摄像头并显示
gst-launch-1.0 v4l2src ! videoconvert ! autovideosink
(v4l2src 在 Linux 下可用,其他系统请用 avfvideosrc、ksvideosrc 等)
构建管道:C 语言示例
通过 API 动态创建管道可完成更复杂的控制。下面是一个最小可运行的 C 程序,实现播放 MP3 文件。
环境准备
编译时需链接 GStreamer:
gcc -o play play.c `pkg-config --cflags --libs gstreamer-1.0`
代码
#include <gst/gst.h>
int main(int argc, char *argv[]) {
GstElement *pipeline, *source, *decode, *convert, *sink;
GstBus *bus;
GstMessage *msg;
/* 初始化 GStreamer */
gst_init(&argc, &argv);
/* 创建元素 */
pipeline = gst_pipeline_new("my-pipeline");
source = gst_element_factory_make("filesrc", "file-source");
decode = gst_element_factory_make("decodebin", "decoder");
convert = gst_element_factory_make("audioconvert", "converter");
sink = gst_element_factory_make("autoaudiosink", "audio-output");
if (!pipeline || !source || !decode || !convert || !sink) {
g_printerr("One or more elements could not be created.\n");
return -1;
}
/* 设置文件路径 */
g_object_set(source, "location", "song.mp3", NULL);
/* 将所有元素加入管道 */
gst_bin_add_many(GST_BIN(pipeline), source, decode, convert, sink, NULL);
/* 连接静态元素 */
if (!gst_element_link(source, decode)) {
g_printerr("Failed to link filesrc and decodebin.\n");
return -1;
}
if (!gst_element_link_many(convert, sink, NULL)) {
g_printerr("Failed to link audioconvert and audiosink.\n");
return -1;
}
/* decodebin 的动态衬垫需要在运行时连接,这里简化使用消息监听 */
g_signal_connect(decode, "pad-added", G_CALLBACK(on_pad_added), convert);
/* 启动管道 */
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;
}
/* decodebin 的动态 pad-added 回调 */
static void on_pad_added(GstElement *decode, GstPad *pad, gpointer data) {
GstElement *convert = (GstElement *)data;
GstPad *sinkpad = gst_element_get_static_pad(convert, "sink");
if (!gst_pad_is_linked(sinkpad)) {
GstPadLinkReturn ret = gst_pad_link(pad, sinkpad);
g_print("Dynamic pad linking: %s\n",
ret == GST_PAD_LINK_OK ? "OK" : "Failed");
}
gst_object_unref(sinkpad);
}
该程序创建管道并静态连接 filesrc 与 decodebin。因 decodebin 输出衬垫在运行时才创建,因此通过 pad-added 信号动态连接到 audioconvert。
常用管道模式
编码与文件录制
将摄像头视频编码为 H.264 保存到文件:
gst-launch-1.0 v4l2src ! videoconvert ! x264enc ! mp4mux ! filesink location=output.mp4
RTP 流媒体传输
发送端(H.264 视频流):
gst-launch-1.0 videotestsrc ! videoconvert ! x264enc ! rtph264pay ! udpsink host=127.0.0.1 port=5000
接收端:
gst-launch-1.0 udpsrc port=5000 caps="application/x-rtp, media=video, payload=96" ! rtph264depay ! avdec_h264 ! videoconvert ! autovideosink
音量归一化与音频混合
gst-launch-1.0 audiotestsrc ! volume volume=0.5 ! autoaudiosink