VLC-黑客指南/如何编写模块

原文:https://wiki.videolan.org/Hacker_Guide/How_To_Write_a_Module/

本文由GOOGLE翻译,我只是搬运工~~

 

←返回黑客指南
LibVLC基于许多独立模块,如大多数竞争多媒体框架。每个模块都提供特定功能。

本文重点介绍如何向VLC(或任何其他LibVLC应用程序)添加新模块(也称为插件)。您需要先阅读 VLC核心和模块以及VLC如何加载模块,否则您将无法充实新模块的内容。

内容

 [ 隐藏 ] 

树内和树外模块

大多数现有VLC模块作为源代码提供在主VLC源代码存储库(以及源代码压缩包)中的目录模块中。它们与VLC核心同时编译,通常与VLC二进制包和安装程序一起提供。这些模块称为树内模块。

但是,也可以在VLC之外编写和编译VLC模块。这对于在树中开发模块有一些优点和缺点:

优点

  • 编译速度要快得多(VLC和其他模块不包含在流程中)。
  • 您可以使用自己的版本控制系统,甚至根本不使用。
  • 版权许可证不需要遵守VideoLAN协会的要求以包含在VLC中。
  • VLC开发人员无需提供,审查和接受源代码。
  • 发布计划独立于VLC版本。无论VLC发布计划如何,都可以随时发布新版本的模块。
  • 至少在理论上可以使用不同的编程语言。(主VLC代码库仅使用C,C ++和Lua,以及MacOS Objective C.)
  • 该模块可以使用不适合VLC依赖的软件库。

缺点

  • VLC开发人员不会审查代码,这将是提高代码质量的好机会。
  • VLC翻译人员不会在适用的情况下处理模块的本地化。VLC翻译成数十种语言。
  • 模块无法通过videolan.org网站分发,并使用VideoLAN基础设施,如错误跟踪器和构建机器人。
  • 模块仅适用于已编译的特定VLC(主要)版本。例如,为VLC 1.1.x编译的模块不适用于VLC 1.0.x或VLC 2.0.x.
  • 模块仅适用于已编译的特定操作系统和体系结构。例如,Windows 32位模块仅适用于Windows 32位版本的VLC。VLC支持许多不同的操作系统和体系结构组合。

示例存根模块

让我们从C语言中的一个小示例模块开始:

/**
 * @file hello.c
 * @brief Hello world interface VLC module example
 */
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
 
#include <stdlib.h>
/* VLC core API headers */
#include <vlc_common.h>
#include <vlc_plugin.h>
#include <vlc_interface.h>
 
/* Forward declarations */
static int Open(vlc_object_t *);
static void Close(vlc_object_t *);
 
/* Module descriptor */
vlc_module_begin()
    set_shortname(N_("Hello"))
    set_description(N_("Hello interface"))
    set_capability("interface", 0)
    set_callbacks(Open, Close)
    set_category(CAT_INTERFACE)
    add_string("hello-who", "world", "Target", "Whom to say hello to.", false)
vlc_module_end ()
 
/* Internal state for an instance of the module */
struct intf_sys_t
{
    char *who;
};
 
/**
 * Starts our example interface.
 */
static int Open(vlc_object_t *obj)
{
    intf_thread_t *intf = (intf_thread_t *)obj;
 
    /* Allocate internal state */
    intf_sys_t *sys = malloc(sizeof (*sys));
    if (unlikely(sys == NULL))
        return VLC_ENOMEM;
    intf->p_sys = sys;
 
    /* Read settings */
    char *who = var_InheritString(intf, "hello-who");
    if (who == NULL)
    {
        msg_Err(intf, "Nobody to say hello to!");
        goto error;
    }
    sys->who = who;
 
    msg_Info(intf, "Hello %s!", who);
    return VLC_SUCCESS;
 
error:
    free(sys);
    return VLC_EGENERIC;    
}
 
/**
 * Stops the interface. 
 */
static void Close(vlc_object_t *obj)
{
    intf_thread_t *intf = (intf_thread_t *)obj;
    intf_sys_t *sys = intf->p_sys;
 
    msg_Info(intf, "Good bye %s!", sys->who);
 
    /* Free internal state */
    free(sys->who);
    free(sys);
}

现在有关代码的一些解释......

模块描述符

一个VLC媒体播放器模块必须包括描述的本身,参数,它接受。

模块描述符以:

vlc_module_begin()

您应该设置有关模块的一些基本信息。这是为dvdread模块:

set_shortname(N_("DVD without menus"))
set_description(N_("DVDRead Input"))
set_category(CAT_INPUT)
set_subcategory(SUBCAT_INPUT_ACCESS)_ACCESS)

注意使用N_(“”)来创建需要由gettext翻译的字符串。

能力和得分

定义示例

set_capability("interface", 0)

这定义了一个“接口”功能模块,得分为0。

该功能决定了我们正在处理的模块类型。它可以是访问,解复用,解码器,接口等。现在是时候重新阅读VLC如何加载模块了

  • 如果VLC需要加载特定名称,它将按名称加载它,VLC直接打开该模块
  • 如果VLC需要一种模块(“我需要一个解码器”),VLC将按降序分数顺序加载所有匹配此功能的模块,直到一个模块的Open()函数(见下文)返回VLC_SUCCESS。

查看VLC的主要功能类型。

分数应为整数,并与同一类别中的其他分数相关。得分0是一个特例

配置类别和子类别

您应该使用一个的的预定义类别进行配置。配置类别和子类别指定其中的模块将出现在 UI对话框。

配置类别包括:

  • 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_directory,

有关完整定义,请参阅include / vlc_plugin.h

打回来

之后详述的激活和取消激活功能必须在描述符中定义。这样VLC核心就知道如何实例化和运行模块。

set_callbacks()宏允许您定义2个参数:第一个参数是pf_activate回调,第二个参数是pf_deactivate。但是,这些功能通常分别称为“打开”和“关闭”。如果/当需要一个提供正确接口的插件实例时,VLC会调用pf_activate回调,如set_capability()宏所声明的那样。

相反,当不再需要插件时,VLC会调用pf_deactivate回调 - 但前提是pf_activate回调先前返回了VLC_SUCCESS(0)。

打开(vlc_object_t *)

模块最重要的功能是开放:通常命名的Open()函数。

static int  Open ( vlc_object_t * );

当VLC核心试图打开模块并想要加载它时,将调用Open()函数。

在Open(),结构,设备或I / O的设置期间,应该进行检查。成功打开应该返回VLC_SUCCESS。如果模块无法完成初始化,则可以返回任何其他值,通常为VLC_EGENERIC或VLC_ENOMEM。

打开()函数预计分配私有数据(如果有的话),并设置了私结构。

如果Open失败,您可能需要在返回之前释放任何已分配的资源。否则,将发生泄漏。

关闭(vlc_object_t *)

模块的第二个最重要的功能是结束:通常命名的Close()函数。

static int  Close ( vlc_object_t * );

当VLC核心尝试关闭或卸载已加载的模块时,将调用Close()函数。

注意:如果Open()函数失败,则不会调用Close()。

在Close()期间,应关闭设备或I / O,并清理结构。不要在这里泄漏内存!

关闭()函数应该释放私有数据。

 

树内模块集成

混帐

如果您计划将工作提交到VLC上游,请务必查看git简介并查看发送补丁部分

编译你的模块

Modules.am

首先,在modules /下找到正确的子目录以添加新代码。

  1. 如果模块只有一个源代码文件模块,只需将其添加到子目录中(例如modules / control / hello.c)。
  2. 较大的模块应该获得自己的子子目录(例如modules / control / hello / *)。

然后,您需要在构建系统中声明该模块。例如,文件modules / control / Modules.am告诉构建系统每个控制模块需要哪些源文件。对于上面的示例,我们可以添加以下行:

libhello_plugin_la_SOURCES = hello.c
libhello_plugin_la_CFLAGS = $(AM_CFLAGS)
libhello_plugin_la_LIBADD = $(AM_LIBADD)
libhello_plugin_la_DEPENDENCIES =
# Always compile the hello module:
libvlc_LTLIBRARIES += libhello_plugin.la

请注意,Modules.am中的缩进(如果需要)使用制表符(ASCII 0x09),而不是空格。

configure.ac

如果模块依赖于某些新库,某些体系结构或某些操作系统特性,则可能需要扩展configure.ac以检测何时以及如何构建模块。有关详细信息,请参阅configure.ac文件和GNU autoconf文档

完成后,您只需要重建VLC:

 make

(这可能会触发autoconf和automake的重新运行,因此可能需要一段时间。)

加载您的模块

出于性能原因,VLC会保留可用模块的缓存。它应该自动更新。但您可以使用./vlc --reset-plugins-cache强制重置。

然后用

 ./vlc -vv --color --list

检查你的插件是否被VLC媒体播放器看到。

您还应该在Qt界面(Linux和Windows)的插件对话框中看到它。

树外模块

有一篇专门的文章。请读出树编译

子模块

子模块,在一些模块描述符中声明

 add_submodule()

工作方式与模块完全相同。当不同的模块(通常但不一定具有不同的功能)共享公共代码时,它们很有用。所有子模块都将包含在与主模块相同的运行时库中。

模块类型

根据模块功能,您将需要有关要实现的必要功能的更多信息。

我们将在这里详述:

模块负载故障排除

有时,在构建树内模块时,由于构建系统问题和其他不一致性,内容不起作用。

您可能需要转到VLC源树的根目录,并执行类似于以下操作的操作。这里的例子假设bash shell。

温和的版本

在某些情况下,automake依赖关系会中断(例如在某些文件名发生更改后)。这可能会起作用:

 find . -name .deps -exec rm -rf \{\} \;
 ./config.status
 make

...但并非总是如此,因此可能会因为总是使用下面的“中等版本”而节省一些麻烦。

中型(先试试)

这是一个更激进但仍然安全的重建程序:

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

至尊版

如果以上都没有帮助,您可以清理源树作为最后的手段。在继续之前,强烈建议您检查哪些文件将被删除:

git clean -nxd

然后检查您将丢失的源代码更改(如果有):

 git diff

使用以下命令可以非常轻松地完成整天的艰苦工作。第一个命令将永久删除任何未在git中跟踪的文件,包括您自己可能创建的文件。第二个命令将删除对现有文件的任何未提交的修改。考虑自己警告。

!!!请注意:这可能导致不可避免的数据丢失!

 git clean -fxd
 git reset --hard HEAD
 ./bootstrap
 ./configure
 make

此页面是官方VLC媒体播放器文档的一部分用户指南 • 流式传输方式 • 黑客指南 • 模块)在编辑文档之前,
请阅读文档编辑指南

根据自由软件基金会发布的GNU通用公共许可证条款,允许复制,分发和/或修改本文档; 许可证的第2版,或(根据您的选择)任何更高版本。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值