vlc框架流程解析(转)
原文地址:http://luzefengoo.blog.163.com/blog/static/1403593882012754481846/
?
第二部分?程序框架實(shí)現(xiàn)
1.?播放列表文件src/playlist/playlist.c的線程
playlist_t?*?__playlist_Create?(?vlc_object_t?*p_parent?)函數(shù)中創(chuàng)建的線程,線程函數(shù)為
static?void?RunThread?(?playlist_t?*p_playlist?)
線程思路分析:
在RunThread里面執(zhí)行循環(huán),如果沒(méi)有任務(wù)執(zhí)行,則適當(dāng)?shù)难舆t,如果接到p_playlist->i_status?!=?PLAYLIST_STOPPED的條件,則調(diào)用PlayItem(?p_playlist?)函數(shù),在PlayItem(?p_playlist?)函數(shù)中從新創(chuàng)建輸入線程。
通過(guò)void?playlist_Command(?playlist_t?*?p_playlist,?playlist_command_t?i_command,int?i_arg?)接收來(lái)自GUI界面的各種命令,然后設(shè)置p_playlist->i_status的狀態(tài),由該狀態(tài)改變?cè)摬シ帕斜砦募餮h(huán)線程的執(zhí)行。
2.?輸入文件SRC/INPUT/INPUT.C的輸入線程
input_thread_t?*__input_CreateThread(?vlc_object_t?*p_parent,
input_item_t?*p_item?)函數(shù)中創(chuàng)建的線程,線程函數(shù)為
static?int?RunThread(?input_thread_t?*p_input?)
線程思路分析:
由?input_thread_t結(jié)構(gòu)的成員分析是接收文件流還是網(wǎng)絡(luò)流,如果是文件流,則調(diào)用file?module?的讀函數(shù)(pf_read)和打開(kāi)函數(shù)(--).如果是network?則打開(kāi)network?module?的打開(kāi)函數(shù)和讀函數(shù)(pf_read)。
在?RunThread線程函數(shù)中接收數(shù)據(jù)和調(diào)用demux?或者decode?etc處理。
一旦產(chǎn)生新的輸入,則在播放列表線程中會(huì)首先結(jié)束該輸入線程,然后從新創(chuàng)建新的輸入線程。
3.?視頻輸出文件src/video_output/?video_output.c的線程
vout_thread_t?*?__vout_Create(?vlc_object_t?*p_parent,
unsigned?int?i_width,?unsigned?int?i_height,
vlc_fourcc_t?i_chroma,?unsigned?int?i_aspect?)函數(shù)中創(chuàng)建的線程,線程函數(shù)為
static?void?RunThread(?vout_thread_t?*p_vout)
線程思路分析:
在RunThread里面執(zhí)行循環(huán),任務(wù)是顯示視頻。
4.?在modules\gui\wxwindows\wxwindows.cpp中的GUI線程
static?void?Run(?intf_thread_t?*p_intf?)?函數(shù)中創(chuàng)建的線程,線程函數(shù)為
static?void?Init(?intf_thread_t?*p_intf?)
線程思路分析:
在Init(?intf_thread_t?*p_intf?)里面執(zhí)行循環(huán),創(chuàng)建新的GUI實(shí)例。Instance-》OnInit()(CreateDialogsProvider)-》DialogsProvider為運(yùn)行的對(duì)話框。
接收網(wǎng)絡(luò)文件的步驟
OnOpenNet(?wxCommandEvent&?event?)打開(kāi)網(wǎng)絡(luò)文件的步驟。打開(kāi)OpenDialog對(duì)話框,點(diǎn)擊Ok后調(diào)用OpenDialog::OnOk(?wxCommandEvent&?WXUNUSED(event)?)函數(shù),調(diào)用playlist_Command函數(shù)改變播放列表線程的狀態(tài)。
激活線程分析:
在wxwindow.cpp中的消息映射中?set_callbacks(?OpenDialogs,?Close?);?則設(shè)置了module_t->pf_activate=?OpenDialogs函數(shù),
在module.c?的__module_Need(?vlc_object_t?*p_this,?const?char?*psz_capability,
const?char?*psz_name,?vlc_bool_t?b_strict?)
函數(shù)中用到了pf_activate激活GUI對(duì)話框;
在video_output.c?的static?void?RunThread(?vout_thread_t?*p_vout)線程中,也用到了pf_activate激活GUI對(duì)話框;
5.?開(kāi)始所有module?的精髓
消息映射宏
vlc_module_begin();
set_callbacks(?NetOpen,?NULL?);
vlc_module_end();
然后設(shè)置模塊結(jié)構(gòu)的成員函數(shù)為:
#define?set_callbacks(?activate,?deactivate?)?\
p_submodule->pf_activate?=?activate;?\
p_submodule->pf_deactivate?=?deactivate
在__module_Need函數(shù)中啟動(dòng)pf_activate?激活相應(yīng)的module。
1.?我的理解:
macro?of?message?map
2./*********
*定義一個(gè)公共的結(jié)構(gòu)
*并把激活本模塊的函數(shù)傳給該結(jié)構(gòu)的函數(shù)成員
************************/
vlc_module_begin();
set_callbacks(?NetOpen,?NULL?);
vlc_module_end();
設(shè)置模塊結(jié)構(gòu)的pf_activate成員函數(shù)為NetOpen:
#define?set_callbacks(?activate,?deactivate?)?\
p_submodule->pf_activate?=?activate;?\
p_submodule->pf_deactivate?=?deactivate
所以當(dāng)通過(guò)函數(shù)module_need激活模塊的時(shí)候,就是通過(guò)pf_activate來(lái)啟動(dòng)模塊的!
vlc_module_begin()起到了一個(gè)消息傳遞的作用!
vlc學(xué)習(xí)計(jì)劃(6)--網(wǎng)絡(luò)數(shù)據(jù)流接收處理過(guò)程分析
網(wǎng)絡(luò)數(shù)據(jù)流接收處理分析
1、在input.c(src\input)文件中的主線程循環(huán)
Thread?in?charge?of?processing?the?network?packets?and?demultiplexing
RunThread(?input_thread_t?*p_input?)
{
InitThread(?p_input?)?;
…………………………………………………….
input_SelectES(?p_input,?p_input->stream.p_newly_selected_es?);
…………………………………………………….
/*?Read?and?demultiplex?some?data.?*/
i_count?=?p_input->pf_demux(?p_input?);
}
2、在下列函數(shù)中:
分離出access?,?demux?,?name字符串?;
根據(jù)分離出的access?字符串通過(guò)module_Need函數(shù)找到acess?指針模塊;
根據(jù)分離出的demux?字符串通過(guò)module_Need函數(shù)找到demux?指針模塊;
static?int?InitThread(?input_thread_t?*?p_input?)
{
msg_Dbg(?p_input,?"access?`%s',?demux?`%s',?name?`%s'",
p_input->psz_access,?p_input->psz_demux,?p_input->psz_name?);
/*?Find?and?open?appropriate?access?module?*/
p_input->p_access?=?module_Need(?p_input,?"access",
p_input->psz_access,?VLC_TRUE?);
…………………………………………………….
while(?!input_FillBuffer(?p_input?)?)
…………………………………………………….
/*?Find?and?open?appropriate?demux?module?*/
p_input->p_demux?=
module_Need(?p_input,?"demux",
(p_input->psz_demux?&&?*p_input->psz_demux)??
p_input->psz_demux?:?"$demux",
(p_input->psz_demux?&&?*p_input->psz_demux)??
VLC_TRUE?:?VLC_FALSE?);
…………………………………………………….
}
3、在ps.c?(module\demux\mpeg)文件中
a.通過(guò)消息映射宏賦值啟動(dòng)函數(shù)Activate;
b.通過(guò)函數(shù)Activate賦值p_input->pf_demux?=?Demux;
c.?通過(guò)函數(shù)module_Need(?p_input,?"mpeg-system",?NULL,?0?)?激活p_input->p_demux_data->mpeg.pf_read_ps(?p_input,?&p_data?)函數(shù)(pf_read_ps);
d.在InitThread函數(shù)中激活;
static?int?Activate(?vlc_object_t?*?p_this?)
{
/*?Set?the?demux?function?*/
p_input->pf_demux?=?Demux;
p_input->p_private?=?(void*)&p_demux->mpeg;
p_demux->p_module?=?module_Need(?p_input,?"mpeg-system",?NULL,?0?);
}
4、在system.c?(module\demux\mpeg)文件中
賦值解碼模塊mpeg_demux_t的成員函數(shù);
static?int?Activate?(?vlc_object_t?*p_this?)
{
static?mpeg_demux_t?mpeg_demux?=
{?NULL,?ReadPS,?ParsePS,?DemuxPS,?ReadTS,?DemuxTS?};
mpeg_demux.cur_scr_time?=?-1;
memcpy(?p_this->p_private,?&mpeg_demux,?sizeof(?mpeg_demux?)?);
return?VLC_SUCCESS;
}
并且申明函數(shù)static?ssize_t?ReadPS(?input_thread_t?*?p_input,?data_packet_t?**?pp_data?);
5、在ps.c?(module\demux\mpeg)文件中
Demux(?input_thread_t?*?p_input?)
{
i_result?=?p_input->p_demux_data->mpeg.pf_read_ps(?p_input,?&p_data?);
p_input->p_demux_data->mpeg.pf_demux_ps(?p_input,?p_data?);
}
進(jìn)行讀取數(shù)據(jù)和分離工作;
6、在system.c?(module\demux\mpeg)文件中
數(shù)據(jù)走向圖如下
ReadPS->?PEEK->?input_Peek(src\input\input_ext-plugins.c)->?input_FillBuffert?通過(guò)?i_ret?=?p_input->pf_read(?p_input,
(byte_t?*)p_buf?+?sizeof(data_buffer_t)
+?i_remains,
p_input->i_bufsize?);
input_thread_t結(jié)構(gòu)的pf_read函數(shù)成員如果是為udp.c(modules\access)的RTPChoose函數(shù)
則在開(kāi)啟access(UDP?模塊)時(shí)通過(guò)module_need?激活;
激活網(wǎng)絡(luò)讀數(shù)據(jù)模塊?RTPChoose(modules\access\?udp.c)->Read->net_Read(src\misc\net.c);
7、在input_programs.c(src\input)文件中
運(yùn)行解碼器對(duì)ES流解碼
int?input_SelectES(?input_thread_t?*?p_input,?es_descriptor_t?*?p_es?)
{
p_es->p_dec?=?input_RunDecoder(?p_input,?p_es?);
}
input_SelectES(src\input\input_programs.c)->input_RunDecoder(src\input\input_dec.c)->DecoderThread->DecoderDecode?->vout_DisplayPicture
vlc學(xué)習(xí)計(jì)劃(7)--從接收到數(shù)據(jù)流到播放視頻的過(guò)程分析
從接收到數(shù)據(jù)流到播放視頻的過(guò)程分析
從網(wǎng)絡(luò)接收到流->對(duì)數(shù)據(jù)流進(jìn)行視頻和音頻分離->對(duì)視頻用解碼器解碼->顯示解碼后的視頻流
視頻顯示部分走勢(shì)線:分離->解碼->新的VOUT緩沖區(qū)->VOUT線程
Demux(modules\demux\mpeg\ps.c)->DemuxPs(modules\demux\mpeg\system.c)->?ParsePS->input_SelectES(src\input\input_programs.c)->input_RunDecoder(src\input\input_dec.c)->CreateDecoder->
vout_new_buffer->vout_Request(src\video_output\video_output.c)->vout_Create->RunThread->vout_RenderPicture(src\video_output\vout_pictures.c)->pf_display
注意:p_dec->pf_vout_buffer_new?=?vout_new_buffer的pf_vout_buffer_new在ffmpeg_NewPictBuf(modules\codec\ffmpeg\video.c)函數(shù)中激活
解碼部分走勢(shì)線:
Demux(modules\demux\mpeg\ps.c)->DemuxPs(modules\demux\mpeg\system.c)->?ParsePS->input_SelectES(src\input\input_programs.c)->input_RunDecoder(src\input\input_dec.c)->CreateDecoder->
DecoderThread
注意:在解碼線程中對(duì)數(shù)據(jù)流(AUDIO?或者VIDEO)進(jìn)行解碼
詳細(xì)資料?http://developers.videolan.org/vlc/?VLC?API?documentation?或者VLC?developer?documentation
創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎(jiǎng)勵(lì)來(lái)咯,堅(jiān)持創(chuàng)作打卡瓜分現(xiàn)金大獎(jiǎng)總結(jié)
以上是生活随笔為你收集整理的vlc框架流程解析(转)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 菜鸟学SSH(十五)——简单模拟Hibe
- 下一篇: 可能 delphi7 下稳定的最后一版本