部分图片来自网络文章,侵权必删
前言
上一章节中我们介绍了GStreamer的一个基本概念:element,以及由element引申出的pad属性。这一节中我们介绍另一个重要的pipeline概念。
一、什么是pipeline
单个element的功能相对简单独立(独立其实为了解耦,SB才把所有功能揉到一个模块),需要其他的element配合才可以完成复杂的功能。通过将source element与其他filter-like element以及最终的sink element链接起来,您就创建了一个媒体数据管道----pipeline。
通过链接这三个元素,我们创建了一个非常简单的元素链。这样做的效果是,source element的输出将用作filter elemetn的输入,filter element将对数据进行处理并将结果发送到最终sink element。将上图想象成一个简单的 mp3 音频解码器:source是从磁盘读取文件,filter是mp3音频解码器,sink是声卡用于播放解码后的音频数据。在代码中,上图的写法如下:
#include <gst/gst.h>
int main (int argc, char *argv[])
{
GstElement *pipeline;
GstElement *source, *filter, *sink;
/* 初始化*/
gst_init (&argc, &argv);
/* 创建管道 */
pipeline = gst_pipeline_new ("my-pipeline");
/* 创建多个元素 */
source = gst_element_factory_make ("fakesrc", "source");
filter = gst_element_factory_make ("identity", "filter");
sink = gst_element_factory_make ("fakesink", "sink");
/* 必须在链接之前将元素添加到管道中 */
gst_bin_add_many (GST_BIN (pipeline), source, filter, sink, NULL);
/* 链接相关元素 */
if (!gst_element_link_many (source, filter, sink, NULL)) {
g_warning ("Failed to link elements!");
}
[..]
}
除了gst_element_link_many()函数可用之外,对于更具体的行为还有函数 gst_element_link () 和 gst_element_link_pads ()。您还可以获取对各个 pad 的引用,并使用各种 gst_pad_link_* () 函数链接这些 pad。
重要提示
您必须先将元素添加到element然后再链接它们,因为将元素添加到容器会断开任何现有的链接。此外您不能直接链接不在同一容器或管道中的元素。
二、pipeline如何工作
pipeline创建出来了,但是是如何工作的呢?这时候就需要介绍Gst的底层工作原理的。简单一点就是:pipeline运行在mainloop线程中,管理着各个element,element之间通过传递不同形式的buffer来实现数据交换,application与pipeline之间通过bus交互命令与状态。
2.1 消息总线(Bus)
Gstreamer- 消息总线(bus)_gstreamer bus-优快云博客
消息总线负责将消息从pipeline流线程转发到其自己的线程上下文中的应用程序。默认情况下,每个pipeline都包含一个消息总线,因此应用程序不需要创建消息总线或任何东西。应用程序唯一应该做的就是在消息总线上设置一个消息处理程序,这类似于目标(object)的信号处理程序。当主循环运行时,消息总线会定期检查新消息,当有消息可用时处理程序会被调用。
2.1.1 消息总线的使用方法
有两种不同的方式使用消息总线:
-
运行 GLib/Gtk+ 主循环(或自己定期迭