文章目录
- 前言
- 一、源码环境搭建
- 二、Basic Tutorial 1 Hello world
- 三、开启更多日志
- 参考
前言
本系列文章将纪录学习 [GStreamer] 的过程。
为什么想学习 [GStreamer],有这么几个原因:
- 多媒体处理是一个复杂的任务,[GStreamer] 的管道架构可以将复杂的任务以「图」的形式模块化的进行处理,它足够灵活。学习 [GStreamer] 这种架构思想,可以帮助我扩展视野,面对复杂任务如何给出一套灵活可靠的框架。
- 掌握 [GStreamer] 对求职有所帮助,如果你对 [GStreamer] 很熟悉,很多音视频岗位是可以加分的。
- 我想造一个视频编辑框架的轮子,无论是基于 [GStreamer] 来实现,还是参考 [GStreamer] 的框架,我都得对 [GStreamer] 非常熟悉。
我对 FFMpeg 比较熟悉,对于 [GStreamer] 属于纯纯新手,因此本系列文章面向的观众也是像我一样想要学习 [GStreamer] 的小白,内容上不会太过深入,属于是想到啥写啥,遇到啥写啥,将学习中查找的资料、遇到的问题、解决的方式、个人的理解通通都写上。
当前目标:
- 将 Basic Tutorial 中教程全部过一遍。
- 封装一个自己的插件
一、源码环境搭建
在源码环境下进行断点调试,可以一窥 [GStreamer] 的实现逻辑。
如何搭建源码调试环境请参考 GStreamer 源码编译,在 Clion 下搭建调试环境
接下来说明如何在源码环境下运行 Tutorial。
- 新建文件夹。在 gstreamer/subprojects 下,找一个文件夹,例如我用的是 gst-examples。在 gst-examples 下面新建一个 my_examples 文件夹
- 修改 gst-examples 的 meson.build,添加
subdir('my_examples')
即可
- 添加 tutorial 运行文件。从 gstreamer/subprojects/gst-docs/examples/tutorials 下,拷贝 basic-tutorial-* 等这些教程运行文件到 my_examples 下
- 更新 my_examples/meson.build 文件,如下
executable('basic-tutorial-1',['basic-tutorial-1.c'],dependencies : [gst_dep, m_dep])
至此,教程运行文件添加完毕,我们可以在 CLion 上快乐地源码调试运行这些教程了。
我把对应的代码上传到了 github 上,你可以参考这里 my_examples
二、Basic Tutorial 1 Hello world
教程链接:https://gstreamer.freedesktop.org/documentation/tutorials/basic/hello-world.html?gi-language=c
代码咋一看挺多挺唬人的,但其实真正在工作的就 4 行,其他的都是初始化、清理等。下面对重要代码做下说明
int
tutorial_main (int argc, char *argv[])
{GstElement *pipeline;GstBus *bus;GstMessage *msg;/* Initialize GStreamer */gst_init (&argc, &argv);/* Build the pipeline */pipeline =gst_parse_launch("playbin uri=https://gstreamer.freedesktop.org/data/media/sintel_trailer-480p.webm",NULL);/* Start playing */gst_element_set_state (pipeline, GST_STATE_PLAYING);/* 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);/* See next tutorial for proper error message handling/parsing */if (GST_MESSAGE_TYPE (msg) == GST_MESSAGE_ERROR) {g_printerr ("An error occurred! Re-run with the GST_DEBUG=*:WARN ""environment variable set for more details.\n");}/* Free resources *//...return 0;
}
这些代码行是一个使用GStreamer的基本程序,它主要用来播放网络上的流媒体内容。以下是这些代码的各个步骤的总结:
-
初始化GStreamer
gst_init (&argc, &argv);
这是所有GStreamer应用程序的第一个命令。这个函数完成了内部结构的初始化,检查插件的可用性,和执行为GStreamer预设的命令行选项。如果你的应用程序总是把argc和argv参数传递给gst_init,你的应用程序将自动受益于GStreamer的标准命令行选项。
-
构建管道
pipeline = gst_parse_launch("playbin uri=https://gstreamer.freedesktop.org/data/media/sintel_trailer-480p.webm", NULL);
gst_parse_launch()
函数把一个文本表达的pipeline转变为一个实际的pipeline,这个函数十分方便。你需要构建的pipeline是由一个叫做playbin的元素组成,playbin是一个特殊的元素,它可以作为一个源和一个sink,它是一个完整的pipeline。在这个例子中,我们只给playbin传递了一个参数,这个参数是我们想要播放的媒体的URI。试试改变它吧!不论它是一个http://
或者file://
的URI,playbin都会透明的实例化一个适当的GStreamer源。 -
开始播放
gst_element_set_state (pipeline, GST_STATE_PLAYING);
这行代码展示了另一个有趣的概念:状态。每一个GStreamer元素都有一个关联的状态,你可以大致理解为你的DVD播放器上的播放/暂停按钮。播放将不会开始,除非你把管道设置为播放状态。在这行代码中,
gst_element_set_state()
将管道设置为播放状态,从而启动播放。 -
等待错误或EOS
bus = gst_element_get_bus (pipeline); msg = gst_bus_timed_pop_filtered (bus, GST_CLOCK_TIME_NONE, GST_MESSAGE_ERROR | GST_MESSAGE_EOS);
这些代码行将会一直等待,直到出现一个错误或者找到流的结束。
gst_element_get_bus()
获取管道的总线,而gst_bus_timed_pop_filtered()
则会阻塞,直到你通过这个总线接收到一个错误或者EOS(流结束)。
三、开启更多日志
在运行 Gstreamer 程序时开启更多日志可以帮助我们排查错误。
# | Name | Description |
---|---|---|
0 | none | 不输出任何信息 |
1 | ERROR | 打印致命错误信息,正确的错误处理可以使得程序还能正常运行 |
2 | WARNING | 打印警告信息,程序可能出现预期外的现象 |
3 | FIXME | 打印“fixme”信息,通常意味着程序触发了一个已知不完整的代码路径,程序大多数情况下可能工作正常,但在特定情况下可能会引发问题 |
4 | INFO | 打印消息类信息,通常用于报告系统中只发生一次的事件,或者是重要且罕见的事件 |
5 | DEBUG | 打印所有的调试信息,包括参数更改,加载,卸载等事件发生 |
6 | LOG | 打印所有日志消息,包含大量重复发生的事件信息 |
7 | TRACE | 打印所有跟踪信息,包括每次修改GstMiniObject(如GstBuffer或GstEvent)的引 用计数等信息 |
9 | MEMDUMP | 记录所有内存转储消息。这是最繁重的日志记录,可能包括转储内存块的内容 |
在运行时,通过设置环境变量 GST_DEBUG 即可。例如 export GST_DEBUG=2
意味着打印 WARNING 和 ERROR 信息
参考
- my_examples
- Basic Tutorial 1 Hello world
- GStreamer基础教程之调试工具
- GStreamer基础教程13 - 调试Pipeline
[GStreamer]:https://gstreamer.freedesktop.org/