02.手动构建 Pipeline
2026/1/15大约 3 分钟pipelineelement
GStreamer学习笔记:02.手动构建 Pipeline
在 Hello World 示例中,使用了 gst_parse_launch() 来简化 pipeline 的构建。本示例尝试手动创建和连接各个 element,试图理解 GStreamer 的工作原理。
核心概念
1. 创建 Element
使用 gst_element_factory_make() 创建 element:
GstElement *element = gst_element_factory_make(element插件名称, 自定义名称);常见 Element 类型
- source element:生产数据(如
videotestsrc) - filter element:处理数据(如
vertigotv) - sink element:消费数据(如
autovideosink)
示例 Element
source = gst_element_factory_make("videotestsrc", "source");
// source element(生产数据):按照模式(pattern=<number>)生成测试视频
filter = gst_element_factory_make("vertigotv", "filter");
// filter element(处理数据):视频特效滤镜
sink = gst_element_factory_make("autovideosink", "sink");
// sink element(消费数据):自动(根据操作系统选择实例程序)创建窗口播放它接收到的图像2. 创建 Pipeline
使用 gst_pipeline_new() 创建 pipeline:
pipeline = gst_pipeline_new("test-pipeline");重要说明:GStreamer 中的所有元素在使用之前通常必须包含在一条 pipeline 中,pipeline 将负责一些时钟和消息功能。
3. 关于 Bin
- bin 是一个逻辑上的 element,用来从整体上控制和管理其内部的所有 elements
- pipeline 是特殊的 bin
将 element 元素添加到 pipeline(bin)统一管理和控制:
gst_bin_add_many(bin, element1, element2, ..., NULL);注意:因为不确定可变参数列表长度所以需要以 NULL 结尾。
4. 链接 Element
使用 gst_element_link() 将 elements 链接起来:
pipeline: [source -> filter -> sink]
gst_element_link(element1, element2);5. 修改元素属性
使用 g_object_set() 修改元素属性。
查询元素属性
使用 gst-inspect-1.0 命令查看元素的属性:
# 查询 videotestsrc 的属性
gst-inspect-1.0 videotestsrc
# pattern: [0,25]
# [0] : smpte - SMPTE 100% color bars
# [1] : snow - Random (television snow)
# [2] : black - 100% Black
# ....
# 查询 vertigotv 的属性
gst-inspect-1.0 vertigotv
# speed: [0.01, 100]
# zoom-speed: [1.01, 1.10]设置属性示例
g_object_set(source, "pattern", 0, NULL);
g_object_set(filter, "speed", 0.01, NULL);6. 状态管理
修改 pipeline 的状态为播放,并检查返回值判断是否修改成功:
ret = gst_element_set_state(pipeline, GST_STATE_PLAYING);
if (ret == GST_STATE_CHANGE_FAILURE)
{
g_printerr("Unable to set the pipeline to the playing state.\n");
gst_object_unref(pipeline);
return -1;
}7. 解析错误消息
if (msg != NULL)
{
GError *err;
gchar *debug_info;
switch (GST_MESSAGE_TYPE(msg))
{
case GST_MESSAGE_ERROR:
gst_message_parse_error(msg, &err, &debug_info);
g_printerr("Error received from element %s: %s\n", GST_OBJECT_NAME(msg->src), err->message);
g_printerr("Debugging information: %s\n", debug_info ? debug_info : "none");
g_clear_error(&err);
g_free(debug_info);
break;
case GST_MESSAGE_EOS:
g_print("End-Of-Stream reached.\n");
break;
default:
g_printerr("Unexpected message received.\n");
break;
}
gst_message_unref(msg);
}完整代码
#include <gst/gst.h>
int main(int argc, char *argv[])
{
GstElement *pipeline, *source, *filter, *sink;
GstBus *bus;
GstMessage *msg;
GstStateChangeReturn ret;
/* Initialize GStreamer */
gst_init(&argc, &argv);
/* Create the elements */
source = gst_element_factory_make("videotestsrc", "source");
filter = gst_element_factory_make("vertigotv", "filter");
sink = gst_element_factory_make("autovideosink", "sink");
/* Create the empty pipeline */
pipeline = gst_pipeline_new("test-pipeline");
if (!pipeline || !source || !filter || !sink)
{
g_printerr("Not all elements could be created.\n");
return -1;
}
/* Build the pipeline */
gst_bin_add_many(GST_BIN(pipeline), source, filter, sink, NULL);
if (gst_element_link(source, filter) != TRUE ||
gst_element_link(filter, sink) != TRUE)
{
g_printerr("Elements could not be linked.\n");
gst_object_unref(pipeline);
return -1;
}
/* Modify the source's properties */
g_object_set(source, "pattern", 0, NULL);
g_object_set(filter, "speed", 0.01, NULL);
/* Start playing */
ret = gst_element_set_state(pipeline, GST_STATE_PLAYING);
if (ret == GST_STATE_CHANGE_FAILURE)
{
g_printerr("Unable to set the pipeline to the playing state.\n");
gst_object_unref(pipeline);
return -1;
}
/* Wait until error or EOS */
bus = gst_element_get_bus(pipeline);
msg = gst_bus_timed_pop_filtered(bus, GST_CLOCK_TIME_NONE,
GST_MESSAGE_ERROR | GST_MESSAGE_EOS);
/* Parse message */
if (msg != NULL)
{
GError *err;
gchar *debug_info;
switch (GST_MESSAGE_TYPE(msg))
{
case GST_MESSAGE_ERROR:
gst_message_parse_error(msg, &err, &debug_info);
g_printerr("Error received from element %s: %s\n", GST_OBJECT_NAME(msg->src), err->message);
g_printerr("Debugging information: %s\n", debug_info ? debug_info : "none");
g_clear_error(&err);
g_free(debug_info);
break;
case GST_MESSAGE_EOS:
g_print("End-Of-Stream reached.\n");
break;
default:
g_printerr("Unexpected message received.\n");
break;
}
gst_message_unref(msg);
}
/* Free resources */
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总结
本示例展示了:
- 手动创建各个 element
- 创建空 pipeline
- 将 elements 添加到 pipeline
- 手动链接 elements
- 配置元素属性
- 状态管理和错误处理
与使用 gst_parse_launch() 相比,手动构建 pipeline 虽然代码更复杂,但提供了更细粒度的控制,是理解 GStreamer 内部工作原理的重要一步。