"); //-->
在之前的多媒体框架介绍中,我们由基本属性,工具使用介绍了多媒体处理的整体框架,在下文中我们将对多媒体的应用程序来基于Gst做一个详细的介绍。
媒体格式和pad的capabilities
• Pads允许信息进入或者离开一个element,这个Capabilities(或者简单地叫做
Caps)就是指定哪些信息可以通过Pad来传输。例如:“RGB视频,尺寸为320x200并且每秒30帧”或者“16位的音频采样, 5.1声道,每秒采样44.1k”甚至可以是类似于mp3/h264之类的压缩格式。
• Pads支持多重Capabilities(比如,一个视频的sink可以支持RGB输出或者YUV输出), Capabilities可以指定一个范围而不必须是一个特定值(比如,一个音频sink可以支持从1~48000的采样率)。 然而,数据从一个pad流向另一个pad的时候,必须是一个双方都能支持的格式。某一种数据形式是两个pad都能支持的,这样Pads的Capabilities就固定下来(只有一个钟个数,并且不再是一个数据区间了), 这个过程被称为协商。
• 为了两个element可以连接,他们必须有一个共同的Capabilities子集(否则它们肯定不能互相连接)。 这就是Capabilities存在的主要目的。作为一个应用开发者,我们通常都是用连接一个个element的方法来建立pipeline的。在这里,你需要了解你使用的element的Pad的Caps。
• Pad模板
Pad是由Pad模板创建的,模板里面会列出一个Pad所有可能的Capabilities。模板对于创建几个相似的Pad是很有帮助的,但也会比较早就判断出两个element是否可以相连:如果连两个Pad的模板都不具备共同的子集的化,就没必要进行更深层的协商了。Pad模板检查是协商流程的第一步。随着流程的逐步深入, Pad会正式初始化,也会确定他们的Capability(除非协商失败了)。
• 如右图所示:这是一个element的永久sink pad。它支持2种媒体格式,都是音频的原始数据(audio/x-raw-int),16位的符号数和8位的无符号数。方括号表示一个范围,例如,频道(channels)的范围是1到2。
• 再看右边的source pad。 video/x-raw-yuv表示这个sourcepad用YUV格式输出视频。它支持一个很广的维数和帧率,一系列的YUV格式(用花括号列出了)。
多线程
• GStreamer 是一个支持多线程的框架,而且是绝对安全的线程。
• 什么情况下你想强加一个线程?强加线程有好几个优点。但是,
基于性能的考虑,你从不希望每个元件占用一个线程,因为这样会产生一些额外的开销。下面列出了一些情形使用线程将会非常有用:
• 数据缓冲,比如在处理网络数据流或者像视频卡或音频卡那样记录在线直播的数据流。
• 同步输出设备,比如播放一段混合了视频和音频的流,使用双线程输出的话,音频流和视频流就可以独立的运行并达到更好的同步效果。
从图上看, queue会创建一个新的线程,所以整个pipeline有3个线程在运行。通常来说,有多于一个的sink element时就需要使用多个线程。这是因为在同步时, sink通常是阻塞起来等待所有其他的sink都准备好,如果仅仅只有一个线程是无法做到这一点的。
Queue元件
• 之前,我们多次ᨀ到了“queue”队列元件,队列是一个线程边界元件,你可以通过标准的ᨀ供者/接收者模型用来强制线程。
• 队列可以看作是一种使线程间数据容量线程安全的方法,同时也可以当作一种缓冲区, GObject 队列具有的一些特殊属性,比如,你可以设置元件的阀值上下限,如果数据低于阀值的下限(默认) :断开线程 ,输出将会被禁止;如果数据高于上限,输入将会被禁止或者数据将被丢弃(预先设置)
Request pads
• 经典的例子就是tee element——有1个输入pad而没有输出pad,需要有申请, tee element才会生成。通过这种方法,输入流可以被复制成多份。和Always Pad比起来, Request Pad因为并非一直存在,所以是不能自连接element的。
我们要建立一个如下图所示的pipeline
步骤:
1)初始化Gstreamer;
2)创建上图中所有的元件;
3)创建pipeline;
4)配置元件;
5)将元件添加进pipeline中,然后将可以链接起来的元件链接起来;
(1. app sourcetee 2. audio_queueaudio_convert audio_resample audio_sink
3. video_queue wave_scope video_convert video_sink)
6)手工链接teeaudio_queue和tee video_queue;
7)设置pipeline状态为PLAYING;
8)监测BUS信号即可。
核心代码如下:
/* Initialize GStreamer */ gst_init (&argc, &argv); /* Create the elements */ audio_source = gst_element_factory_make ("audiotestsrc", "audio_source"); tee = gst_element_factory_make ("tee", "tee"); audio_queue = gst_element_factory_make ("queue", "audio_queue"); audio_convert = gst_element_factory_make ("audioconvert", "audio_convert"); audio_resample = gst_element_factory_make ("audioresample", "audio_resample"); audio_sink = gst_element_factory_make ("autoaudiosink", "audio_sink"); video_queue = gst_element_factory_make ("queue", "video_queue"); visual = gst_element_factory_make ("wavescope", "visual"); video_convert = gst_element_factory_make ("ffmpegcolorspace", "csp"); video_sink = gst_element_factory_make ("autovideosink", "video_sink"); /* Create the empty pipeline */ pipeline = gst_pipeline_new ("test-pipeline"); /* Configure elements */ g_object_set (audio_source, "freq", 215.0f, NULL); g_object_set (visual, "shader", 0, "style", 3, NULL); /* Link all elements that can be automatically linked because they have "Always" pads */ gst_bin_add_many (GST_BIN (pipeline), audio_source, tee, audio_queue, audio_convert, audio_resample, audio_sink, video_queue, visual, video_convert, video_sink, NULL); gst_element_link_many (audio_source, tee, NULL) gst_element_link_many (audio_queue, audio_convert, audio_resample, audio_sink, NULL) gst_element_link_many (video_queue, visual, video_convert, video_sink, NULL) /* Manually link the Tee, which has "Request" pads */ tee_src_pad_template = gst_element_class_get_pad_template (GST_ELEMENT_GET_CLASS (tee), "src%d"); tee_audio_pad = gst_element_request_pad (tee, tee_src_pad_template, NULL, NULL); queue_audio_pad = gst_element_get_static_pad (audio_queue, "sink"); tee_video_pad = gst_element_request_pad (tee, tee_src_pad_template, NULL, NULL); queue_video_pad = gst_element_get_static_pad (video_queue, "sink"); gst_pad_link (tee_audio_pad, queue_audio_pad) gst_pad_link (tee_video_pad, queue_video_pad) /* Start playing the pipeline */ gst_element_set_state (pipeline, GST_STATE_PLAYING);
关于应用程序的编写篇的介绍,我们预计分为2个部分来阐述,在下一篇中,我们将对组件和文件等进行讨论。
*博客内容为网友个人发布,仅代表博主个人观点,如有侵权请联系工作人员删除。