Chinaunix首页 | 论坛 | 博客
  • 博客访问: 859269
  • 博文数量: 1384
  • 博客积分: 27795
  • 博客等级: 上将
  • 技术积分: 16887
  • 用 户 组: 普通用户
  • 注册时间: 2011-04-12 09:28
个人简介

只是心态,抓住机会。

文章分类

全部博文(1384)

文章存档

2014年(3)

2013年(403)

2012年(978)

分类: LINUX

2012-09-12 22:48:16

1.vlc.c 只是入口程序

2.Libvlc.c 是各个模块的结合点,这要是对接口编程

· Vlc_Create(): 两个重要的数据结构:libvlc_t & vlc_t , 所有的参数传递都在这里面 

· Vlc_Init(): 初始化参数, module_bank 

· Vlc_AddInf(): 添加module 

3./src/misc/configure.c 命令行参数和参数文件分析
参数文件是~/.vnc/vlcrc。其中可以设置log文件的位置

4./include/ 所有头文件的集合 

5./src/interface/Interface.h 所有module的集合

6./src/misc/Modules.c
其中module_t * __module_Need( vlc_object_t *p_this, const char *psz_capability,
                          const char *psz_name, vlc_bool_t b_strict ) 方法是寻找合适的interface
如果找到合适的,就调用AllocatePlugin()动态的分配一个。

7.how to link to different modules without OOP

VLC中网络数据流接收处理过程分析

[ 2007-11-25 19:45:00 | By: zyjzyj2000 ]

 

网络数据流接收处理分析

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、在下列函数中:

A. 分离出access  , demux  , name字符串 ; 

B. 根据分离出的access  字符串通过module_Need函数找到acess 指针模块; 

C. 根据分离出的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_RunDecodersrc\input\input_dec.c->DecoderThread->DecoderDecode ->vout_DisplayPicture



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

阅读(2462) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~