vlc框架流程解析(转)
原文地址:http://luzefengoo.blog.163.com/blog/static/1403593882012754481846/
?
第二部分?程序框架實現
1.?播放列表文件src/playlist/playlist.c的線程
playlist_t?*?__playlist_Create?(?vlc_object_t?*p_parent?)函數中創建的線程,線程函數為
static?void?RunThread?(?playlist_t?*p_playlist?)
線程思路分析:
在RunThread里面執行循環,如果沒有任務執行,則適當的延遲,如果接到p_playlist->i_status?!=?PLAYLIST_STOPPED的條件,則調用PlayItem(?p_playlist?)函數,在PlayItem(?p_playlist?)函數中從新創建輸入線程。
通過void?playlist_Command(?playlist_t?*?p_playlist,?playlist_command_t?i_command,int?i_arg?)接收來自GUI界面的各種命令,然后設置p_playlist->i_status的狀態,由該狀態改變該播放列表文件主循環線程的執行。
2.?輸入文件SRC/INPUT/INPUT.C的輸入線程
input_thread_t?*__input_CreateThread(?vlc_object_t?*p_parent,
input_item_t?*p_item?)函數中創建的線程,線程函數為
static?int?RunThread(?input_thread_t?*p_input?)
線程思路分析:
由?input_thread_t結構的成員分析是接收文件流還是網絡流,如果是文件流,則調用file?module?的讀函數(pf_read)和打開函數(--).如果是network?則打開network?module?的打開函數和讀函數(pf_read)。
在?RunThread線程函數中接收數據和調用demux?或者decode?etc處理。
一旦產生新的輸入,則在播放列表線程中會首先結束該輸入線程,然后從新創建新的輸入線程。
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?)函數中創建的線程,線程函數為
static?void?RunThread(?vout_thread_t?*p_vout)
線程思路分析:
在RunThread里面執行循環,任務是顯示視頻。
4.?在modules\gui\wxwindows\wxwindows.cpp中的GUI線程
static?void?Run(?intf_thread_t?*p_intf?)?函數中創建的線程,線程函數為
static?void?Init(?intf_thread_t?*p_intf?)
線程思路分析:
在Init(?intf_thread_t?*p_intf?)里面執行循環,創建新的GUI實例。Instance-》OnInit()(CreateDialogsProvider)-》DialogsProvider為運行的對話框。
接收網絡文件的步驟
OnOpenNet(?wxCommandEvent&?event?)打開網絡文件的步驟。打開OpenDialog對話框,點擊Ok后調用OpenDialog::OnOk(?wxCommandEvent&?WXUNUSED(event)?)函數,調用playlist_Command函數改變播放列表線程的狀態。
激活線程分析:
在wxwindow.cpp中的消息映射中?set_callbacks(?OpenDialogs,?Close?);?則設置了module_t->pf_activate=?OpenDialogs函數,
在module.c?的__module_Need(?vlc_object_t?*p_this,?const?char?*psz_capability,
const?char?*psz_name,?vlc_bool_t?b_strict?)
函數中用到了pf_activate激活GUI對話框;
在video_output.c?的static?void?RunThread(?vout_thread_t?*p_vout)線程中,也用到了pf_activate激活GUI對話框;
5.?開始所有module?的精髓
消息映射宏
vlc_module_begin();
set_callbacks(?NetOpen,?NULL?);
vlc_module_end();
然后設置模塊結構的成員函數為:
#define?set_callbacks(?activate,?deactivate?)?\
p_submodule->pf_activate?=?activate;?\
p_submodule->pf_deactivate?=?deactivate
在__module_Need函數中啟動pf_activate?激活相應的module。
1.?我的理解:
macro?of?message?map
2./*********
*定義一個公共的結構
*并把激活本模塊的函數傳給該結構的函數成員
************************/
vlc_module_begin();
set_callbacks(?NetOpen,?NULL?);
vlc_module_end();
設置模塊結構的pf_activate成員函數為NetOpen:
#define?set_callbacks(?activate,?deactivate?)?\
p_submodule->pf_activate?=?activate;?\
p_submodule->pf_deactivate?=?deactivate
所以當通過函數module_need激活模塊的時候,就是通過pf_activate來啟動模塊的!
vlc_module_begin()起到了一個消息傳遞的作用!
vlc學習計劃(6)--網絡數據流接收處理過程分析
網絡數據流接收處理分析
1、在input.c(src\input)文件中的主線程循環
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、在下列函數中:
分離出access?,?demux?,?name字符串?;
根據分離出的access?字符串通過module_Need函數找到acess?指針模塊;
根據分離出的demux?字符串通過module_Need函數找到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.通過消息映射宏賦值啟動函數Activate;
b.通過函數Activate賦值p_input->pf_demux?=?Demux;
c.?通過函數module_Need(?p_input,?"mpeg-system",?NULL,?0?)?激活p_input->p_demux_data->mpeg.pf_read_ps(?p_input,?&p_data?)函數(pf_read_ps);
d.在InitThread函數中激活;
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的成員函數;
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;
}
并且申明函數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?);
}
進行讀取數據和分離工作;
6、在system.c?(module\demux\mpeg)文件中
數據走向圖如下
ReadPS->?PEEK->?input_Peek(src\input\input_ext-plugins.c)->?input_FillBuffert?通過?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結構的pf_read函數成員如果是為udp.c(modules\access)的RTPChoose函數
則在開啟access(UDP?模塊)時通過module_need?激活;
激活網絡讀數據模塊?RTPChoose(modules\access\?udp.c)->Read->net_Read(src\misc\net.c);
7、在input_programs.c(src\input)文件中
運行解碼器對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學習計劃(7)--從接收到數據流到播放視頻的過程分析
從接收到數據流到播放視頻的過程分析
從網絡接收到流->對數據流進行視頻和音頻分離->對視頻用解碼器解碼->顯示解碼后的視頻流
視頻顯示部分走勢線:分離->解碼->新的VOUT緩沖區->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)函數中激活
解碼部分走勢線:
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
注意:在解碼線程中對數據流(AUDIO?或者VIDEO)進行解碼
詳細資料?http://developers.videolan.org/vlc/?VLC?API?documentation?或者VLC?developer?documentation
創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎總結
以上是生活随笔為你收集整理的vlc框架流程解析(转)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 菜鸟学SSH(十五)——简单模拟Hibe
- 下一篇: 可能 delphi7 下稳定的最后一版本