背景
用最少的代码播放一个网络视频,理解 GStreamer 程序的最小骨架:
初始化 → 建管道 → 播放 → 等消息 → 释放
完整代码
#include <gst/gst.h>
int main (int argc, char *argv[]) {
GstElement *pipeline;
GstBus *bus;
GstMessage *msg;
/* 1. 初始化 GStreamer */
gst_init (&argc, &argv);
/* 2. 用一行描述构建管道:playbin 内部完成全部工作 */
pipeline = gst_parse_launch (
"playbin uri=https://gstreamer.freedesktop.org/data/media/"
"sintel_trailer-480p.webm", NULL);
/* 3. 开始播放 */
gst_element_set_state (pipeline, GST_STATE_PLAYING);
/* 4. 等待 ERROR 或 EOS(一直阻塞到其中一个发生) */
bus = gst_element_get_bus (pipeline);
msg = gst_bus_timed_pop_filtered (bus, GST_CLOCK_TIME_NONE,
GST_MESSAGE_ERROR | GST_MESSAGE_EOS);
/* 5. 释放资源 */
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;
}
逐段解析
1. 初始化
gst_init (&argc, &argv);
必须第一个调用。作用:
- 解析 GStreamer 相关命令行参数(如
--gst-debug-level) - 初始化内部数据结构
- 准备好插件系统
参数是 main 的 argc / argv,GStreamer 会从中提取自己需要的选项。
2. 构建管道
pipeline = gst_parse_launch (
"playbin uri=https://gstreamer.freedesktop.org/data/media/"
"sintel_trailer-480p.webm", NULL);
用一行字符串描述构建整条管道。
playbin 是什么?
playbin 是一个"全能"元件,内部自动完成:
读源 → 解封装 → 解码 → 音视频同步 → 输出
所以第 1 课整条管道只有它一个元素。
参数:
- 第一个:管道描述字符串
- 第二个:
GError **,传NULL表示不接收详细错误
注意:字符串可以拆成多行写(C 语言相邻字符串字面量自动拼接),但不能加逗号。
3. 播放
gst_element_set_state (pipeline, GST_STATE_PLAYING);
四种状态:
| 状态 | 含义 |
|---|---|
GST_STATE_NULL | 初始,未分配资源 |
GST_STATE_READY | 已分配资源,未处理 |
GST_STATE_PAUSED | 暂停,数据已准备 |
GST_STATE_PLAYING | 播放中 |
状态转换 NULL → READY → PAUSED → PLAYING,GStreamer 自动完成中间过渡。
4. 等待消息
bus = gst_element_get_bus (pipeline);
msg = gst_bus_timed_pop_filtered (bus, GST_CLOCK_TIME_NONE,
GST_MESSAGE_ERROR | GST_MESSAGE_EOS);
为什么需要总线? GStreamer 是异步的,组件在后台线程工作。错误、EOS 等事件通过总线发送给应用。
参数:
bus:要监听的总线GST_CLOCK_TIME_NONE:超时时间,NONE表示无限等待GST_MESSAGE_ERROR | GST_MESSAGE_EOS:只接收这两种消息
关键消息:
| 消息 | 含义 |
|---|---|
GST_MESSAGE_ERROR | 出错 |
GST_MESSAGE_EOS | End Of Stream,播放结束 |
5. 释放资源
if (msg != NULL) gst_message_unref (msg);
gst_object_unref (bus);
gst_element_set_state (pipeline, GST_STATE_NULL);
gst_object_unref (pipeline);
顺序很重要:先停止管道(NULL),再释放管道。
引用计数:GStreamer 用引用计数管理对象,gst_object_unref 减 1,减到 0 自动销毁。
谁获取,谁释放:
gst_element_get_bus拿到的 bus 需要unrefgst_bus_timed_pop_filtered拿到的 msg 需要unref
编译与运行
gcc 1-Hello_world.c -o 1-Hello_world $(pkg-config --cflags --libs gstreamer-1.0)
./1-Hello_world
运行说明:
- 打开窗口播放视频(含音频)
命令行等价
gst-launch-1.0 playbin uri=https://gstreamer.freedesktop.org/data/media/sintel_trailer-480p.webm
学习方法建议:先用 gst-launch-1.0 在命令行验证管道能跑通,再翻译成 C 代码。
关键 API 速查
| API | 作用 |
|---|---|
gst_init(&argc, &argv) | 初始化 GStreamer |
gst_parse_launch(descr, &error) | 从文本描述构建管道 |
gst_element_set_state(el, state) | 切换元件状态 |
gst_element_get_bus(el) | 取管道总线 |
gst_bus_timed_pop_filtered(bus, timeout, types) | 阻塞等待指定类型消息 |
总结
| 步骤 | API |
|---|---|
| 初始化 | gst_init |
| 建管道 | gst_parse_launch |
| 播放 | gst_element_set_state(PLAYING) |
| 等消息 | gst_element_get_bus + gst_bus_timed_pop_filtered |
| 释放 | gst_message_unref + gst_object_unref + NULL 态 |