GStreamer 开发记录(一):Hello World —— 最小播放骨架

0 阅读3分钟

背景

用最少的代码播放一个网络视频,理解 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_EOSEnd 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 需要 unref
  • gst_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 态