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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM