libobs
是obs最核心的库,其他扩展插件都是基于libobs
(负责管理各个插件)
//模块信息结构体 obs\obs-studio\libobs\obs-internal.h 中定义
struct obs_module {
char *mod_name; //模块名
const char *file; //模块文件名
char *bin_path; //dll路径
char *data_path; //数据路径
void *module; //dll打开后的handle
bool loaded;
//模块的一些导出接口
bool (*load)(void); //加载模块时首先调用这个函数指针,每个模块都需要实现这个函数指针(obs_moudle_load 函数)
void (*unload)(void);
void (*post_load)(void);
void (*set_locale)(const char *locale);
bool (*get_string)(const char *lookup_string,
const char **translated_string);
void (*free_locale)(void);
uint32_t (*ver)(void);
void (*set_pointer)(obs_module_t *module);
const char *(*name)(void);
const char *(*description)(void);
const char *(*author)(void);
struct obs_module *next; //指向下一个模块
};
// obs\obs-studio\libobs\util\platform-windows.c 中定义
void *os_dlopen(const char *path) //打开dll
void *os_dlsym(void *module, const char *func) //dll中函数接口的导出地址
//示例:
struct obs_module mod = {0};
mod.module = os_dlopen(path);
load_module_exports(&mod, path);
static int load_module_exports(struct obs_module *mod, const char *path)
{
mod->load = os_dlsym(mod->module, "obs_module_load");
if (!mod->load)
return req_func_not_found("obs_module_load", path);
mod->set_pointer = os_dlsym(mod->module, "obs_module_set_pointer");
if (!mod->set_pointer)
return req_func_not_found("obs_module_set_pointer", path);
mod->ver = os_dlsym(mod->module, "obs_module_ver");
if (!mod->ver)
return req_func_not_found("obs_module_ver", path);
/* optional exports */
mod->unload = os_dlsym(mod->module, "obs_module_unload");
mod->post_load = os_dlsym(mod->module, "obs_module_post_load");
mod->set_locale = os_dlsym(mod->module, "obs_module_set_locale");
mod->free_locale = os_dlsym(mod->module, "obs_module_free_locale");
mod->name = os_dlsym(mod->module, "obs_module_name");
mod->description = os_dlsym(mod->module, "obs_module_description");
mod->author = os_dlsym(mod->module, "obs_module_author");
mod->get_string = os_dlsym(mod->module, "obs_module_get_string");
return MODULE_SUCCESS;
}
实现模块插件必要内容
- 包含头文件
#include
obs\obs-studio\libobs\obs-module.h 目录下- 包含
OBS_DECLARE_MODULE()
宏- 实现
bool obs_module_load(void)
(仅在头文件obs-module.h中定义,每个插件模块需要实现此函数)可选内容
- 包含
OBS_MODULE_USE_DEFAULT_LOCALE("win-dshow", "en-US")
默认语言处理相关的宏(虽非必须,但通常也都包含)void obs_module_unload(void)
void obs_module_post_load(void)
;void obs_module_set_locale(const char *locale)
;void obs_module_free_locale(void);
等
OBS_DECLARE_MODULE()
#define OBS_DECLARE_MODULE()
//静态模块变量
static obs_module_t *obs_module_pointer;
//两个导出接口函数
MODULE_EXPORT void obs_module_set_pointer(obs_module_t *module);
MODULE_EXPORT uint32_t obs_module_ver(void);
//设置变量值
void obs_module_set_pointer(obs_module_t *module)
{
obs_module_pointer = module;
}
//获得变量值
obs_module_t *obs_current_module(void) { return obs_module_pointer; }
//模块版本
uint32_t obs_module_ver(void) { return LIBOBS_API_VER; }
bool obs_module_load(void)
函数实现示例//win-dshow插件 obs\obs-studio\plugins\win-dshow\dshow-plugin.cpp 中定义
bool obs_module_load(void)
{
RegisterDShowSource();
RegisterDShowEncoders();
#ifdef VIRTUALCAM_ENABLED
obs_register_output(&virtualcam_info);
bool installed = vcam_installed(false);
#else
bool installed = false;
#endif
obs_data_t *obs_settings = obs_data_create();
obs_data_set_bool(obs_settings, "vcamEnabled", installed);
obs_apply_private_data(obs_settings);
obs_data_release(obs_settings);
return true;
}
OBS_MODULE_USE_DEFAULT_LOCALE
/** Optional: Use this macro in a module to use default locale handling. */
#define OBS_MODULE_USE_DEFAULT_LOCALE(module_name, default_locale) \
lookup_t *obs_module_lookup = NULL; \
const char *obs_module_text(const char *val) \
{ \
const char *out = val; \
text_lookup_getstr(obs_module_lookup, val, &out); \
return out; \
} \
bool obs_module_get_string(const char *val, const char **out) \
{ \
return text_lookup_getstr(obs_module_lookup, val, out); \
} \
void obs_module_set_locale(const char *locale) \
{ \
if (obs_module_lookup) \
text_lookup_destroy(obs_module_lookup); \
obs_module_lookup = obs_module_load_locale( \
obs_current_module(), default_locale, locale); \
} \
void obs_module_free_locale(void) \
{ \
text_lookup_destroy(obs_module_lookup); \
obs_module_lookup = NULL; \
}
//使用示例
OBS_MODULE_USE_DEFAULT_LOCALE("win-dshow", "en-US")
插件基本信息
- OBS插件是一些编译好的dll库,放在制定目录下,由
libobs
加载,然后调用os_dlopen
和os_dlsym
获得插件的对外接口- 插件目录结构
obs\obs-studio\build-vs2019\rundir\Debug\bin
->可执行程序目录 obs.exeobs\obs-studio\build-vs2019\rundir\Debug\data
->资源目录obs\obs-studio\build-vs2019\rundir\Debug\data\obs-plugins
->各个插件资源目录obs\obs-studio\build-vs2019\rundir\Debug\data\obs-plugins\win-dshow\locale
->win-dshow 插件下面的语言包obs\obs-studio\build-vs2019\rundir\Debug\obs-plugins\32bit
-> 所有插件dll位置
插件初始化过程
3.1 设置插件路径(.dll路径和插件data路径)
main():obs-app.cpprun_program():obs-app.cppOBSApp::OBSInit():obs-app.cppOBSBasic::OBSInit():window-base-main.cppAddExtraModulePaths 设置windows系统插件路径StartupOBSobs_startupobs_initadd_default_module_paths 设置默认插件路径 ../../obs-plugins/ ../../data/obs-plugins/%module%3.2 插件初始化
查找插件、设置插件路径obs_load_all_modules()查找所有插件并设置回调obs_find_modules(load_all_callback, NULL)在指定路径中查找插件 find_modules_in_path(struct obs_module_path *omp, obs_find_module_callback_t callback, void *param)处理每个查到的插件 process_found_module(omp, gi->gl_pathv[i].path, search_directories, callback, param);回调加载插件 load_all_callback()打开插件,并进行初始化 obs_open_module打开dll并导出函数 os_dlopen、load_module_exports初始化插件 obs_init_module调用每个插件实现的obs_module_load 函数 module->load()
obs_load_all_modules()
函数分析//obs\obs-studio\libobs\obs-module.c
void obs_load_all_modules(void)
{
profile_start(obs_load_all_modules_name);
obs_find_modules(load_all_callback, NULL); //查找所有模块
#ifdef _WIN32
profile_start(reset_win32_symbol_paths_name);
reset_win32_symbol_paths();
profile_end(reset_win32_symbol_paths_name);
#endif
profile_end(obs_load_all_modules_name);
}
void obs_find_modules(obs_find_module_callback_t callback, void *param)
{
if (!obs)
return;
for (size_t i = 0; i < obs->module_paths.num; i++)
{
struct obs_module_path *omp = obs->module_paths.array + i;
find_modules_in_path(omp, callback, param); //加载查找到的插件
}
}
//函数调用
find_modules_in_path() //加载插件
|os_glob()
|process_found_module() //处理插件
|info.bin_path = parsed_bin_path.array;
|info.data_path = parsed_data_dir;
|callback(param, &info); //调用回调传出插件信息(info)
|static void load_all_callback(void *param, const struct obs_module_info *info) //回调函数
|obs_open_module() //加载dll 获得模块基本信息和导出接口
|mod.module = os_dlopen(path);
|load_module_exports(&mod, path); //获得模块导出接口指针 对应 ## 2. 模块通用函数
|obs_init_module(module); //初始化模块
|module->loaded //此处调用插件自己实现的 bool obs_module_load(void)