OBS源
+ -

OBS源实例的创建过程obs_source_create

2024-03-22 50 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:为创建实例时使用的标签名,用户可以随意命名,但不能和别的实例名冲突
  1. 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

0 篇笔记 写笔记

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

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

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