原文地址: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