输入源实例加入场景
2024-06-23
29
0
新创建的源obs_source_t只有加入场景”sence”中才可以进行渲染使用。代码如下:
AddSourceData data;
data.source = source;
data.visible = visible;
obs_enter_graphics();
obs_scene_atomic_update(scene, AddSource, &data);
obs_leave_graphics();
可以看到,这里增加了一个指定的参数visible是否可显示。这是由用户创建源界面中是否显示指定。
其实这里为什么不直接放在源obs_source_t结构体的成员中呢?
struct AddSourceData {
obs_source_t *source;
bool visible;
obs_transform_info *transform = nullptr;
obs_sceneitem_crop *crop = nullptr;
obs_blending_method *blend_method = nullptr;
obs_blending_type *blend_mode = nullptr;
};
增加源到场是的回调函数为AddSource,其中obs_scene_atomic_update的代码很简单。就是为了防止sence被删除而增加引用计数。
void obs_scene_atomic_update(obs_scene_t *scene,
obs_scene_atomic_update_func func, void *data)
{
if (!scene)
return;
scene = obs_scene_get_ref(scene);
if (!scene)
return;
full_lock(scene);
func(data, scene);
full_unlock(scene);
obs_scene_release(scene);
}
AddSource函数如下:
static void AddSource(void *_data, obs_scene_t *scene)
{
AddSourceData *data = (AddSourceData *)_data;
obs_sceneitem_t *sceneitem;
sceneitem = obs_scene_add(scene, data->source);
if (data->transform != nullptr)
obs_sceneitem_set_info2(sceneitem, data->transform);
if (data->crop != nullptr)
obs_sceneitem_set_crop(sceneitem, data->crop);
if (data->blend_method != nullptr)
obs_sceneitem_set_blending_method(sceneitem, *data->blend_method);
if (data->blend_mode != nullptr)
obs_sceneitem_set_blending_mode(sceneitem, *data->blend_mode);
obs_sceneitem_set_visible(sceneitem, data->visible);
}
使用函数obs_scene_add将新源加入场景中。
obs_sceneitem_t *obs_scene_add(obs_scene_t *scene, obs_source_t *source)
{
obs_sceneitem_t *item = obs_scene_add_internal(scene, source, NULL, 0);
struct calldata params;
uint8_t stack[128];
if (!item)
return NULL;
calldata_init_fixed(¶ms, stack, sizeof(stack));
calldata_set_ptr(¶ms, "scene", scene);
calldata_set_ptr(¶ms, "item", item);
signal_handler_signal(scene->source->context.signals, "item_add", ¶ms);
return item;
}
obs_scene_add_internal的功能如下:
static obs_sceneitem_t *obs_scene_add_internal(obs_scene_t *scene,
obs_source_t *source,
obs_sceneitem_t *insert_after,
int64_t id)
{
struct obs_scene_item *last;
struct obs_scene_item *item;
pthread_mutex_t mutex;
struct item_action action = {.visible = true, .timestamp = os_gettime_ns()};
if (!scene)
return NULL;
//对需要被加入的源引用计数
source = obs_source_get_ref(source);
if (!source) {
blog(LOG_ERROR, "Tried to add a NULL source to a scene");
return NULL;
}
...
//这个与什么相关?
if (!obs_source_add_active_child(scene->source, source)) {
blog(LOG_WARNING, "Failed to add source to scene due to infinite source recursion");
pthread_mutex_destroy(&mutex);
goto release_source_and_fail;
}
item = bzalloc(sizeof(struct obs_scene_item));
item->source = source; //源
item->id = id ? id : ++scene->id_counter;
item->parent = scene;
item->ref = 1;
item->align = OBS_ALIGN_TOP | OBS_ALIGN_LEFT;
item->actions_mutex = mutex;
item->user_visible = true;
item->locked = false;
item->is_group = strcmp(source->info.id, group_info.id) == 0;
item->private_settings = obs_data_create();
item->toggle_visibility = OBS_INVALID_HOTKEY_PAIR_ID;
os_atomic_set_long(&item->active_refs, 1);
vec2_set(&item->scale, 1.0f, 1.0f);
matrix4_identity(&item->draw_transform);
matrix4_identity(&item->box_transform);
if (source_has_audio(source)) {
item->visible = false;
da_push_back(item->audio_actions, &action);
} else {
item->visible = true;
}
//item加入链表
full_lock(scene);
if (insert_after) {
obs_sceneitem_t *next = insert_after->next;
if (next)
next->prev = item;
item->next = insert_after->next;
item->prev = insert_after;
insert_after->next = item;
} else {
last = scene->first_item;
if (!last) {
scene->first_item = item;
} else {
while (last->next)
last = last->next;
last->next = item;
item->prev = last;
}
}
full_unlock(scene);
...
}
其实就是创建一个item,然后加入scene的item链表中。