GStreamer官方教程系列
Basic tutorial 1: Hello world!
原文:https://gstreamer.freedesktop.org/documentation/tutorials/basic/hello-world.html?gi-language=c
目标
这个教程将会利用GStreamer播放一个视频。
Hello world
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);
/* Free resources */
if (msg != NULL)
gst_message_unref (msg);
gst_object_unref (bus);
gst_element_set_state (pipeline, GST_STATE_NULL);
gst_object_unref (pipeline);
return 0;
}
Linux平台编译命令:gcc basic-tutorial-1.c -o basic-tutorial-1 `pkg-config --cflags --libs gstreamer-1.0`
讲解
回顾代码:
/* Initialize GStreamer */
gst_init (&argc, &argv);
这必须是GStreamer的第一行命令。除开其他, gst_init():
- 初始化所有内部结构
- 检查可用的插件
- 执行任何用于GStreamer的命令行选项
如果你总是传递命令行参数argc和argv给 gst_init() ,应用会自动受益于GStreamer标准命令行选项(在Basic tutorial 10: GStreamer tools中有更多关于此的内容)。
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是一种设计来用于处理多媒体数据流的框架。媒体数据从“源”元件(制造者)流向“槽”元件(消费者),经过一系列执行各种任务的中间元件。联通的所有元件的集合就是所谓的“管道”。
在GStreamer中,通常以手动组合单个的元件来构造管道,但是,当管道比较简单并且不需要任何高阶特性的时候,可以走捷径:gst_parse_launch()。
该函数接受一个管道的文本描述,并将其转变为真实的管道,非常方便。实际上,该函数也是一个工具的核心(转到Basic tutorial 10: GStreamer tools了解 gst-launch-1.0和gst-launch-1.0语法)。
playbin
所以,我们想让gst_parse_launch()为我们构造一个怎样的管道呢?这里就引入了第二个重点:我们构建了一个由一个叫做playbin的元件组成的管道。
playbin是一种特殊的元件,它既担当源又担当槽,是一个完整的管道。在其内部,它创建并且连接了所有必要的元件来播放媒体,这样就不需要操心其他。
它没有像手动管道一样的控制粒度,但是依旧允许足够的定制来满足很大范围的应用。包括本教程。
在本例中,我们仅传递一个参数给playbin,这个参数是我们想要播放的媒体的URI。可以将其改为其他。无论是http://或者file://类型的URI,playbin可以初始化正确的源。
如果你打错了URI,或者文件不存在,又或者缺少了一个插件,GStreamer提供了集中提示机制,但是在本例中我们唯一做的就是在遇到错误时退出,所以不要期待更多反馈。
/* Start playing */
gst_element_set_state (pipeline, GST_STATE_PLAYING);
该行强调了另一种有趣的概念:状态。每个GStreamer元件有一个关联的状态,你可以视其为DVD播放器的播放/暂停按钮。目前,足以说明播放不会开始,除非你将pipeline设置为PLAYING状态。
在这行,gst_element_set_state()将pipeline(记住,这是我们唯一的元件)设置为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);
这几行代码会等待错误或者流终点的到来。gst_element_get_bus()获取管道的总线,gst_bus_timed_pop_filtered()会阻塞主线程直到你通过总线获取了一个错误或EOS。不用担心这行,GStreamer总线会在Basic tutorial 2: GStreamer concepts中介绍。
就是这样!这样之后,GStreamer就会接管所有事。播放会在媒体结束(EOS)或者遇到错误(关闭播放界面,网线断连)时结束。应用可以在控制台按下ctrl+c来终止。
释放资源
在终止应用之前,我们需要做一些事情来正确地释放资源。
/* Free resources */
if (msg != NULL)
gst_message_unref (msg);
gst_object_unref (bus);
gst_element_set_state (pipeline, GST_STATE_NULL);
gst_object_unref (pipeline);
在使用函数之前阅读文档来了解你是否需要在使用后释放这些方法返回的对象。
在本例中,gst_bus_timed_pop_filtered() 返回了一个消息,需要用gst_object_unref()来释放这个对象。将管道设置为NULL状态可以确保管道释放了所有分配给它的资源(在Basic tutorial 3: Dynamic pipelines中了解更多)。最后,解除管道的引用计数会摧毁管道及其所有内容。
结论
这样就结束了GStreamer的第一个教程。我们新希望这简短的形式能够让你了解这个架构的功能是多么强大!
我们扼要重述一下。今天我们学到了:
- 用gst_init()来初始化GStreamer。
- 用gst_parse_launch()来从文本描述快速构建一个管道。
- 用gst_element_set_state()来通知GStreamer开始播放。
- 用gst_element_get_bus()和gst_bus_timed_pop_filtered()来接管消息处理以便自动运行。