GStreamer 初探 (三)
这里是之前概述计划里介绍Gstreamer基本概念的第二部分,这次的初探三会将Gstreamer需要用到的剩余基本概念做一个讲解,最主要涉及的是不再在最初就将整个管道创建完成,取而代之的是在数据流可以使用时“动态”的创建管道来进行处理
这次教程结束之后,我们将获得打开GStreamer进阶内容的钥匙,当然,这需要我们在这次教程后,找到这些知识点的答案:1.在连接elements之后如何对其进行更好的控制,2.如何获取关注事件的消息以便及时做出回应,2.element都可能处于哪些不同的states
简介
本次教程我们将看到,在我们设置pipeline的状态为 play 之后,我们的 pipeline 居然还没有完整的构建出来,这怎么可以呢?假使我们的pipeline没有构建完成,数据流向pipeline后定然会出现错误然后停止下来,那有没有可能在设置state后采取行动进一步对pipeline进行操作呢?
在这次的例子里我们会使用一个既有音频数据也有视频数据的数据流,数据流被存放在container,而我们使用demuxer来处理具有多路数据的container,这些数据格式常见的有mkv、mov、ogg、asf、wmv、wma,demuxer会将container中的多路数据分流,根据不同类型分别开的数据流向不同的src,element 之间通过pads(GstPad)进行通信,数据通过sink pad流入一个element,通过source pad从element中流出,很自然的之前用到的source element会只包含source pad,sink element 只包含sink pad,而filter element 两种pad都会包含
然后,刚刚get到的demuxer会包含多个source pad
为了更完整的去理解这些,我们假定构建了这样一个管道,这并不是本次代码所要展示的,仅供理解,demuxer将数据流分成两支,一支用来处理音频数据,一支用来处理视频数据
demuxer的复杂性在于其在最初的时候是没有source pad给其他element连接的,它只有在查看到container里的都有哪些复用数据时才能构建自己的source pad并产生通知消息,所以一个pipeline必然会在它们这里终止,解决的办法是照常构建一个从source element到demuxer的pipeline,然后将pipeline的state设置为play,demuxer获取到container里复用数据的类别后开始创建它的source pad,恰恰这个时候我们完成构建新的pipeline然后将它连接在demuxer创建的pads上
简单起见,本次代码我们仅仅再次构建音频数据流的pipeline而省略了视频数据流的pipeline构建
basic-tutorial-3.c
#include <gst/gst.h>
/* Structure to contain all our information, so we can pass it to callbacks */
typedef struct _CustomData {
GstElement *pipeline;
GstElement *source;
GstElement *convert;
GstElement *resample;
GstElement *sink;
} CustomData;
/* Handler for the pad-added signal */
static void pad_added_handler (GstElement *src, GstPad *pad, CustomData *data);
int main(int argc, char *argv[]) {
CustomData data;
GstBus *bus;
GstMessage *msg;
GstStateChangeReturn ret;
gboolean terminate = FALSE;
/* Initialize GStreamer */
gst_init (&argc, &argv);
/* Create the elements */
data.source = gst_element_factory_make ("uridecodebin", "source");
data.convert = gst_element_factory_make ("audioconvert", "convert");
data.resample = gst_element_factory_make ("audioresample", "resample");
data.sink = gst_element_factory_make ("autoaudiosink", "sink");
/* Create the empty pipeline */
data.pipeline = gst_pipeline_new ("test-pipeline");
if (!data.pipeline || !data.source || !data.convert || !data.resample || !data.sink) {
g_printerr ("Not all elements could be created.\n");
return -1;
}
/* Build the pipeline. Note that we are NOT linking the source at this
* point. We will do it later. */
gst_bin_add_many (GST_BIN (data.pipeline), data.source, data.co