zoukankan      html  css  js  c++  java
  • vlc学习计划(5)--VLC程序宏及线程分析

           第一部分             变量及宏定义
    1.消息映射宏
                           vlc_module_begin();
                               …………………..
    vlc_module_end();
    2.结构中包含函数
           struct input_thread_t
    {
        VLC_COMMON_MEMBERS
        /* Thread properties */
        vlc_bool_t              b_eof;
        vlc_bool_t              b_out_pace_control;
        /* Access module */
        module_t *       p_access;
        ssize_t       (* pf_read ) ( input_thread_t *, byte_t *, size_t );
        int           (* pf_set_program )( input_thread_t *, pgrm_descriptor_t * );
        int           (* pf_set_area )( input_thread_t *, input_area_t * );
        void          (* pf_seek ) ( input_thread_t *, off_t );
    }
    3.宏与换行符妙用
    #define VLC_COMMON_MEMBERS                                                  \
    /** \name VLC_COMMON_MEMBERS                                                \
     * these members are common for all vlc objects                             \
     */                                                                         \
    /**@{*/                                                                     \
        int   i_object_id;                                                      \
        int   i_object_type;                                                    \
        char *psz_object_type;                                                  \
        char *psz_object_name;                                                  \
                                                                                                   \
     /** Just a reminder so that people don't cast garbage */                \
        int be_sure_to_add_VLC_COMMON_MEMBERS_to_struct;                        \
    /**@}*/                    
    #define VLC_OBJECT( x ) \ 
    ((vlc_object_t *)(x))+
    0*(x)->be_sure_to_add_VLC_COMMON_MEMBERS_to_struct
    struct vlc_object_t
    {
        VLC_COMMON_MEMBERS
    };//定义一个结构来使用宏定义的公共成员
    4.定义导出函数
    #ifndef __PLUGIN__
    #   define VLC_EXPORT( type, name, args ) type name args
    #else
    #   define VLC_EXPORT( type, name, args ) struct _u_n_u_s_e_d_
        extern module_symbols_t* p_symbols;
    #endif
    5.定义回调函数
    typedef int ( * vlc_callback_t ) ( vlc_object_t *,      /* variable's object */
                                       char const *,            /* variable name */
                                       vlc_value_t,                 /* old value */
                                       vlc_value_t,                 /* new value */
                                       void * );                /* callback data */                                                 
    6.函数作为参数的定义方式
         Int Fun(int n,int (*pf)(int ,int),char *pstr)
    {   int j =10;
    pf(n,j);
    }
    7.回调函数的声明
    必须声明为global,或者static
    Int   vlc_callback_t (int ,int)
    {。。。。。。。。。。。}
           
    8.回调函数的使用
           Fun(0, vlc_callback_t,"test");
    9.函数表达式
    #define input_BuffersInit(a) __input_BuffersInit(VLC_OBJECT(a))
    void * __input_BuffersInit( vlc_object_t * );
    #define module_Need(a,b,c,d) __module_Need(VLC_OBJECT(a),b,c,d)
    VLC_EXPORT( module_t *, __module_Need, ( vlc_object_t *, const char *, const char *, vlc_bool_t ) );
    10.定义函数
       /* Dynamic array handling: realloc array, move data, increment position */
    #define INSERT_ELEM( p_ar, i_oldsize, i_pos, elem )                           \
        do                                                                        \
        {                                                                         \
            if( i_oldsize )                                                       \
            {                                                                     \
                (p_ar) = realloc( p_ar, ((i_oldsize) + 1) * sizeof( *(p_ar) ) );  \
            }                                                                     \
            else                                                                  \
            {                                                                     \
                (p_ar) = malloc( ((i_oldsize) + 1) * sizeof( *(p_ar) ) );         \
            }                                                                     \
            if( (i_oldsize) - (i_pos) )                                           \
            {                                                                     \
                memmove( (p_ar) + (i_pos) + 1,                                    \
                         (p_ar) + (i_pos),                                        \
                         ((i_oldsize) - (i_pos)) * sizeof( *(p_ar) ) );           \
            }                                                                     \
            (p_ar)[i_pos] = elem;                                                 \
            (i_oldsize)++;                                                        \
        }                                                                         \
        while( 0 )

    应用为:
         INSERT_ELEM( p_new->p_libvlc->pp_objects,
                         p_new->p_libvlc->i_objects,
                         p_new->p_libvlc->i_objects,
                         p_new );

    11.改变地址的方式传递其值
    stream_t *input_StreamNew( input_thread_t *p_input )
    {    stream_t *s = vlc_object_create( p_input, sizeof( stream_t ) );
        input_stream_sys_t *p_sys;
        if( s )
        {
            s->p_sys = malloc( sizeof( input_stream_sys_t ) );
            p_sys = (input_stream_sys_t*)s->p_sys;
            p_sys->p_input = p_input;
        }
    return s;//注解:s->p_sys改变了
    }
                                第二部分  程序框架实现
    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。
     
    本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/jsphuang/archive/2005/01/27/271133.aspx
  • 相关阅读:
    浏览器渲染原理
    前端日常工作性能优化条例
    前端的发展历程
    【YOLO-V1】You Only Look Once: Unified, Real-Time Object Detection
    ModuleNotFoundError: No module named 'keras_retinanet.utils.compute_overlap'
    python学习笔记:线性回归
    软件安装笔记5:navicat for mysql及其简单应用
    python学习笔记39:sklearn
    python学习笔记38:matplotlib
    python学习笔记37:pandas
  • 原文地址:https://www.cnblogs.com/qq78292959/p/2077030.html
Copyright © 2011-2022 走看看