OBS源实例的创建过程obs_source_create
2024-03-22
57
0
OBS源实例的创建使用的是函数obs_source_create实现的
obs_source_t *obs_source_create(const char *id, const char *name,
obs_data_t *settings, obs_data_t *hotkey_data)
{
return obs_source_create_internal(id, name, NULL, settings, hotkey_data,
false, LIBOBS_API_VER);
}
- id为注册时的obs_source_info结构体中的id
- name:为创建实例时使用的标签名,用户可以随意命名,但不能和别的实例名冲突
obs_source_create_internal函数中,首先创建源的实例结构体obs_source。该结构体的一个成员是obs_source_info,obs_source_info就是注册的源类型.
struct obs_source { struct obs_context_data context; struct obs_source_info info; ... }
2.创建源是通过源ID来创建的,故需要先根据源找到obs_source_info。如果不存在,说明提供的是一个不存在的类型。如果存在,将源类型信息obs_source_info复制一份保存在struct obs_source的成员info中。
3.对源实例obs_source 进行初始化。初始化使用的obs_source_init_context函数实现。初始化主要源实例context和private_settings。static bool obs_source_init(struct obs_source *source) { ... obs_context_init_control(&source->context, source, (obs_destroy_cb)obs_source_destroy); source->deinterlace_top_first = true; source->audio_mixers = 0xFF; source->private_settings = obs_data_create(); return true; }
4.使用3中创建的context内容,调用create回调函数。
5.obs_source_init_finalize加入链表obs->data.sources。
static obs_source_t *
obs_source_create_internal(const char *id, const char *name, const char *uuid,
obs_data_t *settings, obs_data_t *hotkey_data,
bool private, uint32_t last_obs_ver)
{
//申请obs_source
struct obs_source *source = bzalloc(sizeof(struct obs_source));
const struct obs_source_info *info = get_source_info(id);
if (!info)
{
...
}
else
{
//保存源类型信息。其实感觉这里用指针感觉更好。
source->info = *info;
...
}
//创建context
if (!obs_source_init_context(source, settings, name, uuid, hotkey_data, private))
goto fail;
//默认参数获取get_defaults
if (info) {
if (info->get_defaults) {
info->get_defaults(source->context.settings);
}
if (info->get_defaults2) {
info->get_defaults2(info->type_data,source->context.settings);
}
}
//互斥体等基本初始化
if (!obs_source_init(source))
goto fail;
//调用Create回调函数
if (info && info->create)
source->context.data = info->create(source->context.settings, source);
//加入obs->data.sources链表
obs_source_init_finalize(source);
}
由于settings默认为NULL,故在obs_source_init_context会使用obs_data_newref创建一个。
context->settings = obs_data_newref(settings);
过程如下:
static inline obs_data_t *obs_data_newref(obs_data_t *data)
{
if (data)
obs_data_addref(data);
else
data = obs_data_create();
return data;
}
obs_data_t *obs_data_create()
{
struct obs_data *data = bzalloc(sizeof(struct obs_data));
data->ref = 1;
return data;
}
流程梳理
所以对于obs_source_create:
- get_defaults/get_defaults2 获取默认参数
- create 调用create,创建实例
- obs_source_init_context 初始化context.settings,使用函数obs_data_create创建一个。context.data是源对象结构体。
struct obs_context_data {
char *name;
const char *uuid;
void *data; //源对象
obs_data_t *settings; //配置参数
signal_handler_t *signals;
proc_handler_t *procs;
enum obs_obj_type type;
struct obs_weak_object *control;
obs_destroy_cb destroy;
DARRAY(obs_hotkey_id) hotkeys;
DARRAY(obs_hotkey_pair_id) hotkey_pairs;
obs_data_t *hotkey_data;
DARRAY(char *) rename_cache;
pthread_mutex_t rename_cache_mutex;
pthread_mutex_t *mutex;
struct obs_context_data *next;
struct obs_context_data **prev_next;
UT_hash_handle hh;
UT_hash_handle hh_uuid;
bool private;
};
上下文配置
上下文配置由context.settings指针指向一个obs_data_t的结构体。
typedef struct obs_data obs_data_t;
struct obs_data_item {
volatile long ref;
const char *name; //名称指针
struct obs_data *parent;
UT_hash_handle hh;
enum obs_data_type type;
size_t name_len;
size_t data_len;
size_t data_size;
size_t default_len;
size_t default_size;
size_t autoselect_size;
size_t capacity;
};
struct obs_data {
volatile long ref;
char *json;
struct obs_data_item *items;
};
以函数obs_data_set_default_int为示例:
obs_data_set_default_int(settings, "width", 400);
函数实现如下:
void obs_data_set_default_int(obs_data_t *data, const char *name, long long val)
{
obs_set_int(data, NULL, name, val, set_item_def);
}
struct obs_data_number {
enum obs_data_number_type type;
union {
long long int_val;
double double_val;
};
};
static inline void obs_set_int(obs_data_t *data, obs_data_item_t **item,
const char *name, long long val,
set_item_t set_item_)
{
struct obs_data_number num;
num.type = OBS_DATA_NUM_INT;
num.int_val = val;
set_item_(data, item, name, &num, sizeof(struct obs_data_number), OBS_DATA_NUMBER);
}
回调函数set_item_def内容如下:
static inline void set_item_def(struct obs_data *data, obs_data_item_t **item,
const char *name, const void *ptr, size_t size,
enum obs_data_type type)
{
obs_data_item_t *actual_item = NULL;
if (!data && !item)
return;
if (!item) {
actual_item = get_item(data, name);
item = &actual_item;
}
if (*item && (*item)->type != type)
return;
set_item_data(data, item, name, ptr, size, type, true, false);
}
其最终使用如下实现参数ITEM的创建与获取:
- HASH_ADD_STR
- HASH_FIND_STR