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

类别:编程语言 点击:0 评论:0 推荐:
第一部分 变量及宏定义 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。

本文地址:http://com.8s8s.com/it/it23401.htm