VLC媒体播放器系统结构

来源:互联网 发布:软件架构包含服务器吗 编辑:程序博客网 时间:2024/06/06 11:43
http://blog.csdn.net/buffi/article/details/7174421

VLC媒体播放器系统结构



VLC是免费和 开源跨平台多媒体播放器,一个可以播放大部分多媒体格式如DVDCDVCD和各种媒体流协议的框架。从技术来讲,只是一个处理计算机和网络上的媒体数据的软件包。VLC提供一套直观的API和模块化框架,可以很容易地添加新的编解码器,容器格式和传输协议。


源代码由C语言方面的专家编写。有时非常难以理解。要完全解释VLC播放器工作原理的话,可能需要编写一本书。我将努力用最少的语言文字来说明我对VLC源代码的研究的一些结果。让我们从最顶层的系统结构开始吧。

VLC由一个运行核和很多功能模块组成(200-400不等),VLC不能没有功能模块,很多功能都有由模块提供。主要有下面几个模块:


  • libVLCcore是框架的中心模块。提供一个面向对象的层给c语言写成的模块,进行模块装载,对多媒体操作的功能抽象,如:输入,复用,解复,语音输出,视频输出。

  • modules实现livVLCcore具体的功能,模块按照不同的能力进行分类。如输入管理模块(文件,网络),解码模块(mp3,dirvx),用户接口模块(文本,网页,telnet,等)

  • Externallibraries外部依靠文件,通常为具体的功能模块服务。

  • vlc (主要程序)–播放器主要入口,初始化libVLC,建立和显示用户接口(播放器窗口)。


功能模块

没有功能模块,VLC实际上是没有任何用处的。功能模块可以根据其能够提供的功能分类。每个具体的功能可以认为是类似面向对象的接口。模块装载简单解释如下:当VLC需要一个特别功能的模块(如解码功能)的时候,将打开所有的模块,然后找到一个最合适的。打开的时候按照匹配的分数按照从大到小进行排列,调用模块的Open()函数,如果返回OKVLC就使用该模块。(更多详情,可以参考”VLC如何装载模块”一文)。下图说明一些主要模块的功能。

VLC 提供不同风格的用户界面。每个界面也是一个模块。与VLC一起发布的界面有基于QT的用于rWindows/Linux的界面, 基于Cocoa/Objective-C用于OSX的界面,基于Ncurses用于DOS控制台的界面和用于Maemo设备的界面等。



下图说明功能模块代码在文件系统中存放结构,以modules/audio_output为例。

audio_output目录下实现了不同语音技术的输出:ALSA,PulseOSS,DirectXWindows平台)


面向对象的层 – VLC对象


VLC定义了一些管理模块的层,这些层使用面向对象开发方法。VLC对象的定义如下:

/***************************************************************************** * The vlc_object_t type. Yes, it's that simple :-) *****************************************************************************//** The main vlc_object_t structure */struct vlc_object_t{    VLC_COMMON_MEMBERS};

VLC_COMMON_MEMBERS is a C“#define” coded as the following:

/* VLC_COMMON_MEMBERS : members common to all basic vlc objects */#define VLC_COMMON_MEMBERS                                       \/** \name VLC_COMMON_MEMBERS                                     \ * these members are common for all vlc objects                  \ */                                                              \/**@{*/                                                          \  const char *psz_object_type;                                   \                                                                     \  /* Messages header */                                          \  char *psz_header;                                              \  int  i_flags;                                                  \                                                                     \  /* Object properties */                                        \  volatile bool b_die;                /**< set by the outside */ \  bool b_force;   /**< set by the outside (eg. module_need()) */ \                                                                     \  /* Stuff related to the libvlc structure */                    \  libvlc_int_t *p_libvlc;         /**< (root of all evil) - 1 */ \                                                                     \  vlc_object_t *  p_parent;                   /**< our parent */ \                                                                     \/**@}*/

src/misc/objects.c里面,定义了VLC对象的创建,销毁和查找方法:vlc_custom_create(..),vlc_object_destroy(...),vlc_object_find(...).例如,下面的例子创建一个心的VLC对象:

p_libvlc = vlc_custom_create( (vlc_object_t *)NULL,                         sizeof (*priv),VLC_OBJECT_GENERIC, "libvlc" );


LibVLC实例

VLC库的根类是libvlc实例,该类定义如下:

struct libvlc_instance_t{  libvlc_int_t *p_libvlc_int;  libvlc_vlm_t  libvlc_vlm;  unsigned      ref_count;  int           verbosity;  vlc_mutex_t   instance_lock;  struct libvlc_callback_entry_list_t *p_callback_list;};

这里 libvlc_int_t为一个vlc对象。在初始化过程中,指向一个类型为libvlc_priv_t的对象。



这个libvlc_priv_t类型包含库主要的数据和结构。如playlist_t(src/playlist/)为一个主要的抽象结构,表示媒体播放清单。vlm_t是服务器运行核的根对象,允许多个媒体流同时运行。VLC可以有不同的用户界面,这些界面模块功过p_intf变量指向的对象进行访问。

/** * Private LibVLC instance data. */typedef struct libvlc_priv_t{    . . . . . .    . . . . . .     bool               playlist_active;    /* Messages */    msg_bank_t        *msg_bank;    ///< The message bank    /* Singleton objects */    module_t          *p_memcpy_module;  ///< Fast memcpy plugin used    playlist_t        *p_playlist; //< the playlist singleton    vlm_t             *p_vlm;  ///< the VLM singleton (or NULL)    vlc_object_t      *p_dialog_provider; ///< dialog provider    httpd_t           *p_httpd; ///< HTTP daemon (src/network/httpd.c)    . . . . . .     . . . . . .    /* Interfaces */    struct intf_thread_t *p_intf; ///< Interfaces linked-list} libvlc_priv_t;


模块抽象和通信

正如当前谈到的,VLC是有一套功能模块组成。在开发过程中,主要分两个方面:

  • 初始化。调用open()close()函数。

  • 实现功能。实现每个具体的功能需要的方法。

例如,语音输出类模块需要实现下面的方法:

..................int aout_VolumeDown( vlc_object_t * p_object, int i_nb_steps,audio_volume_t * pi_volume )int aout_VolumeUp( vlc_object_t * p_object, int i_nb_steps, audio_volume_t * pi_volume )int aout_VolumeGet( vlc_object_t * p_object, audio_volume_t * pi_volume )int aout_ToggleMute( vlc_object_t * p_object, audio_volume_t * pi_volume )..................

视频输出类的模块需要实现下面的方法:

....................picture_t *vout_CreatePicture( vout_thread_t *p_vout, bool b_progressive,bool b_top_field_first,                               unsigned int i_nb_fields )void vout_DisplayPicture( vout_thread_t *p_vout, picture_t *p_pic )void DestroyPicture( vout_thread_t *p_vout, picture_t *p_picture )void vout_DropPicture( vout_thread_t *p_vout, picture_t *p_pic  )....................

另外一个VLC的基本概念是:按照“察看者/可察看“结构开发,这样可以降低模块之间的耦合度。这个结构通过VLC变量的这种概念实现。

所谓VLC变量是一个可以设置为任何VLC对象的值。令人感兴趣的是,这些变量可以激活回调函数。下面说明变量如何工作的:


  • 首先创建变量,使用 var_Create(p_libvlc, name, VLC_VAR_INTEGER )p_libvlc为指向vlc对象的指针,name为变量名称,VLC_VAR_INTEGER为类型。

  • 当需要设置变量的时候,调用var_SetInteger(p_libvlc, name, temp_value)之类的函数。temp_value是需要设置的值。对应地,可以使用var_getInteger将数据读取回来。

  • var_AddCallback(vlc_object_t *p_this, const char *psz_name,vlc_callback_tpf_callback, void *p_data )可以设置回调函数,psz_name为变量名称,pf_callback为函数指针,p_data为通用的函数指针,指向用户数据。

  • 当改变一个变量的值的时候,TriggerCallback(..)方法将会被调用,这样变量的察看者将会获得通知。

这个机制如何具体实现的呢?让在VLCncurses文本用户界面模块里面有一段代码:var_AddCallback(p_playlist, "playlist-item-append", PlaylistChanged, p_intf); 该代码的作用是:当 “playlist-item-append”变量发生变化时,PlaylistChanged()回调函数将会被调用。



这就是”察看者/可察看”结构的复杂执行的执行机制。

原创粉丝点击