Demo
1 |
|
效果如下图:

关键代码解析
1 | gst_init(&argc, &argv); |
gst_init用于初始化,必须在其他GStreamer接口之前被调用,不需要其处理命令行参数时可将参数赋值为NULL。
1 | GstElement *pipeline = gst_parse_launch("playbin uri=file:///root/video.mp4", NULL); |
创建了一个Pipeline,该Pipeline是Playbin类型的。
GStreamer是一个基于管道机制的多媒体库,一个典型的GStreamer程序包含了一个或多个Pipeline,每个Pipeline通过其拥有的一系列Element完成对多媒体数据的处理。同时,虽然是由C语言实现的,但GStreamer实现了自己的面向对象机制,因此其各类型间具有继承关系。
本句中涉及了两个类型,GstPipeline和playbin。
其中,GstPipeline是一个在GStreamer当中十分重要的类型,其继承关系如下所示。
1 | GObject |
GstElement是一个抽象基类,定义了Element、Pipeline等的接口,在GStreamer中该接类被广泛的用作基类。
GstBin是一个能够容纳和管理其他GstElement的类型,其能够将用户的操作分发到其管理的多个GstElement中,降低了使用复杂性。同时,GstBin还提供了对GstMessage的拦截功能。
GstPipeline通常被用作顶层的容器,其进一步的拓展了GstBin的功能,对内提供了用于多媒体数据同步的全局时钟GstClock,对外提供了统一的消息接口GstBus。
而playbin则是扩展了GstPipeline的功能,其能够通过有效的Uri获取数据并将其渲染到屏幕上。因为其功能的完整性和高度的集成化,本文不对其进行展开叙述。
gst_parse_launch则通过解析传入字符串来创建指定的GstPipeline。
1 | gst_element_set_state(pipeline, GST_STATE_PLAYING); |
gst_element_set_state用于设置GstElement的状态,该句将pipeline设为了播放状态,使得视频开始能够播放。
正如上文所说的,GstBin能对其管理的GstElement进行统一操作。实际上在该句之后pipeline中包含的所有GstElement都转变为了播放状态,这才使得多媒体数据顺利播放。
每一个GstElement都具有内部状态,通常使用的是以下几个:
1. GST_STATE_NULL:默认状态,该状态下[GstElement](https://gstreamer.freedesktop.org/documentation/gstreamer/gstelement.html?gi-language=c)不会具有任何资源。转入该状态后会释放持有的资源。
2. GST_STATE_READY:在该状态下[GstElement](https://gstreamer.freedesktop.org/documentation/gstreamer/gstelement.html?gi-language=c)将获得全部需要的资源,包括打开的设备、缓冲区等,但流还是会处于关闭状态并被置零。如果在流打开过的情况下转入该状态,将会重置流的配置和位置。
3. GST_STATE_PAUSED:在该状态下[GstElement](https://gstreamer.freedesktop.org/documentation/gstreamer/gstelement.html?gi-language=c)不仅具有GST_STATE_READY分配的全部资源,还会将流打开,使得能够对流进修改。但不会具有运行时钟,流不会随着时钟而发生变化。
4. GST_STATE_PLAYING:在该状态下[GstElement](https://gstreamer.freedesktop.org/documentation/gstreamer/gstelement.html?gi-language=c)的情况与GST_STATE_PAUSED基本相同。但是会具有运行时钟,流会自然地随时钟信号进行处理。
1 | GstBus *bus = gst_element_get_bus(pipeline); |
这两句分别用于获取消息总线和等待播放程序运行完毕。
gst_element_get_bus返回传入的GstElement对应的GstBus。
GstBus是一个能够传递GstMessage的类型。GstBus主要用于解决多线程通信的问题。在播放时,GStreamer内部可能会创建多个线程进行处理,这使得GStreamer需要一个统一的消息传递机制来降低应用程序的复杂度。
gst_bus_timed_pop_filtered则用于监听传入的GstBus,等待目标消息的返回。根据该句的传入参数,程序将会无限等待,直到有发生错误或播放完毕的消息传回。
GstMessage是GStreamer封装的消息类型。一个常用的读取程序如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
if(msg != NULL) {
GError *err;
gchar *debug_info;
switch (GST_MESSAGE_TYPE (msg)) {
case GST_MESSAGE_ERROR:
gst_message_parse_error (msg, &err, &debug_info);
g_printerr ("Error received from element %s: %s\n",
GST_OBJECT_NAME (msg->src), err->message);
g_printerr ("Debugging information: %s\n",
debug_info ? debug_info : "none");
g_clear_error (&err);
g_free (debug_info);
break;
case GST_MESSAGE_EOS:
g_print ("End-Of-Stream reached.\n");
break;
default:
/* We should not reach here because we only asked for ERRORs and EOS */
g_printerr ("Unexpected message received.\n");
break;
}
gst_message_unref (msg);
}
1 | if(msg != NULL) |
本段进行了资源释放。由于C语言没有析构函数和垃圾回收等资源管理机制,因此仍然需要进行手动管理。
GStreamer使用引用计数的方式来管理资源。通过在每个类型中放置一个引用数,并在引用数归零是才进行资源释放的方式,能够避免资源的过早释放,因此在使用GStreamer提供的API时,需要着重关注其对引用计数的影响。
gst_object_unref能够将输入的变量的引用计数减一,归零时自动释放。
与之对应的gst_object_ref能够将输入的变量的引用计数加一。