织梦CMS - 轻松建站从此开始!

罗索

vlc学习计划(4)--VLC程序宏及线程分析

落鹤生 发布于 2010-06-28 22:31 点击:次 
VLC程序宏、线程、回调等相关架构的分析
TAG:

第一部分 变量及宏定义
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。

(jsphuang)
本站文章除注明转载外,均为本站原创或编译欢迎任何形式的转载,但请务必注明出处,尊重他人劳动,同学习共成长。转载请注明:文章转载自:罗索实验室 [http://www.rosoo.net/a/201006/9744.html]
本文出处:CSDN博客 作者:jsphuang
顶一下
(2)
66.7%
踩一下
(1)
33.3%
------分隔线----------------------------
发表评论
请自觉遵守互联网相关的政策法规,严禁发布色情、暴力、反动的言论。
评价:
表情:
用户名: 验证码:点击我更换图片
栏目列表
将本文分享到微信
织梦二维码生成器
推荐内容