OBS源
+ -

obs_source与渲染互联

2024-06-24 10 0

使用obs_source_create_internal新创建的输入源,调用了create回调函数后,最后会调用obs_source_init_finalize函数。

static void obs_source_init_finalize(struct obs_source *source)
{
    if (is_audio_source(source))
    {
        pthread_mutex_lock(&obs->data.audio_sources_mutex);

        source->next_audio_source = obs->data.first_audio_source;
        source->prev_next_audio_source = &obs->data.first_audio_source;
        if (obs->data.first_audio_source)
            obs->data.first_audio_source->prev_next_audio_source =&source->next_audio_source;
        obs->data.first_audio_source = source;

        pthread_mutex_unlock(&obs->data.audio_sources_mutex);
    }

    if (!source->context.private) {
        obs_context_data_insert_name(&source->context,
                         &obs->data.sources_mutex,
                         &obs->data.public_sources);
    }

    //插入obs->data.sources中。
    obs_context_data_insert_uuid(&source->context, &obs->data.sources_mutex, &obs->data.sources);
}

可以看到,这里与全局变量obs的成员data相关,即将新创建的源使用obs_context_data_insert_uuid插入链表obs->data.sources中。

struct obs_core {
...
    struct obs_core_video video;
    struct obs_core_audio audio;
    struct obs_core_data data;
...
};

struct obs_core_data中应是一些通过模块创建的对象。

/* user sources, output channels, and displays */
struct obs_core_data {
    /* Hash tables (uthash) */
    struct obs_source *sources;        /* Lookup by UUID (hh_uuid) */
    struct obs_source *public_sources; /* Lookup by name (hh) */

    /* Linked lists */
    struct obs_source *first_audio_source;
    struct obs_display *first_display;
    struct obs_output *first_output;
    struct obs_encoder *first_encoder;
    struct obs_service *first_service;

    pthread_mutex_t sources_mutex;
    pthread_mutex_t displays_mutex;
    pthread_mutex_t outputs_mutex;
    pthread_mutex_t encoders_mutex;
    pthread_mutex_t services_mutex;
    pthread_mutex_t audio_sources_mutex;
    pthread_mutex_t draw_callbacks_mutex;
    DARRAY(struct draw_callback) draw_callbacks;
    DARRAY(struct rendered_callback) rendered_callbacks;
    DARRAY(struct tick_callback) tick_callbacks;

    struct obs_view main_view;

    long long unnamed_index;

    obs_data_t *private_data;

    volatile bool valid;

    DARRAY(char *) protocols;
    DARRAY(obs_source_t *) sources_to_tick;
};

在视频线程obs_graphics_thread中,循环调用obs_graphics_thread_loop。

bool obs_graphics_thread_loop(struct obs_graphics_context *context)
{
...
    context->last_time = tick_sources(obs->video.video_time, context->last_time);
...
    //内容输出
    profile_start(output_frame_name);
    output_frames();
    profile_end(output_frame_name);


    //render_displays是显示渲染的结果,可以有多个,与窗口HWND绑定
    profile_start(render_displays_name);
    render_displays();
    profile_end(render_displays_name);
...
}

tick_sources中对所有增加的源进行渲染

atic uint64_t tick_sources(uint64_t cur_time, uint64_t last_time)
{
    struct obs_core_data *data = &obs->data;
    struct obs_source *source;
    uint64_t delta_time;
    float seconds;

    if (!last_time)
        last_time = cur_time - obs->video.video_frame_interval_ns;

//delta_time实际上就是obs->video.video_frame_interval_ns帧率的时间间隔
    delta_time = cur_time - last_time;

//将它转成秒级
    seconds = (float)((double)delta_time / 1000000000.0);

    /* ------------------------------------- */
    /* call tick callbacks                   */
    pthread_mutex_lock(&data->draw_callbacks_mutex);
    for (size_t i = data->tick_callbacks.num; i > 0; i--) 
    {
        struct tick_callback *callback = data->tick_callbacks.array + (i - 1);
        callback->tick(callback->param, seconds);
    }
    pthread_mutex_unlock(&data->draw_callbacks_mutex);

    /* ------------------------------------- */
    /* get an array of all sources to tick   */
    da_clear(data->sources_to_tick);

    pthread_mutex_lock(&data->sources_mutex);

//对加入的源于进行引数计数,后面调用obs_source_video_tick渲染。
    source = data->sources;
    while (source) 
    {
        //增加引用计数
        obs_source_t *s = obs_source_get_ref(source);
        if (s)
        {
            da_push_back(data->sources_to_tick, &s);
        }
        source = (struct obs_source *)source->context.hh_uuid.next;
    }
    pthread_mutex_unlock(&data->sources_mutex);

    /* ------------------------------------- */
    /* call the tick function of each source */
    for (size_t i = 0; i < data->sources_to_tick.num; i++) 
    {
        obs_source_t *s = data->sources_to_tick.array[i];
        //秒级调用???
        obs_source_video_tick(s, seconds);

        //减少引用计数,如果为0销毁,模块了COM的接引用
        obs_source_release(s);
    }

    return cur_time;
}

最终调用obs_source_video_tick进行渲染。
obs_source_video_tick其实应只是针对的是采样数据用的,采格到的数据放在source->context.data中,数据读取到后进行渲染。

0 篇笔记 写笔记

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

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

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