Nothing better to get a first impression about a software library than to print “Hello World” on the screen! 没有什么比在屏幕上打印“Hello World”更好的对软件库的第一印象了!
But since we are dealing with multimedia frameworks, we are going to play a video instead. 但是由于我们正在处理多媒体框架,因此我们将播放视频。
Do not be scared by the amount of code below: there are only 4 lines which do real work. The rest is cleanup code, and, in C, this is always a bit verbose. 不要被下面的代码量吓到:只有 4 行可以完成实际工作。其余的都是清理代码,在 C 中,这总是有点冗长。
Without further ado, get ready for your first GStreamer application... 事不宜迟,为您的第一个 GStreamer 应用做好准备......
Copy this code into a text file named basic-tutorial-1.c
(or find it in your GStreamer installation). 将此代码复制到名为的文本 basic-tutorial-1.c
文件中(或在 GStreamer 安装中找到它)。
#include
#ifdef __APPLE__
#include
#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_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;
}
int
main (int argc, char *argv[])
{
#if defined(__APPLE__) && TARGET_OS_MAC && !TARGET_OS_IPHONE
return gst_macos_main (tutorial_main, argc, argv, NULL);
#else
return tutorial_main (argc, argv);
#endif
}
Compile it as described in Installing on Linux, Installing on Mac OS X or Installing on Windows. If you get compilation errors, double-check the instructions given in those sections.
按照在 Linux 上安装、在 Mac OS X 上安装或在 Windows 上安装中所述进行编译。如果出现编译错误,请仔细检查这些部分中给出的说明。
If everything built fine, fire up the executable! You should see a window pop up, containing a video being played straight from the Internet, along with audio. Congratulations! 如果一切正常,请启动可执行文件!您应该会看到一个弹出窗口,其中包含直接从 Internet 播放的视频以及音频。祝贺!
Need help? 需要帮助吗?
If you need help to compile this code, refer to the Building the tutorials section for your platform: Linux, Mac OS X or Windows, or use this specific command on Linux: 如果您需要有关编译此代码的帮助,请参阅为您的平台构建教程部分:Linux、Mac OS X 或 Windows,或在 Linux 上使用此特定命令:
gcc basic-tutorial-1.c -o basic-tutorial-1
pkg-config --cflags --libs gstreamer-1.0``If you need help to run this code, refer to the Running the tutorials section for your platform: Linux, Mac OS X or Windows. 如果您需要有关运行此代码的帮助,请参阅运行适用于您的平台的教程部分:Linux、Mac OS X 或 Windows。
Required libraries:
gstreamer-1.0
所需库:gstreamer-1.0
This tutorial opens a window and displays a movie, with accompanying audio. The media is fetched from the Internet, so the window might take a few seconds to appear, depending on your connection speed. Also, there is no latency management (buffering), so on slow connections, the movie might stop after a few seconds. See how Basic tutorial 12: Streaming solves this issue.
本教程将打开一个窗口并显示电影,并附带音频。媒体是从互联网上获取的,因此窗口可能需要几秒钟才能显示,具体取决于您的连接速度。此外,没有延迟管理(缓冲),因此在连接速度较慢的情况下,电影可能会在几秒钟后停止。了解基本教程 12:流式处理如何解决此问题。
Let's review these lines of code and see what they do: 让我们回顾一下这些代码行,看看它们的作用:
/* Initialize GStreamer */ gst_init (&argc, &argv);
This must always be your first GStreamer command. Among other things, gst_init():
这必须始终是您的第一个 GStreamer 命令gst_init():
Initializes all internal structures 初始化所有内部结构
Checks what plug-ins are available 检查哪些插件可用
Executes any command-line option intended for GStreamer 执行任何用于 GStreamer 的命令行选项
If you always pass your command-line parameters argc
and argv
to gst_init() your application will automatically benefit from the GStreamer standard command-line options (more on this in Basic tutorial 10: GStreamer tools)
如果您始终传递命令行参数 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);
This line is the heart of this tutorial, and exemplifies two key points: gst_parse_launch() and playbin. 这一行是本教程的核心,并举例说明了两个关键点:gst_parse_launch() 和 playbin。
GStreamer is a framework designed to handle multimedia flows. Media travels from the “source” elements (the producers), down to the “sink” elements (the consumers), passing through a series of intermediate elements performing all kinds of tasks. The set of all the interconnected elements is called a “pipeline”.
GStreamer是一个旨在处理多媒体流的框架。媒体从“源”元素(生产者)向下传播到“接收器”元素(消费者),通过一系列执行各种任务的中间元素。所有互连元素的集合称为“管道”。
In GStreamer you usually build the pipeline by manually assembling the individual elements, but, when the pipeline is easy enough, and you do not need any advanced features, you can take the shortcut: gst_parse_launch().
在 GStreamer 中,您通常通过手动组装各个元素来构建管道,但是,当管道足够简单并且您不需要任何高级功能时,您可以使用快捷方式:gst_parse_launch()。
This function takes a textual representation of a pipeline and turns it into an actual pipeline, which is very handy. In fact, this function is so handy there is a tool built completely around it which you will get very acquainted with (see Basic tutorial 10: GStreamer tools to learn about gst-launch-1.0 and the gst-launch-1.0 syntax).
此函数采用管道的文本表示形式,并将其转换为实际管道,非常方便。事实上,这个函数非常方便,有一个完全围绕它构建的工具,你会非常熟悉(请参阅基本教程 10:GStreamer 工具以了解 gst-launch-1.0 和 gst-launch-1.0 语法)。
So, what kind of pipeline are we asking gst_parse_launch() to build for us? Here enters the second key point: We are building a pipeline composed of a single element called playbin.
那么,我们要求gst_parse_launch()为我们构建什么样的管道呢?这里进入第二个关键点:我们正在构建一个由称为 playbin 的单个元素组成的管道。
playbin is a special element which acts as a source and as a sink, and is a whole pipeline. Internally, it creates and connects all the necessary elements to play your media, so you do not have to worry about it.
Playbin是一种特殊的元素,它充当源和接收器,并且是一个完整的管道。在内部,它会创建并连接播放媒体所需的所有元素,因此您不必担心。
It does not allow the control granularity that a manual pipeline does, but, still, it permits enough customization to suffice for a wide range of applications. Including this tutorial.
它不允许手动管道那样的控制粒度,但它仍然允许足够的自定义,足以满足广泛的应用程序。包括本教程。
In this example, we are only passing one parameter to playbin, which is the URI of the media we want to play. Try changing it to something else! Whether it is an http://
or file://
URI, playbin will instantiate the appropriate GStreamer source transparently!
在此示例中,我们只将一个参数传递给 playbin,即我们要播放的媒体的 URI。尝试将其更改为其他内容!无论是http:// 或者 file://URI,playbin 都会透明地实例化相应的 GStreamer 源!
If you mistype the URI, or the file does not exist, or you are missing a plug-in, GStreamer provides several notification mechanisms, but the only thing we are doing in this example is exiting on error, so do not expect much feedback.
如果您键入了错误的 URI,或者文件不存在,或者您缺少插件,GStreamer 提供了几种通知机制,但我们在本例中唯一要做的就是在出错时退出,因此不要期望太多反馈。
/* Start playing */ gst_element_set_state (pipeline, GST_STATE_PLAYING);
This line highlights another interesting concept: the state. Every GStreamer element has an associated state, which you can more or less think of as the Play/Pause button in your regular DVD player. For now, suffice to say that playback will not start unless you set the pipeline to the PLAYING
state.
这行代码突出了另一个有趣的概念:状态。每个 GStreamer 元素都有一个关联的状态,您或多或少可以将其视为常规 DVD 播放器中的“播放/暂停”按钮。现在,只要说播放不会开始就足够了,除非您将管道设置为状态 PLAYING
。
In this line, gst_element_set_state() is setting pipeline
(our only element, remember) to the PLAYING
state, thus initiating playback.
在这行代码中,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);
These lines will wait until an error occurs or the end of the stream is found. gst_element_get_bus() retrieves the pipeline's bus, and gst_bus_timed_pop_filtered() will block until you receive either an ERROR or an EOS
(End-Of-Stream) through that bus. Do not worry much about this line, the GStreamer bus is explained in Basic tutorial 2: GStreamer concepts.
这些行将等待,直到发生错误或找到流的末尾。gst_element_get_bus() 检索管道的总线,gst_bus_timed_pop_filtered() 将阻塞,直到您通过该总线收到错误或 EOS
(流结束)。不用太担心这条线,GStreamer总线在基本教程2:GStreamer概念中有解释。
And that's it! From this point onwards, GStreamer takes care of everything. Execution will end when the media reaches its end (EOS) or an error is encountered (try closing the video window, or unplugging the network cable). The application can always be stopped by pressing control-C in the console.
就是这样!从这一点开始,GStreamer会照顾一切。当媒体到达其末端 (EOS) 或遇到错误(尝试关闭视频窗口或拔下网线)时,执行将结束。始终可以通过在控制台中按 control-C 来停止应用程序。
Before terminating the application, though, there is a couple of things we need to do to tidy up correctly after ourselves.
但是,在终止应用程序之前,我们需要做几件事来正确整理自己。
/* Free resources */ gst_message_unref (msg); gst_object_unref (bus); gst_element_set_state (pipeline, GST_STATE_NULL); gst_object_unref (pipeline); return 0;
Always read the documentation of the functions you use, to know if you should free the objects they return after using them.
始终阅读您使用的函数的文档,以了解在使用后是否应该释放返回的对象。
In this case, gst_bus_timed_pop_filtered() returned a message which needs to be freed with gst_message_unref() (more about messages in Basic tutorial 2: GStreamer concepts).
在这种情况下,gst_bus_timed_pop_filtered() 返回了一个需要使用 gst_message_unref() 释放的消息对象(有关消息的更多信息,请参阅基本教程 2:GStreamer 概念)。
gst_element_get_bus() added a reference to the bus that must be freed with gst_object_unref(). Setting the pipeline to the NULL state will make sure it frees any resources it has allocated (More about states in Basic tutorial 3: Dynamic pipelines). Finally, unreferencing the pipeline will destroy it, and all its contents.
gst_element_get_bus() 添加了对必须使用 gst_object_unref() 释放的总线的引用。将管道设置为 NULL 状态将确保它释放已分配的任何资源(有关状态的详细信息,请参阅基本教程 3:动态管道)。最后,取消引用管道将销毁它及其所有内容。
And so ends your first tutorial with GStreamer. We hope its brevity serves as an example of how powerful this framework is!
到此结束了你与GStreamer的第一个教程。我们希望它的简洁性可以作为一个例子来说明这个框架有多强大!
Let's recap a bit. Today we have learned: 让我们回顾一下。今天我们了解到:
How to initialize GStreamer using gst_init(). 如何使用 gst_init() 初始化 GStreamer。
How to quickly build a pipeline from a textual description using gst_parse_launch(). 如何使用 gst_parse_launch() 从文本描述快速构建管道。
How to create an automatic playback pipeline using playbin. 如何使用播放宾创建自动播放管道。
How to signal GStreamer to start playback using gst_element_set_state(). 如何使用 gst_element_set_state() 向 GStreamer发出信号以开始播放。
How to sit back and relax, while GStreamer takes care of everything, using gst_element_get_bus() and gst_bus_timed_pop_filtered(). 如何坐下来放松,而GStreamer使用gst_element_get_bus()和gst_bus_timed_pop_filtered()处理一切。
The next tutorial will keep introducing more basic GStreamer elements, and show you how to build a pipeline manually.
下一教程将继续介绍更多基本的 GStreamer 元素,并向您展示如何手动构建管道。
It has been a pleasure having you here, and see you soon! 很高兴您来到这里,回头见!