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小时内删除。
留言与评论(共有 0 条评论) |