现在的位置: 首页 > 自动控制 > 工业·编程 > 正文

VLC功能模块编程指南

2013-07-12 06:41 工业·编程 ⁄ 共 6146字 ⁄ 字号 暂无评论

VLC建立在很多独立的功能模块上面的,象很多媒体播放器系统框架一样,每个模块实现一个新的功能。在阅读本文之前,必须先行阅读“VLC运行核及功能模块”和“VLC如何装载功能模块”章节。本文叙述如何为VLC编写一个新的功能模块。

Git与资源库操作

Git

如果你打算将你的工作上传到VLC,首先请阅读”git简介”一节,除此以外,还要检查”发送补丁”页里面的内容。

编译模块
Modules.am

首先在modules目录下,找到正确的存放代码的位置。

  1. 如果只是增加单文件模块到资源库,只需要添加该文件到moduels.am所在的目录。

  2. 如果需要添加比较大的模块到资源库:

    • 创建一个新目录

    • 在新目录下面创建一个新的Modules.am.

    • 在configure.ac文件末尾添加对应的一行语句,用于m akefile。

例如, modules/video_filter/Modules.am文件告诉编译系统哪些源代码将加入videofilter模块。

注意: modules.am里面的缩进使用tab键(ASCII0x09),不是空隔键。

configure.ac

为了使模块可以编译,还需要在configure.ac添加VLC_ADD_PLUGINPKG_ENABLE_MODULES_VLC语句,以新模块的名称作为参数。还要参照其它模块编译和链结所需要的参数,进行相应的添加。

当修改configure.ac以后,必须重新运行./bootstrap&& ./configure

装载模块

VLC 保留模块的缓冲区,用户不应该清除,但是,可以使用vlc–reset-plugins-cache来强行重启。

然后使用

vlc -vvv --color --list

检查插件是否可见。 也可以在QT开发的图形界面下查看。

一个空模块的例子

下面是一个很小的例子,有助于更好的理解。

/*****************************************************************************
 * Preamble
 *****************************************************************************/

#ifdef HAVE_CONFIG_H
# include "config.h"
#endif

#include <vlc_common.h>
#include <vlc_plugin.h>

/*****************************************************************************
* Local prototypes.
*****************************************************************************/

static int  Open           ( vlc_object_t * );
static void Close          ( vlc_object_t * );

/*****************************************************************************
 * Module descriptor
 *****************************************************************************/

vlc_module_begin()
    set_shortname( _("testmodule") )
    set_description( _("testmodle plug-in") )
    set_capability( "testing", 0 )
    set_callbacks( Open, Close )
    set_category( CAT_INTERFACE ) /* 定义模块分类,默认的一些类别在vlc/include/vlc_configuration.h 中定义*/

    add_integer( "test-angle", 1, "DVD Angle", "Default DVD Angle", false)
vlc_module_end ()


/*****************************************************************************
 * Open: 初始化接口
 *****************************************************************************/
static int Open( vlc_object_t *p_this )
{
}

/*****************************************************************************
 * Close: 销毁接口
 *****************************************************************************/
static void Close( vlc_object_t *p_this )
{
}

编写模块

模块描述表

VLC播放器模块必须包含一个自身的描述表,以及它可以接受的参数。

模块描述表使用vlc_module_begin()开始。

然后设置基本的信息:

    set_shortname( _("DVD without menus") );
    set_description( _("DVDRead Input") );
    set_category( CAT_INPUT );
    set_subcategory( SUBCAT_INPUT_ACCESS );

注意: _("")可以用来创建需要翻译的字符串。

能力和匹配分数

能力是模块可以装载的关键 。它定义模块的类型,即是否是数据读取模块,解复模块,还是其它类型的模块。VLC如何装载以及VLC能力的主要类型详情,请参考”VLC如何装载功能模块”一文。

  • 如果VLC装载具体模块名称,直接打开。

  • 如果VLC需要装载某一类型的功能模块(如解码器),VLC将装载所有的具有该能力的模块,按照匹配分数降序排列,然后调用Open()函数,如果返回VLC_SUCCESS,结束。

分数是一个整数,是一个与同一类功能模块的相对值。分数为0的时候,一种特例。下面是一个定义实例:

   set_capability( "testing", 10 )

该语句定义testing能力为10.

分类和子类的配置

使用其中一个预定义的分类进行配置。分类和子类的配置决定功能模块的优先顺序。

配置分类包括:

  • CAT_INTERFACE

  • CAT_AUDIO

  • CAT_VIDEO

  • CAT_INPUT

  • CAT_SOUT

  • CAT_ADVANCED

  • CAT_PLAYLIST

同时,也应该使用某一个子类进行配置。所有的配置分类和子类的定义,参考include/vlc_configuration.h

配置和参数选项

如果需要给模块添加新的选项,按照下面的语句进行:

 add_integer(name, value, text, longtext, advanced) 
  • name是参数的标识,在命令行控制台里面可以用来设置参数的值

  • value参数的默认值。

  • text参数的简单描述,使用 _("")创建需要翻译的字符串。

  • longtext完整的参数描述,使用_("")可以创建需要翻译的文本。

  • advanced布尔值,如果为TRUE,对应的参数仅仅在—advanced选项的时候显示。

你可以添加下面的选项或参数到模块里面:

  • add_integer,

  • add_string,

  • add_float,

  • add_bool,

  • add_key,

  • add_file,

  • add_directory,

完整定义,请参看 include/vlc_plugin.h。

回调

模块打开和关闭的函数(随后详细介绍)需要在模块描述表里面定义,这样VLC才可以与模块进行交互。

set_callbacks()宏可以定义两个参数:第一个参数是pf_activate回调函数,第二个是pf_deactivate回调函数。VLC当需要一个插件实例提供正确接口的时候,调用pf_activate回调函数, 像宏里面set_capability()制定的一样。

Open(vlc_object_t*)

最重要的模块函数是打开函数:

static int  Open ( vlc_object_t * );

VLC运行核尝试打开模块的时候,将调用该函数,进行模块装载。

在Open函数里面,设置各种结构,设备或I/O。可以正常打开的函数将返回VLC_SUCCESS。否则,将认为装载失败。

Open函数里面还进行私有数据的分配(如有),对私有结构进行设置。如果打开失败,需要用户自己清理结构里面的资源。

Close(vlc_object_t*)

第二个最重要的函数是关闭函数,其声明如下:

static int  Close ( vlc_object_t * );

VLC运行核尝试关闭或卸载模块的时候,调用Close函数。

在关闭函数里面,将清理一些数据结构,I/O或设备。同时,关闭函数也释放一些私有数据。

子模块

子模块,如使用add_submodule()语句进行添加

与模块工作原理一样,这写模块对父模块非常有用,可以在模块之间代码公用。子模块在缓冲区分开存放,装载方式与模块一样。

模块类型

根据模块的能力的类别不同,需要实现的函数或方法也不一样,用户可以在相应的模块分类里面找到更多的信息。下面是一些主要的模块类别清单:

  • Access/获取

  • Demux/解复

  • Access_Demux / 获取并解复

  • Decoder/解码

  • Interface/用户界面

  • Videofilter / 视频滤波

  • Audiofilter /音频滤波

  • Audio output /语音输出

模块装载时的常见问题

有些时候,模块可能不正常工作,这时,需要转入到VLC源代码树的顶层目录,做下面的一些工作。这里假设使用bashshell.

保险方法 (先试)
  1. 编译文件和环境准备

find . -name .deps -exec rm -rf \{\} \;
./bootstrap
./configure

rm-rf选项具有递归功能,删除在源代码树里面的依赖缓冲区。它可以保证编译器自动查找新的文件。

  1. 编译

./compile
  1. 最后运行:

./vlc --reset-plugins-cache
省事方法

有时候,重设config.status里面的.deps缓冲区就可以了:

find . -name .deps -exec rm -rf \{\} \;
./config.status
./compile
./vlc --reset-plugins-cache

如果仅仅上面的几行不能凑效,请按照保险方法进行。

终极方法

当上面的方法还不能解决问题,可以按照下面的方法进行:

find . -name .deps -exec rm -rf \{\} \;
find . -name .libs -exec rm -rf \{\} \;
./bootstrap
./configure
./compile
./vlc --reset-plugins-cache

上面的过程同样删除库缓冲。在这个过程中必须运行configure,而不是config.status,后者在--no-create模式下运行configure,不会重新创建.lib缓冲。

独立的模块编译

为了能够避免编译整个的VLC源代码,可以单独对一些功能模块进行编译。这样在有些情况下非常有用的。例如新的模块由于只是版权问题不能随VLC一起发布。单独编译可以降低VLC的依赖,增加模块的独立性。

国际化

独立的模块不能使用VLC的主国际化域。需要添加自己的域。声明如下:

#define DOMAIN  "vlc-myplugin"
#define _(str)  dgettext(DOMAIN, str)
#define N_(str) (str)

/* ... */

vlc_module_begin()
   set_text_domain (DOMAIN)
   set_description (N_("My plugin"))
   /* ... */
vlc_module_end()

或者完全禁止国际化:

#define _(str)  (str)
#define N_(str) (str)
关键字

为了保证VLC能装载模块,需要定义 __PLUGIN__关键字.这个可以使输出的符号类似下面的几行:(该处译者不甚明白,请参照原文。)

EXPORTS
vlc_entry__1_1_0g
vlc_entry_license__1_1_0g

同样,还可以定义__LIBVLC__关键字。

编译

使用简单makefile

下面的Makefile是VLC的X264模块的例子。

libdir = $(shell pkg-config --variable=libdir vlc-plugin )
vlclibdir = $(libdir)/vlc

all: libx264_plugin.so
 
libx264_plugin.so: libx264_plugin.o
        gcc -shared -std=gnu99 $< `pkg-config  --libs vlc-plugin x264`  -Wl,-soname -Wl,$@ -o $@
 
libx264_plugin.o: x264.c
        gcc -c -std=gnu99  $< `pkg-config  --cflags vlc-plugin x264` -D__PLUGIN__  -DMODULE_STRING=\"x264\" -o $@  
 
clean:
        rm -f libx264_plugin.o libx264_plugin.so

install: all
        mkdir -p $(DESTDIR)$(vlclibdir)/
        install -m 0755 libx264_plugin.so $(DESTDIR)$(vlclibdir)/

install-strip: all
        mkdir -p $(DESTDIR)$(vlclibdir)/
        install -s -m 0755 libx264_plugin.so $(DESTDIR)$(vlclibdir)/

uninstall:
        rm -f -- $(DESTDIR)$(vlclibdir)/libx264_plugin.so

.PHONY: all clean install uninstall
使用自动工具

如果使用automake和libtool,按照下面Makefile.am例子进行:

vlclibdir = $(libdir)/vlc

vlclib_libx264_plugin_la_SOURCES = x264.c
vlclib_libx264_plugin_la_CFLAGS = $(VLC_PLUGIN_CFLAGS) $(X264_CFLAGS) \
      -D__PLUGIN__ -DMODULE_STRING=\"x264\"
vlclib_libx264_plugin_la_LIBADD = $(VLC_PLUGIN_LIBS) $(X264_LIBS)
vlclib_libx264_plugin_la_LDFLAGS = \
      -avoid-version -module -export-symbol-regex ^vlc_entry

给我留言

留言无头像?