GStreamer Tutorial 1中文翻译
文章目录
前言
由于工作原因,用的GStreamer的图像解码库,所以记录GStreamer Tutorial 的中文翻译和个人的理解以便学习。若有不足请多指教。侵删。
Basic tutorial 1: Hello world!
目的
没有什么比在屏幕上打印 "Hello World "更能让人对一个软件库产生第一印象的了!但由于我们要处理的是多媒体框架,所以我们要播放一段视频。
不要被下面的代码量所吓倒:只有4行是真正工作的。其余的是清理代码,而在C语言中,这总是有点冗长。
不多说了,准备好你的第一个GStreamer应用程序吧…
Hello world
将代码复制到basic-tutorial-1.c
中,或在你的GStreamer路径中找到它。
basic-tutorial-1.c
#include <gst/gst.h>
int
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://www.freedesktop.org/software/gstreamer-sdk/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_error ("An error occurred! Re-run with the GST_DEBUG=*:WARN environment "
"variable set for more details.");
}
/* Free resources */
gst_message_unref (msg);
gst_object_unref (bus);
gst_element_set_state (pipeline, GST_STATE_NULL);
gst_object_unref (pipeline);
return 0;
}
本教程打开一个窗口,显示一部电影,并伴有音频。媒体是从互联网上获取的,所以窗口可能需要几秒钟才能出现,这取决于你的连接速度。此外,没有延迟管理(缓冲),所以在慢速连接上,电影可能会在几秒钟后停止。请看基础教程12:流媒体如何解决这个问题。
代码走读
让我们回顾一下这几行代码,看看它们做了什么:
/* Initialize GStreamer */
gst_init (&argc, &argv);
这必须始终是你的第一个GStreamer命令。相比于其他,gst_init()
:
- 初始化所有的内部结构;
- 检查哪些插件是可用的;
- 执行任何用于GStreamer的命令行选项。
如果你总是把你的命令行参数argc和argv传给gst_init()
,你的应用程序将自动受益于GStreamer的标准命令行选项(更多内容见基础教程10:GStreamer工具)。
pipeline =
gst_parse_launch
("playbin uri=https://www.freedesktop.org/software/gstreamer-sdk/data/media/sintel_trailer-480p.webm",
NULL);
这一行是本教程的核心,体现了两个关键点:gst_parse_launch()
和playbin
。
gst_parse_launch
GStreamer是一个框架,旨在处理多媒体流。媒体从 "源 "(source)元素(生产者)到 "汇 "(sink)元素(消费者),要经过一系列的中间元素,执行各种任务。所有相互连接的元素的集合被称为 “管道”(pipeline)。
在GStreamer中,你通常通过手动组装各个元素来建立管道,但是,当管道足够简单,并且你不需要任何高级功能时,你可以采取捷径:gst_parse_launch()
。
这个函数把一个管道的文本表示法变成一个实际的管道,这非常方便。事实上,这个函数非常方便,有一个完全围绕它建立的工具,你会非常熟悉(见基础教程10:GStreamer工具,了解gst-launch-1.0和gst-launch-1.0的语法)。
playbin
那么,我们要求gst_parse_launch()
为我们建立什么样的管道?这里进入了第二个关键点。我们正在建立一个由名为playbin
的单一元素组成的管道。
playbin是一个特殊的元素,它作为一个source
和一个sink
,是一个完整的管道。在内部,它创建并连接所有必要的元素来播放你的媒体,所以你不必担心。
它不允许像手动管道那样的控制精度,但是,它仍然允许足够的定制,足以满足广泛的应用。包括本教程。
在这个例子中,我们只向playbin传递一个参数,即我们要播放的媒体的URI。试着把它改成别的东西吧 无论它是http:// 还是file:// URI,playbin都会透明地实例化适当的GStreamer源!
如果你打错了URI,或者文件不存在,或者你缺少一个插件,GStreamer提供了几种通知机制,但是我们在这个例子中唯一要做的就是在出错时退出,所以不要指望有什么反馈。
/* Start playing */
gst_element_set_state (pipeline, GST_STATE_PLAYING);
这一行强调了另一个有趣的概念:状态。每个GStreamer元素都有一个相关的状态,你或多或少可以把它看作是普通DVD播放器中的播放/暂停按钮。现在,我们只需要说,除非你把管道设置为播放状态,否则播放将不会开始。
在这一行中,gst_element_set_state()
正在将管道(我们唯一的元素,记得)设置为播放状态,从而开始播放。
/* 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);
gst_element_get_bus()
检索管道的总线,gst_bus_timed_pop_filtered()
将阻塞,直到你通过该总线收到ERROR
或EOS(End-Of-Stream)
。不要太担心这一行,GStreamer总线在基础教程2:GStreamer概念中已经解释了。
就这样了! 从这一点开始,GStreamer会照顾到一切。当媒体到达终点(EOS)或遇到错误(尝试关闭视频窗口,或拔掉网线)时,执行将结束。应用程序总是可以通过在控制台中按下control-C来停止。
清理工作
不过,在终止应用程序之前,我们需要做几件事情来正确地清理程序。
/* See next tutorial for proper error message handling/parsing */
if (GST_MESSAGE_TYPE (msg) == GST_MESSAGE_ERROR) {
g_error ("An error occurred! Re-run with the GST_DEBUG=*:WARN environment "
"variable set for more details.");
}
始终阅读你所使用的函数的文档,以了解你在使用这些函数后是否应该释放它们所返回的对象。
在示例中,gst_bus_timed_pop_filtered()
返回了一个消息,需要用gst_message_unref()
来释放(更多关于消息的内容请看基础教程2:GStreamer概念)。
gst_element_get_bus()
添加了一个对总线的引用,必须用gst_object_unref()
释放。将管道设置为NULL
状态将确保它释放它所分配的任何资源(更多关于状态的内容见基础教程3:动态管道)。最后,取消引用管道将销毁它和它的所有内容。
结论
这个例程展示了:
- 如何使用
gst_init()
来初始化GStreamer; - 如何使用
gst_parse_launch()
从文本描述中快速建立一个管道; - 如何使用playbin创建一个自动播放管道;
- 如何使用
gst_element_set_state()
向GStreamer发出开始播放的信号; - 如何坐下来放松,而GStreamer使用
gst_element_get_bus()
和gst_bus_timed_pop_filtered()
来照顾一切。
下一个教程将继续介绍更多基本的GStreamer元素,并告诉你如何手动建立一个管道。
PS:有没有发现你一直在播放视频,主程序主要被 gst_bus_timed_pop_filtered()阻塞住了,而不是想象中的无限循环,等待某个参数FALSE后退出。