OBS
+ -

obs_display及render_displays

2024-06-03 7 0

一个obs_display_t是一个渲染组,其与窗口HWND绑定,也可以认为其代表一个交换链。

render_displays是显示渲染的结果,可以有多个,与窗口HWND绑定

obs_display_t创建

在OBS中其实就是输出主窗口。其结绝体如下:

/* displays */

struct obs_display {
    bool update_color_space;
    bool enabled;
    uint32_t cx, cy;
    uint32_t next_cx, next_cy;
    uint32_t background_color;

    gs_swapchain_t *swap; //交换链

    pthread_mutex_t draw_callbacks_mutex;
    pthread_mutex_t draw_info_mutex;
    DARRAY(struct draw_callback) draw_callbacks;
    bool use_clear_workaround;

    struct obs_display *next;
    struct obs_display **prev_next;
};

其创建一个obs_display_t时,需要的参数如下:

struct gs_init_data {
    struct gs_window window; //窗口句柄
    uint32_t cx, cy;  //长宽
    uint32_t num_backbuffers;
    enum gs_color_format format;//GS_BGRA
    enum gs_zstencil_format zsformat;/GS_ZS_NONE
    uint32_t adapter;  //适配器索引,应该与窗口句柄互斥
};

所以其创建时:

    gs_init_data info = {};
    info.cx = size.width();
    info.cy = size.height();
    info.format = GS_BGRA;
    info.zsformat = GS_ZS_NONE;

    if (!QTToGSWindow(windowHandle(), info.window))
        return;

    display = obs_display_create(&info, backgroundColor);

新创建的obs_display_t其实是以链表互连,其头指针为obs->data.first_display。新增加一个时,也仅是互链指针而已

obs_display_t *obs_display_create(const struct gs_init_data *graphics_data,
                  uint32_t background_color)
{
    struct obs_display *display = bzalloc(sizeof(struct obs_display));

    gs_enter_context(obs->video.graphics);

    display->background_color = background_color;

//初始化交换链
    if (!obs_display_init(display, graphics_data))
    {
        obs_display_destroy(display);
        display = NULL;
    }
    else
    {
        //通过链表相连
        pthread_mutex_lock(&obs->data.displays_mutex);
        display->prev_next = &obs->data.first_display;
        display->next = obs->data.first_display;
        obs->data.first_display = display;
        if (display->next)
            display->next->prev_next = &display->next;
        pthread_mutex_unlock(&obs->data.displays_mutex);
    }

    gs_leave_context();
    return display;
}

obs_display_t渲染调用

在视频渲染线程中:

  • obs_graphics_thread
    • obs_graphics_thread_loop
      • render_displays

render_displays函数其实就是从链表中找到第一个obs_display,并调用render_display

static inline void render_displays(void)
{
    /* render extra displays/swaps */
    pthread_mutex_lock(&obs->data.displays_mutex);

    display = obs->data.first_display;
    while (display)
    {
        render_display(display);
        display = display->next;
    }

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

对于render_display函数,对于其draw_callbacks进行调用绘图,最终调用gs_present进行上屏


void render_display(struct obs_display *display)
{
    uint32_t cx, cy;
    bool update_color_space;

    if (!display || !display->enabled)
        return;

    /* -------------------------------------------- */
    pthread_mutex_lock(&display->draw_info_mutex);

    cx = display->next_cx;
    cy = display->next_cy;
    update_color_space = display->update_color_space;
    display->update_color_space = false;

    pthread_mutex_unlock(&display->draw_info_mutex);
    /* -------------------------------------------- */


    if (render_display_begin(display, cx, cy, update_color_space)) 
    {
        GS_DEBUG_MARKER_BEGIN(GS_DEBUG_COLOR_DISPLAY, "obs_display");

        pthread_mutex_lock(&display->draw_callbacks_mutex);
        for (size_t i = 0; i < display->draw_callbacks.num; i++)
        {
            struct draw_callback *callback;
            callback = display->draw_callbacks.array + i;
            callback->draw(callback->param, cx, cy);
        }
        pthread_mutex_unlock(&display->draw_callbacks_mutex);

        render_display_end();
        GS_DEBUG_MARKER_END();

        //上屏
        gs_present();
    }
}

draw_callbacks

可以看到,分别使用draw_callbacks来进行绘制。怎么绘制以及怎么图像融合,需要看draw_callbacks的相关信息。
对于每一个draw_callback,其是一个回调函数以及回调函数对应的参数。

struct draw_callback {
    void (*draw)(void *param, uint32_t cx, uint32_t cy);
    void *param;
};

其通过函数obs_display_add_draw_callback增加的。

void obs_display_add_draw_callback(obs_display_t *display,
                   void (*draw)(void *param, uint32_t cx,uint32_t cy),
                   void *param)
{
    if (!display)
        return;

    struct draw_callback data = {draw, param};

    pthread_mutex_lock(&display->draw_callbacks_mutex);
    da_push_back(display->draw_callbacks, &data);
    pthread_mutex_unlock(&display->draw_callbacks_mutex);
}

使用此函数的类有:

  • OBSBasicFilters::OBSBasicFilters 滤镜的
  • OBSBasicInteraction::OBSBasicInteraction
  • OBSBasic::CreateProgramDisplay
  • OBSBasic::OBSInit
    • OBSBasicProperties::OBSBasicProperties /OBSBasicProperties::DrawPreview
    • OBSBasicProperties::OBSBasicProperties/OBSBasicProperties::DrawTransitionPreview
  • OBSProjector::OBSProjector

0 篇笔记 写笔记

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

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

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