OBS源
+ -

输入源实例加入场景

2024-06-23 9 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(&params, stack, sizeof(stack));
    calldata_set_ptr(&params, "scene", scene);
    calldata_set_ptr(&params, "item", item);
    signal_handler_signal(scene->source->context.signals, "item_add", &params);
    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链表中。

0 篇笔记 写笔记

作者信息
我爱内核
Windows驱动开发,网站开发
好好学习,天天向上。
取消
感谢您的支持,我会继续努力的!
扫码支持
扫码打赏,你说多少就多少

打开支付宝扫一扫,即可进行扫码打赏哦

您的支持,是我们前进的动力!