• 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. 在modulesguiwxwindowswxwindows.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(srcinput)文件中的主线程循环

    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 (moduledemuxmpeg)文件中

    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 (moduledemuxmpeg)文件中

    赋值解码模块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 (moduledemuxmpeg)文件中

    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 (moduledemuxmpeg)文件中

    数据走向图如下

    ReadPS-> PEEK-> input_Peek(srcinputinput_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(modulesaccess)的RTPChoose函数

    则在开启access(UDP 模块)时通过module_need 激活;

    激活网络读数据模块 RTPChoose(modulesaccess udp.c)->Read->net_Read(srcmisc et.c);

    7、在input_programs.c(srcinput)文件中

    运行解码器对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(srcinputinput_programs.c)->input_RunDecoder(srcinputinput_dec.c)->DecoderThread->DecoderDecode ->vout_DisplayPicture

    vlc学习计划(7)--从接收到数据流到播放视频的过程分析

    从接收到数据流到播放视频的过程分析

    从网络接收到流->对数据流进行视频和音频分离->对视频用解码器解码->显示解码后的视频流

    视频显示部分走势线:分离->解码->新的VOUT缓冲区->VOUT线程

    Demux(modulesdemuxmpegps.c)->DemuxPs(modulesdemuxmpegsystem.c)-> ParsePS->input_SelectES(srcinputinput_programs.c)->input_RunDecoder(srcinputinput_dec.c)->CreateDecoder->

    vout_new_buffer->vout_Request(srcvideo_outputvideo_output.c)->vout_Create->RunThread->vout_RenderPicture(srcvideo_outputvout_pictures.c)->pf_display

    注意:p_dec->pf_vout_buffer_new = vout_new_buffer的pf_vout_buffer_new在ffmpeg_NewPictBuf(modulescodecffmpegvideo.c)函数中激活

    解码部分走势线:

    Demux(modulesdemuxmpegps.c)->DemuxPs(modulesdemuxmpegsystem.c)-> ParsePS->input_SelectES(srcinputinput_programs.c)->input_RunDecoder(srcinputinput_dec.c)->CreateDecoder->

    DecoderThread

    注意:在解码线程中对数据流(AUDIO 或者VIDEO)进行解码

    详细资料 http://developers.videolan.org/vlc/ VLC API documentation 或者VLC developer documentation

  • 相关阅读:
    PHPMailer 发送邮件
    Joomla with blog modification
    PHPGD库分类整理
    转 memcache保存php的session 解决多服务器的session问题
    PHP缓存检查
    PHP HMVC框架kohana 小结1
    安装新版ganglia web UI 笔记。
    oracle sqlserver & oracle temp
    db mysql error list / mysql tools / mysql error_list
    oracle sql statement temp
  • 原文地址:https://www.cnblogs.com/wainiwann/p/3868290.html
Copyright © 2020-2023  润新知