streamer

更新时间:2022-12-27 12:49:06 阅读: 评论:0


2022年12月27日发(作者:自考英语)

Tech

Gstreamer工作原理分析

Guide

HowtoMountMaemoFileSystem——Guide

Issue:<0.5>

SystemAnalysisandDesignDocumentsIssueDate:<10/29/2007>

Tech,2005

Page2of22

RevisionHistory

DateIssueDescriptionAuthor

<7/03/2008><0.5>Firstdraftwangfei

目录

CT.........................................................................................................................................................3

UCTION...............................................................................................................................................3

3.原理分析...............................................................................................................................................................3

3.1术语介绍......................................................................................................................................................3

3.1.1元素.......................................................................................................................................................3

3.1.2一些特别的元素。................................................................................................................................3

3.2插件的工作原理。.......................................................................................................................................5

3.3GST-LAUNCH的工作逻辑..................................................................................................................................7

3.4动态PIPELINE的创建原理..............................................................................................................................9

3.5DECODEBIN的工作原理..................................................................................................................................10

3.6TYPEFIND的实现原理....................................................................................................................................12

3.7SETUPELEMENT................................................................................................................................................12

3.8PLAYBIN的工作原理......................................................................................................................................14

3.9数据流动.....................................................................................................................................................16

3.10总结.........................................................................................................................................................20

NCE.....................................................................................................................................................20

HowtoMountMaemoFileSystem——Guide

Issue:<0.5>

SystemAnalysisandDesignDocumentsIssueDate:<10/29/2007>

Tech,2005

Page3of22

ct

主要讲的是gstreamer的工作原理,包括gst-launch的分析和playbin的分析,以及数据的

流动分析。

uction

先介绍一些术语,然后介绍了插件的工作原理,后面接着介绍了

gst-launch,playbin,decodebin,typefind,数据流动.

3.原理分析

3.1术语介绍.

3.1.1元素

代码里面的类型是GstElement,可以理解为gstreamer里面的基类。

3.1.2一些特别的元素。

Source:可以理解为源头,也就是数据流的起始地,就像长江的发源地是沱沱河一样。

Sink:就是这个数据流最终要流向的地方,就像长江最终要流向东海一样。

Filter:过滤器,就像是筛子一样滤掉我们不感兴趣的东西,流下我们想要的东西,或者从代码上来说

就是拦截下数据,对这个数据做一定的修改或者其它动作,当然你什么也不做也是可以的,然后再

把数据传出去:

Pipeline:典型的pipeline是这样的:

HowtoMountMaemoFileSystem——Guide

Issue:<0.5>

SystemAnalysisandDesignDocumentsIssueDate:<10/29/2007>

Tech,2005

Page4of22

更复杂一点的:

Bin:有点像pipeline,它们的区别就是pipeline肯定是一个bin,但bin不一定是pipeline,它就像一个盒

子,里面放了什么东西你可以不关心。

Ghostpad:文档上说ghostpad就像linux里面的link文件,我的理解是在一个盒子上开一个口,这样里就

可以访问这个盒子了。

HowtoMountMaemoFileSystem——Guide

Issue:<0.5>

SystemAnalysisandDesignDocumentsIssueDate:<10/29/2007>

Tech,2005

Page5of22

3.2插件的工作原理。

如下图所示,这个所有的基于插件的程序的工作原理类似,本质上都是通过读取动态库实现的,只

需要每个动态库都实现某一个特定的接口就可以了,比如XX_init等,这里就是plugin_init。

里面会有个像注册表一样的数据结构会存储所有的插件的信息。

HowtoMountMaemoFileSystem——Guide

Issue:<0.5>

SystemAnalysisandDesignDocumentsIssueDate:<10/29/2007>

Tech,2005

Page6of22

gst_element_register

GST_PLUGIN_DEFINE

(GST_VERSION_MAJOR,

GST_VERSION_MINOR,

"playbin",

"playerbin",plugin_init,

VERSION,GST_LICENSE,

GST_PACKAGE_NAME,

GST_PACKAGE_ORIGIN)

gst_plugin_load_file

g_module_open

g_module_symbol

(“gst_plugin_des

c”)

#define

GST_PLUGIN_DEFINE(major,minor,name,description,init,version,licen,package,origi

n)

GST_PLUGIN_EXPORTGstPluginDescgst_plugin_desc={

major,

minor,

name,

description,

init,

version,

licen,

PACKAGE,

package,

origin,

GST_PADDING_INIT

};

gst_plugin_register_

func

gst_default_registry

_add_plugin

(desc->plugin_init)

(plugin)

plugin_init

这里进入每一个插件的入口

gst_registry_add_feature

(gst_registry_get_default

(),

GST_PLUGIN_FEATUR

E(factory))

这里把插件的信息

加入到注册表里面

load_plugin_func

init_post

gst_init_get_option_

group

main(gst-launch.c)

HowtoMountMaemoFileSystem——Guide

Issue:<0.5>

SystemAnalysisandDesignDocumentsIssueDate:<10/29/2007>

Tech,2005

Page7of22

3.3Gst-launch的工作逻辑

它的工作原理就是根据!号来划分输入的字符串,然后为每个元素构建一个element,最后建立一个pipeline

把这些元素加入,最后通过tstate来启动整个数据循环。

HowtoMountMaemoFileSystem——Guide

Issue:<0.5>

SystemAnalysisandDesignDocumentsIssueDate:<10/29/2007>

Tech,2005

Page8of22

main

gst_par_launchv

_gst_par_escapegst_par_launch

_gst_par_launch

yypar

gst_bin_add(bin,

GST_ELEMENT

(walk->data));

把所有的!分割的元素放

到一个图里面去,图是由

一个chain,和一个list组成

的,chain存储的是一条

链,链里面包括元素也包

括links,而list里面存储

的是links

把这些元素加到新

建立的pipeline里

面去

gst_par_perform_l

ink

把这两个元素连接

起来

gst_element_link_pa

ds_filtered

把src的pad和sink

的pad连接起来,

如果有filter就src-

>fileter->sink

gst_par_perform_

delayed_link

DelayedLink*data=g_new

(DelayedLink,1);

data->src_pad=g_strdup

(src_pad);

data->sink=sink;

data->sink_pad=g_strdup

(sink_pad)

data->caps=gst_caps_copy

(caps);

data->signal_id=

g_signal_connect(G_OBJECT

(src),"pad-added",

G_CALLBACK

(gst_par_found_pad),data);

gst_par_found_pa

d

gst_element_link_pa

ds_filtered

这里根据信号产生

的新的pad作新的

连接

gst_element_t_state(pipeline,

GST_STATE_PAUSED);

event_loop(pipeline,FALSE,

GST_STATE_PLAYING);

gst_element_t_state(pipeline,

GST_STATE_PLAYING)

g_main_context_iteration

到这里的话表示

pipeline都已经建立的

差不多了,下面就是接

收dbus消息,然后设置

相应的状态

Event_loop是消息处理循

环,里面取出能取出的消

息并处理,

g_main_context_iteration

就相当于进入了

g_main_loop_run

gst_element_t_stat

e

(oclass->t_state)

(element,state)

change_state是虚

函数,子类重写这

个函数,在这里就

可以被调用了.

gst_element_t_stat

e_func

gst_element_change

_state

(oclass-

>change_state)

(element,transition)

HowtoMountMaemoFileSystem——Guide

Issue:<0.5>

SystemAnalysisandDesignDocumentsIssueDate:<10/29/2007>

Tech,2005

Page9of22

3.4动态pipeline的创建原理

我们经常需要创建动态的pipeline,因为我们不知道源头是什么格式的,这时候需要这么

做:

比如demuxer,

pipeline=gst_pipeline_new("my_pipeline");

//创建pipeline

source=gst_element_factory_make("filesrc","source");

//创建src

g_object_t(source,"location",argv[1],NULL);

//设置输入文件路径

demux=gst_element_factory_make("oggdemux","demuxer");

//创建demux元素

gst_bin_add_many(GST_BIN(pipeline),source,demux,NULL);

//把这两个元素加入到pipeline里面

gst_element_link_pads(source,"src",demux,"sink");

//把这两个元素连接起来

g_signal_connect(demux,"pad-added",G_CALLBACK(cb_new_pad),NULL);

//这里是关键,demux会创建出一个pad,于是发出信号,等待我们设定的函数cb_new_pad.

gst_element_t_state(GST_ELEMENT(pipeline),GST_STATE_PLAYING);

//启动整个数据流循环

loop=g_main_loop_new(NULL,FALSE);

g_main_loop_run(loop);

//启动gloop事件循环

staticvoid

cb_new_pad(GstElement*element,

GstPad*pad,

gpointerdata)

{

gchar*name;

name=gst_pad_get_name(pad);

g_print("Anewpad%swascreatedn",name);

g_free(name);

/*here,youwouldtupanewpadlinkforthenewlycreatedpad*/

…...

}

在这里就可以根据不同pad来连接不同的后面的element,比如:

gst_element_link_pads(pad,"src",fakesink,"sink");

而如何发现源数据的类型则是这样的:

typefind=gst_element_factory_make("typefind","typefinder");

g_signal_connect(typefind,"have-type",G_CALLBACK(cb_typefound),loop);

每当typefine插件查出类型的时候就会发出这个信号。

“Onceamediatypehasbeendetected,youcanpluganelement(erordecoder)tothe

HowtoMountMaemoFileSystem——Guide

Issue:<0.5>

SystemAnalysisandDesignDocumentsIssueDate:<10/29/2007>

Tech,2005

Page10of22

sourcepadofthetypefindelement,anddecodingofthemediastreamwillstartrightafter.”

总结:从上面这些例子可以看出,它的工作过程是这样的:

首先连接能够连接的原素,比如前端src->decodebin,然后后端连接

converter->resampler->volume->

audiosink。

通过decodebin的信号,根据源类型创建特定的srcpad,再把这个pad连接到后端(后端可以

创建一个ghostpad以方便使用)这样一个pipeline就建好了

3.5Decodebin的工作原理

3.4节已经用文字介绍了decodebin的工作原理,下面的图是讲它的内部实现的:

HowtoMountMaemoFileSystem——Guide

Issue:<0.5>

SystemAnalysisandDesignDocumentsIssueDate:<10/29/2007>

Tech,2005

Page11of22

gst_decode_bin_cha

nge_state

gst_decode_bin_class_init:

gstelement_klass-

>change_state=

GST_DEBUG_FUNCPTR

(gst_decode_bin_change_sta

te);

GST_ELEMENT_CL

ASS(parent_class)-

>change_state

(element,transition);

这里基本上是调用

的其父亲的

change_state

只有在从ready到

pau的时候会加

一个add_fakesink

gst_bin_change_stat

e_func

gst_bin_class_init

gstelement_class-

>change_state=

GST_DEBUG_FUNCPTR

(gst_bin_change_state_func

);

gst_bin_src_pads_ac

tivate

gst_bin_element_t

_state

Foreachelementin

bintoinvoke

gst_element_t_bas

e_time

gst_element_t_stat

e

(oclass->t_state)

(element,state);

调用各自原素重载

后的t_state

parent_class-

>change_state

(element,

transition);

iterator_activate_fol

d_with_resync

new_pad

dynamic_add:

dyn->np_sig_id=g_signal_connect

(G_OBJECT(element),"pad-added",

G_CALLBACK(new_pad),dyn);

dyn->nmp_sig_id=g_signal_connect

(G_OBJECT(element),"no-more-pads",

G_CALLBACK(no_more_pads),

dyn);

decode_bin->typefind=

gst_element_factory_ma

ke("typefind",

"typefind");

gst_decode_bin_init

gst_bin_add(GST_BIN

(decode_bin),decode_bin-

>typefind)

decode_bin->have_type_id=

g_signal_connect

(G_OBJECT(decode_bin-

>typefind),"have_type",

G_CALLBACK

(type_found),decode_bin);

clo_pad_link

type_found

信号调用

find_compatibles

try_to_link_1(decod

e_bin,element,pad,

to_try)

这个函数的作用是这样的:

首先由typefind发现源所设

定的caps,也就决定了

decodebin所提供的sink的类

型,这个函数就是用来根据

它提供的srccaps来选择我

们能提供的sink,比如解码

这里的element

可以理解为

源,而to_try是

一个list这里面

放的是可能连

接这个src的

sink,比如mp3

文件为

element,那么

sink就可能是

我们的mp3dec

sink

如果这个src元素的类型为demux则要先创

建一个queue;则下面的ursrcpad就是

queue的srcpad,到最后的时候会把

source的src取消连接到queue的sink:

gst_element_t_state(element,

GST_STATE_READY);

gst_pad_link(udsrcpad,sinkpad)

gst_element_t_state(element,

GST_STATE_PAUSED);

这样的话源的srcpad就已经连上了

demuxer或者其它元素的sink

gst_element_no_more_pads

g_signal_emit(element,

gst_element_signals[NO_M

ORE_PADS],0);

当没有pads需

要添加的时候

执行

总结:

从上可以看出,decodebin的工作其实是依靠

typefind来实现的,每当它识别出类型的时候

就发出信号,由decodebin接收信号并处理,

也就是根据它识别出的类型参数,寻找匹配

的pad,如果找到了这个元素就把它加到

decodebin里面来。这里需要注意的是queue

的作用,queue意味着是一个thread,他们之

间的同步通过一系列的线程同步函数来实

现,所以显得非常的复杂

HowtoMountMaemoFileSystem——Guide

Issue:<0.5>

SystemAnalysisandDesignDocumentsIssueDate:<10/29/2007>

Tech,2005

Page12of22

3.6Typefind的实现原理

这里是讲程序是如何查找出对应文件应该选用什么解码器之类的,可以简单理解为source识别。

gst_type_find_elem

ent_handle_event

gst_type_find_element_init:

gst_pad_t_event_function(typefind-

>sink,GST_DEBUG_FUNCPTR

(gst_type_find_element_handle_event));

gst_type_find_elem

ent_chain_do_typefi

nding

g_signal_emit(typefind,

gst_type_find_element_s

ignals[HAVE_TYPE],0,

probability,caps);

gst_type_find_elem

ent_chain

gst_type_find_element_init

gst_pad_t_chain_function

(typefind->sink,

GST_DEBUG_FUNCPTR

(gst_type_find_element_chain));

设置

至于如何调用到这

里请看页数据流动

页2

这里发出信号给

decodebin,剩下的

事由它来处理

gst_type_find_helpe

r_for_buffer

gst_type_find_factor

y_get_list

gst_type_find_factor

y_call_function

new_factory-

>function(find,

new_factory-

>ur_data);

gst_type_find_regist

er

factory->function

=func;

设置

就是这里设置的函数

plugin_init

TYPE_FIND_REGISTER

这里会被多次调用,这是一个对

gst_type_find_register

封装的宏,这里会为每一个类似“video/

mpeg4”的字符串设定一个匹配函数,这

个函数的作用就是根据一段buffer里面的

一些字节的特征来识别它的类型,比如

像函数:mpeg4_video_type_find等

设置

调用的就是这里设置的函数

3.7Setupelement

这里主要讲的是如何把这些播放一个source所需要的element连接起来的:

HowtoMountMaemoFileSystem——Guide

Issue:<0.5>

SystemAnalysisandDesignDocumentsIssueDate:<10/29/2007>

Tech,2005

Page13of22

gst_play_bin_class_

init:

playbabin_klass-

>tup_output_pad

s=tup_sinks;

tup_sinks

res=

GST_PLAY_BASE

_BIN_GET_CLASS

(play_ba_bin)->

tup_output_pads

(play_ba_bin,

group);

gen_vis_elementor

gen_audio_element

pad=gst_element_get_pad

(group-

>type[GST_STREAM_TYPE_AU

DIO-1].preroll,”src”);

res=add_sink(play_bin,sink,

pad,NULL);

从这里我们可以推断

出preroll的作用应该

是前端的,add_sink

的作用应该就是把这

个src和sink连接起来

gen_video_element

pad=

gst_element_get_pad

(group-

>type[GST_STREAM_

TYPE_VIDEO-

1].preroll,

"src");

res=add_sink

(play_bin,sink,pad,

textsrcpad);

这里连接的是video的

pad,前面一行代码是

说取一个preroll的src

pad,而后面一行里面

的sink就是

gen_video_element返回

的那个bin,add_link的

作用就是把这srcpad连

接到这个sink。

gen_vis_element

gst_element_get_req

uest_pad

gst_element_class_g

et_pad_template

gst_element_request

_pad

gst_element_class_ge

t_pad_template_list

从这个list里面取出

和传入参数名字相同

的template

newpad=(oclass-

>request_new_pad

)(element,templ,

name);

这里返回取得的

newpad

gst_tee_class_init

gstelement_class-

>request_new_pad

=

GST_DEBUG_FU

NCPTR

(gst_tee_request_n

ew_pad);

gst_tee_request_ne

w_pad

在这里设置

gen_audio_elementgen_video_element

剩下的逻辑就是建立一

个bin,bin里面的内容是

如右所示:

返回的是包含这些元素

的bin,并且建立了一个

ghostpad,作为整个bin

的代表,tee的意思就是

把一个stream分解成两部

tee

Vqueue->converter->vis->vsinkAqueue->asink

element=gst_bin_new("abin");

sink=gst_element_factory_make("alsasink",

"audiosink");

Audioconvert,

Audioresample,

Volume,

gst_element_link_pads(…)

所以最后的结果就像是这样的:

Audioconvert->audioresample->volume->audiosink

最后两点是:

gst_element_add_pad(element,gst_ghost_pad_new

("sink",pad));

建立一个ghostpad在convert的sinkpad上

g_hash_table_inrt(play_bin->cache,"abin",

element);

把这整个bin插入到playbin的abincache里面去。

lement=gst_bin_new("vbin");

构建一个bin

conv=gst_element_factory_make

("ffmpegcolorspace","conv");

构建converter

sink=gst_element_factory_make

(DEFAULT_VIDEOSINK,"sink");

构建videosink

gst_bin_add(GST_BIN(element),conv);

gst_bin_add(GST_BIN(element),sink);

加入到bin里面去

gst_element_link_pads(conv,"src",sink,"sink");

连接这些pads

pad=gst_element_get_pad(conv,"sink");

gst_element_add_pad(element,gst_ghost_pad_new

("sink",pad));

创建ghostpad

这里就是取得audio类

型的srcpad,然后连

接到通过

gen_audio_element返

回的bin

上接playbin页

HowtoMountMaemoFileSystem——Guide

Issue:<0.5>

SystemAnalysisandDesignDocumentsIssueDate:<10/29/2007>

Tech,2005

Page14of22

3.8Playbin的工作原理

有了上面几个步骤就可以很容易理解playbin的工作原理,不过细节依然非常的复杂,我只是画了框

架图:

HowtoMountMaemoFileSystem——Guide

Issue:<0.5>

SystemAnalysisandDesignDocumentsIssueDate:<10/29/2007>

Tech,2005

Page15of22

tup_source

gst_play_ba_bin_

change_state

gen_source_elementanaly_source

取得数据源,这里

有关于http上取数

据的处理

make_decoder

gst_play_bin_chang

e_state

至于程序逻辑如何

走到这里请看gst-

launch页

这里需要特别注意的是,

gstreamer里面的状态控制

是,先从null->ready,然后

从ready->pau…,所以

tup_source的调用时机就

是在从ready到pau的时

这里我分析的是最

普通的情形,也就

是需要解码的,如

果源数据是raw的

走别的路线

g_signal_connect(decoder,"element-

added",

G_CALLBACK

(decodebin_element_added_cb),

play_ba_bin);

g_signal_connect(G_OBJECT

(decoder),

"new-decoded-pad",

G_CALLBACK(new_decoded_pad),

play_ba_bin);

g_signal_connect(G_OBJECT

(decoder),"no-more-pads",

G_CALLBACK(no_more_pads),

play_ba_bin);

上面对decoder做了几个信号连接

gst_element_link

这里把source和

decorder连接起来

decodebin_element

_added_cb

new_decoded_pad

new_decoded_pad_f

ull

gen_preroll_element

sinkpad=

gst_element_get_request_pad

(group->type[type-1].lector,

"sink%d");

gst_pad_link(pad,sinkpad);

add_streamno_more_pads_full

group_commit

信号连接

信号是如何发出

的,请看decodebin

preroll=

gst_element_factory_make

("queue",name);

overrun_sig=g_signal_connect

(G_OBJECT(preroll),"overrun",

G_CALLBACK

(queue_overrun),play_ba_bin);

queue_overrun

res=

GST_PLAY_BASE

_BIN_GET_CLASS

(play_ba_bin)->

tup_output_pads

(play_ba_bin,

group);

不同的babin的子

类不同的实现

tup_substreamsprepare_output

gst_pad_add_event_

probe

probe_triggered

建立的信号处理函

数,谁调用的待

查?但这里只处理

eos信号

以下的几个函数在

每次新构建组的时

候会被执行。。。

下面的工作请看

tup页

HowtoMountMaemoFileSystem——Guide

Issue:<0.5>

SystemAnalysisandDesignDocumentsIssueDate:<10/29/2007>

Tech,2005

Page16of22

3.9数据流动

下面讲的是里面最复杂的数据流动的分析,我主要分析了src的流动和sink的流动,因为中间的数据流动太多,

比如解码器,filter等等,实在没空,但是我想有这两元素的分析,其它的元素就很容易了:

HowtoMountMaemoFileSystem——Guide

Issue:<0.5>

SystemAnalysisandDesignDocumentsIssueDate:<10/29/2007>

Tech,2005

Page17of22

gst_element_t_stat

e

klass->t_state=

GST_DEBUG_FU

NCPTR

(gst_element_t_st

ate_func);

gst_element_change

_state

(oclass-

>change_state)

(element,

transition);

gst_element_continu

e_state

gst_file_src_class_i

nit

gst_file_src_create

gst_file_src_create_

mmap

或者

gst_file_src_create_

read

gst_ba_src_loop

gst_ba_src_get_ra

nge

bclass->create(src,

offt,length,buf);

gst_ba_src_t_pl

aying

gst_pad_start_task

(basrc->srcpad,

(GstTaskFunction)

gst_ba_src_loop,

gst_task_creategst_task_start

在这里handler

gst_ba_src_loop

被赋给了GstTask

的func

task->func=func;

gst_task_class_init

klass->pool=

g_thread_pool_ne

w(

(GFunc)

gst_task_func,

klass,-1,FALSE,

NULL);

g_thread_pool_new

retval->=

func;

g_thread_pool_push

g_thread_pool_start

_thread

g_thread_create

(g_thread_pool_thr

ead_proxy,pool,

FALSE,

&local_error);

g_thread_pool_threa

d_proxy

g_async_queue_pop

_unlocked

pool->

(task,pool-

>_data);

gst_task_func

task->func(task-

>data);

gst_ba_src_loop

是在

gst_task_create

里被设置的,在

gst_task_func

里面被调用的

init时状态为GST_TASK_STOPPED,于是调用它

设置

调用

设置

调用

gst_ba_src_chang

e_state

当元素为filesrc的时候

Ca

GST_STATE_CHAN

GE_PAUSED_TO_P

LAYING:

...

gst_ba_src_is_live

(basrc)

gst_ba_src_do_sy

nc

gst_ba_src_start

gstbasrc_class-

>create=

GST_DEBUG_FUNCP

TR

(gst_file_src_create);

设置

bclass->start

(basrc);

(在init函数里被

设置)

gst_pad_push_event

gst_pad_push(pad,

buf);

请看数据流动页2

HowtoMountMaemoFileSystem——Guide

Issue:<0.5>

SystemAnalysisandDesignDocumentsIssueDate:<10/29/2007>

Tech,2005

Page18of22

gst_pad_push

gst_pad_emit_have_

data_signal

(peer=

GST_PAD_PEER

(pad))

gst_pad_chain_unch

ecked(peer,buffer);

(chainfunc=

GST_PAD_CHAIN

FUNC(pad))

gst_pad_emit_have_

data_signal

ret=chainfunc(pad,

buffer);

从这里整个数据流的循

环就开始了,从src的pad

发送数据,调用peer的

pad的chainfunc函数,这

样一步步的传下去了

gst_pad_t_chain_f

unction

plugin的init函数里

面初始化

chainfunc,下面的

chainfunc是sink的

处理逻辑

gst_ba_sink_chain

gst_ba_sink_chain

_unlocked

gst_ba_sink_queu

e_object_unlocked

gst_ba_sink_prero

ll_object

gst_ba_sink_rende

r_object

gst_ba_transform_

handle_buffer

ret=bclass-

>transform_ip

(trans,inbuf);

gst_ba_transform_

chain

gst_ba_transform_

init

gst_pad_t_chain_functi

on(trans->sinkpad,

GST_DEBUG_FUNCPT

R

(gst_ba_transform_cha

in));

gst_ba_sink_chan

ge_state

这是volume的处理

逻辑

gstbasink_class-

>render=

GST_DEBUG_FU

NCPTR

(gst_ba_audio_si

nk_render);

gst_ba_audio_sink

_class_init

赋值

gst_ring_buffer_co

mmit_full

gst_ba_audio_sink

_render

gst_pad_push

gst_ba_sink_do_s

ync

gst_ba_sink_do_r

ender_stats

bclass->render

(basink,buf);

gst_ba_audio_sink

_change_state

gst_ba_audio_sink

_do_play

gst_ba_audio_sink

_async_play

Change_state的时

候执行逻辑

FWD_SAMPLES

memcpy

gst_audio_sink_crea

te_ringbuffer

gst_audio_src_class_init

gstbaaudiosrc_class-

>create_ringbuffer=

GST_DEBUG_FUNCPTR

(gst_audio_sink_create_ringb

uffer);

设置

gst_ba_audio_sink

_change_state

gst_audioringbuffer

_open_device

csrc->open(src);

gst_alsasink_open

Foralsasink

gst_ring_buffer_star

t

rclass->start(buf);

start所对应的函数

请看页数据流动3

HowtoMountMaemoFileSystem——Guide

Issue:<0.5>

SystemAnalysisandDesignDocumentsIssueDate:<10/29/2007>

Tech,2005

Page19of22

audioringbuffer_thre

ad_func

gst_audioringbuffer

_acquire

csink->prepare

(sink,spec);

g_thread_create

((GThreadFunc)

audioringbuffer_th

read_func,buf,

TRUE,

NULL);

GST_AUDIORIN

G_BUFFER_WAI

T(buf);

gst_audioringbuffer_class_init

gstringbuffer_class->acquire=

GST_DEBUG_FUNCPTR

(gst_audioringbuffer_acquire);

赋值

gst_ring_buffer_acq

uire

res=rclass-

>acquire(buf,spec);

gst_ba_audio_sink

_tcaps

gst_ba_audio_sink_cl

ass_init:

tbasink_class-

>t_caps=

GST_DEBUG_FUNCP

TR

(gst_ba_audio_sink_s

etcaps);

赋值

调用

gst_ba_sink_pad_

tcaps

bclass->t_caps

(bsink,caps);

调用

gst_ba_sink_init:

。。。

gst_pad_t_tcaps_func

tion(basink->sinkpad,

GST_DEBUG_FUNCPT

R

(gst_ba_sink_pad_tca

ps));

设置

gst_pad_get_caps_u

nlocked

GST_PAD_GETCA

PSFUNC(pad)

(pad);

gst_pad_get_caps

gst_pad_link_check

_compatible_unlock

ed

gst_pad_link_prepar

e

gst_pad_link

这里有多种可能的

调用

pad_link_maybe_gh

osting

gst_element_link_pa

ds

gen_audio_elementgen_video_element

这个函数也是有多

种调用可能

至于如何到这里请

看tup页

gst_audioringbuffer

_start

gst_audioringbuffer_class_in

it:

gstringbuffer_class->start=

GST_DEBUG_FUNCPTR

(gst_audioringbuffer_start);

gst_ring_buffer_star

t

设置

gst_ba_audio_sink

_render

至于如何到这里的

请看页数据流动页

2

rclass->start(buf);

调用

上接页数据流动2

GST_AUDIORIN

G_BUFFER_SIGN

AL(buf);

发出信号

writefunc=csink-

>write;

gst_ring_buffer_pre

pare_read

writefunc(sink,

readptr+written,

left);

GST_AUDIORING_B

UFFER_SIGNAL

(buf);

GST_AUDIORING_B

UFFER_WAIT(buf);

从这个signal和wait操作就可以看清楚它

的脉络了,当数据流开始的时候,

writefunc一直等待在那个环行缓冲的地

方,等待被唤醒,当数据开始的时候由

render函数开始一直到

gst_ring_buffer_commit_full函数,这里

面把数据用memcpy把数据送到环行数据

缓冲区里面,并且发出唤醒信号,于是整

个生产者消费者循环开始了,它们之间是

通过g_cond_signal来实现同步的

HowtoMountMaemoFileSystem——Guide

Issue:<0.5>

SystemAnalysisandDesignDocumentsIssueDate:<10/29/2007>

Tech,2005

Page20of22

3.10总结

.时间有限,我只能分析这些框架了,估计看懂这几个图也不容易,

两个关键的函数是change_state,这是一个经常被重载的函数,基本上元素的初始化,

状态的改变都会在这里面会被处理,另外一个非常关键的chaingfunc这个函数是开

启数据流动的关键函数,通常src调用chainfunc函数,在这个函数里面会取出peerpad

的chainfunc,然后调用src对应的sink的chainfunc,另外一个让我迷惑了很久的是到

sink的数据是如何流动的,最后分析的结果是它使用了一个环行缓冲,并且使用了

线程同步操作来实现生产者消费者的模式以加快数据的传递,所以数据的最终传递

是通过发出p、v操作来实现的,里面先把数据取出来调用memcpy来copy到环行缓冲,

然后发出v操作,对应的消费者被唤醒调用sink插件的write操作把数据写到设备里面

去,这里面还有几块我没有分析的,比如时间戳的处理,各种元素之间的延迟的协

商,以及音频视频之间的同步播放等,这里面涉及很多多线程问题,如果要分析估

计得花很多的时间。

nce

[1]/documentation/

补充:

#playbin的工作流程

1,创建source。

2,创建decodebin。

3,为decodebin添加typefind。

4,在向bin添加元素的时候都会发出element-added的信号。

5,向decodebin添加fakesink。

6,把decodebin加入到playbin.

7,等待typefind元素发出的have-type信号,并调用回调函数,注意这里的信号实际是只

包含了caps信息,而后,根据注册表里面的每个factory取出其提供的caps与typefind提供的

caps取交集,如果有交集则加入到一个list表中(find_compatibles)。

8,取出list里面的元素来连接,如果找到一个就结束,找到后把这个元素与src元素连

接起来,递归的进行这个元素本身的sinkpad的连接,直到收到了no_more_pads的消息。

9,decodebin收到no_more_pads消息后也会发出同样的消息,其余处理逻辑请看文档

HowtoMountMaemoFileSystem——Guide

Issue:<0.5>

SystemAnalysisandDesignDocumentsIssueDate:<10/29/2007>

Tech,2005

Page21of22

注意:clo_pad_link

1,通常每一个element在被创建的时候都会添加自己的pad,所以都会发出pad-added的

信号。

2,clo_link(GstElement*element,GstDecodeBin*decode_bin)

try_to_link_1(GstDecodeBin*decode_bin,GstElement*srcelement,GstPad*pad,GList*

factories):这个函数的意思是从这个factories里面取出某个能够连接到pad的元素,和

srcelement连接起来,连接起来后还要为这个刚连接起来的元素寻找到它的归属,也就是为

它寻找它的sink,调用的函数是clo_link,当从这个函数返回的时候,或则它的sinkpad已经被

装上或则如果是动态的则已经装上了信号处理器等待sinkpad被动态装上,于是

gst_element_t_state(element,GST_STATE_PAUSED);当这个函数执行完后,所有的需要安

装sink的元素都已经好了,这个函数会发出pad-added信号,而这个信号的处理函数是

new_pad,在这个函数里面会调用clo_pad_link根据pad和caps寻找适合这个pad的sinkpad,

所有实际是从这个函数返回后,几乎所有的tup工作都已经over了,可以理解为将要从

typefind元素的have-type信号的信号处理函数type_fount返回了,当然之前还会收到

no_more_pads的信号执行处理函数no_more_pads,于是decodebin发出了no_more_pads的信

号,于是playbin会根据这个信号执行处理函数group_commit.

3,clo_pad_link(GstElement*element,GstPad*pad,GstCaps*caps,GstDecodeBin*

decode_bin,gbooleanmore):这个函数是根据pad和caps为它寻找到一个可以与之连接的一个

链表,或则如果这个caps代表raw数据则创建并添加一个ghostpad到decodebin里面去。

4,find_compatibles(GstDecodeBin*decode_bin,constGstCaps*caps):这个函数的意思

是根据这个caps从注册表里面找出和它有交集的GstElementFactory,并加入到list中返回。

5,clo_link(GstElement*element,GstDecodeBin*decode_bin):这个函数的意思是为

element添加sink,如果它的srcpad是动态的,则调用dynamic_add来添加信号处理函数,等待

它的动态的pad被添加上,如果不是动态的就调用clo_pad_link来从注册表里面选择合适的

sinkpad来加入。

TYPE_FIND_REGISTER(plugin,"video/mp4",GST_RANK_PRIMARY,m4v_type_find,

mp4_exts,M4V_CAPS,NULL,NULL);

行;需要移掉gstdecodebin.c和gstdecodebin2.c里面的函数find_compatibles里面的to_try

=g_list_rever(to_try)

HowtoMountMaemoFileSystem——Guide

Issue:<0.5>

SystemAnalysisandDesignDocumentsIssueDate:<10/29/2007>

Tech,2005

Page22of22

本文发布于:2022-12-27 12:49:06,感谢您对本站的认可!

本文链接:http://www.wtabcd.cn/fanwen/fan/90/40403.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

上一篇:go out
下一篇:reciprocally
标签:streamer
相关文章
留言与评论(共有 0 条评论)
   
验证码:
Copyright ©2019-2022 Comsenz Inc.Powered by © 专利检索| 网站地图