obs_core结构体初始化
OBSBasic::OBSInit()函数的第一步是创建obs_core对构体,并对其进行初始化。实际为了防止重复初始化,该函数进行了简单的判断之后,使用的是函数是obs_init()来进行创建初始化。
bool obs_startup(void)
{
bool success;
if (obs) {
blog(LOG_WARNING, "Tried to call obs_startup more than once");
return false;
}
//1.申表obs_core内存
//2.初始化各个mutext和main_view的mutext
//3.注册obs_scene
success = obs_init();
if (!success)
obs_shutdown();
return success;
}
obs_init中使用bzalloc申请内存空间,并清0。使用obs_init_data()初始化成员。
最后注册一个输入源,类型为scene场景。
static bool obs_init(void)
{
obs = bzalloc(sizeof(struct obs_core));
if (!obs_init_data())
return false;
if (!obs_init_handlers())
return false;
obs_register_source(&scene_info);
return true;
}
申请内存空间bzalloc
bzalloc申请内存间,并请0
static inline void *bzalloc(size_t size)
{
void *mem = bmalloc(size);
if (mem)
memset(mem, 0, size);
return mem;
}
obs_init_data
obs_init_data用于初始化运行时的信息。主要是运行时添加删除源时的一些互斥体等。
obs_init_handlers
信号量及处理过程集。
static inline bool obs_init_handlers(void)
{
obs->procs = proc_handler_create();
if (!obs->procs)
return false;
//根据obs_signals数组解析并存储
obs->signals = signal_handler_create();
if (!obs->signals)
return false;
return signal_handler_add_array(obs->signals, obs_signals);
}
obs_signals的内容有:
static const char *obs_signals[] = {
"void source_create(ptr source)",
"void source_destroy(ptr source)",
"void source_add(ptr source)",
"void source_remove(ptr source)",
"void source_activate(ptr source)",
"void source_deactivate(ptr source)",
"void source_show(ptr source)",
"void source_hide(ptr source)",
"void source_volume(ptr source, in out float volume)",
"void channel_change(int channel, in out ptr source, ptr prev_source)",
"void master_volume(in out float volume)",
NULL
};
这里一个比较重的是通过parse_decl_string解析obs_signals数组中的每个字符串,解析函数名,返回类型及参数类型等。
注意 single_info中的callbacks中是一个数组,即一个种类型可以有多个回调。
bool signal_handler_add(signal_handler_t handler, const char *signal_decl)
{
struct decl_info func = {0};
struct signal_info *sig, *last;
bool success = true;
//根据字符串解析
if (!parse_decl_string(&func, signal_decl))
{
blog(LOG_ERROR, "Signal declaration invalid: %s", signal_decl);
return false;
}
pthread_mutex_lock(&handler->mutex);
sig = getsignal(handler, func.name, &last);//先判断是否已经存在
if (sig)
{
blog(LOG_WARNING, "Signal declaration '%s' exists", func.name);
decl_info_free(&func);
success = false;
}
else //不存在,则创建添加decl_info->signal_info
{
sig = signal_info_create(&func);
if (!last)
handler->first = sig;
else
last->next = sig;
}
pthread_mutex_unlock(&handler->mutex);
return success;
}
字符串的解析使用的是 c-family-parser实现的。
C-family parser 是一个针对 C 语言及其家族语言(如 C++、Objective-C 等)的开源解析器,主要用于编译器开发、代码分析和其他软件工具。下面是关于 C-family parser 的一些介绍、官网、学习资源和源码下载链接。
官方介绍
C-family parser 通常是指 Clang 提供的解析器。Clang 是一个开源 C/C++/Objective-C 编译器工具链,隶属于 LLVM 项目。Clang 提供了高效的 C-family 语言解析、语法分析和其他功能。官网
Clang 官方网站: https://clang.llvm.org/
LLVM 官方网站: https://llvm.org/
文档:https://clang.llvm.org/docs/