基础教程 1:Hello world!
目的
我们学一个软件库,都是先写一个“Hello World”,但由于我们处理的是多媒体框架,所以我们将播放一段视频。
下面的代码看起来很长,但是只有4行代码真正起到了作用。下面是第一个GStreamer应用程序:
Hello world
复制这段代码到名为basic-tutorial-1.c的文件(或是在GStreamer installation中找到它)
#include <gst/gst.h>
#ifdef __APPLE__
#include <TargetConditionals.h>
#endif
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 */
gst_message_unref (msg);
gst_object_unref (bus);
gst_element_set_state (pipeline, GST_STATE_NULL);
gst_object_unref (pipeline);
return 0;
}
int
main (int argc, char *argv[])
{
#if defined(__APPLE__) && TARGET_OS_MAC && !TARGET_OS_IPHONE
return gst_macos_main ((GstMainFunc) tutorial_main, argc, argv, NULL);
#else
return tutorial_main (argc, argv);
#endif
}
按照在Linux上安装、在Mac OS X上安装或在Windows上安装中所述进行编译。如果你编写错误,仔细检查这部分给出的说明。
如果一切顺利,启动可执行文件!你应该会看到一个窗口弹出,包括一个直接在网上播放的视频,以及音频!
需要帮助?
如果你编写程序需要帮助,参考你平台的构建教程 部分:Linux, Mac OS X or Windows,或者在Linux上使用此特定命令:
gcc basic-tutorial-1.c -o basic-tutorial-1 `pkg-config --cflags --libs gstreamer-1.0`
如果你运行程序需要帮助,参考你平台的运行教程 部分:
Linux, Mac OS X or Windows.
Required libraries: gstreamer-1.0
本教程将打开一个窗口并显示一段有声音的影片。视频是从互联网上获取的,因此窗口可能会需要几秒才会出现,具体取决于你的连接速度。此外,没有延时管理(缓冲),所以网速慢的话,影片可能几秒后停止。 了解基本教程12:流如何解决此问题。
演练
让我们复习一下这几行代码并理解它们:
/* Initialize GStreamer */
gst_init (&argc, &argv);
这必须始终是您的第一个GStreamer命令。其中, gst_init():
- 初始化所有内部结构
- 检查哪些插件可用
- 执行对GStreamer的任何命令行选项
如果您总是将命令行参数argc和argv传递给gst_init(),您的应用程序将自动受益于GStreamer标准命令行选项(在基础教程10:GStreamer工具中对此有更多介绍)
/* Build the pipeline */
pipeline =
gst_parse_launch
("playbin uri=https://gstreamer.freedesktop.org/data/media/sintel_trailer-480p.webm",
NULL);
这行是本教程的核心,并举例说明了两个关键点:gst_parse_Launch()和playbin。
gst_parse_launch
GStreamer是一个设计用于处理多媒体流的框架。媒体从“源”元素(生产者),一直到“汇”元素(消费者),通过一系列执行各种任务的中间元素。所有相互连接的元素的集合被称为“管道”。
在GStreamer中,你通常通过手动组装各个元素来构建管道,但当管道够简单并且不需要任何高级功能时,你可以采用快捷方式:gst_parse_Launch()。
此函数采用管道的文本表示形式,并将其转换为实际的管道,这非常方便。事实上,这个函数非常方便,有一个完全围绕它构建的你将会非常熟悉的工具。(请参阅基础教程10:GStreamer工具以了解gst-Launch-1.0和gst-Launch-1.0语法)。
playbin
那么,我们询问的gst_parse_Launch()能为我们构建什么样的管道呢?这里进入第二个关键点:我们正在构建一个由名为playbin的单个元素组成的管道。
Playbin是一种特殊元素,既是源又是汇,是一条完整的管道。在内部,它创建并连接播放您的媒体所需的所有元素,因此你不必担心。
它不允许手动管道所做的控制粒度,但仍然允许足够的定制,以满足广泛的应用程序。包括本教程。
在本例中,我们只向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()将阻塞,直到你通过该总线接收到错误或EOS(流结束)。不要太担心这一行,GStreamer总线在基础教程2:GStreamer概念中有解释。
就是这样!从现在开始,GStreamer负责一切。当介质到达末端(EOS)或遇到错误(尝试关闭视频窗口或拔下网线)时,执行将结束。应用程序总是可以通过在控制台中按Ctrl-C来停止。
清理
不过,在终止应用程序之前,我们需要做几件事来正确整理自己的应用程序。
/* Free resources */
gst_message_unref (msg);
gst_object_unref (bus);
gst_element_set_state (pipeline, GST_STATE_NULL);
gst_object_unref (pipeline);
return 0;
始终阅读你使用的函数的文档,以了解你是否应该释放它们在使用后返回的对象。
在本例中,gst_bus_timed_pop_filtered()返回一条消息,需要用 gst_message_unref()释放(有关消息的更多信息,请参阅基础教程2:GStreamer概念)。
gst_element_get_bus()添加了对必须使用gst_object_unref()释放的总线的引用。
将管道设置为空状态将确保它释放已分配的所有资源(有关状态的更多信息,请参阅基础教程3:动态管道)。最后,取消引用管道将销毁它及其所有内容。
总结
关于GStreamer的第一个教程到此结束。我们希望它的简洁性可以作为一个例子,说明这个框架是多么强大!
让我们来回顾一下。今天我们了解到:
- 如何使用gst_init()初始化GStreamer。
- 如何使用gst_parse_Launch()从文本描述快速构建管道。
- 如何使用Playbin创建自动播放管道。
- 如何使用gst_element_set_state()通知GStreamer开始播放。
- 如何休息和放松,而GStreamer使用gst_element_get_bus()和gst_bus_timed_pop_filtered()处理所有事情。
下一篇教程将继续介绍更多基本的GStreamer元素,并向你展示如何手动构建管道。很高兴你能来到这里,再见!