obs_core_video_mix
+ -

OBS渲染架构

2024-07-24 14 0

OBS最顶层的是obs_core_video_mix,所以的obs_core_video_mix都通过数组存储在obs->video.mixes.array[]的数组中,但一般只有一个obs_core_video_mix。

obs_core_video_mix结构体中有成员obs_view指针,该成员下有64个通道。

struct obs_core_video_mix {
    struct obs_view *view;
    ...
}
struct obs_view {
    pthread_mutex_t channels_mutex;
    obs_source_t *channels[MAX_CHANNELS];//64
};

obs_view下的64个通道是这样分配的:

  • 0通道是用于图像渲染的。
  • 1通道是桌面音频1
  • 2通道是桌面音频2
  • 3通道是AuxAudioDevice1
  • 4通道是AuxAudioDevice2
  • 5通道是AuxAudioDevice3
  • 6通道是AuxAudioDevice4

在函数OBSBasic::LoadData中有代码如下:

void OBSBasic::LoadData(obs_data_t *data, const char *file)
{
    LoadAudioDevice(DESKTOP_AUDIO_1, 1, data);
    LoadAudioDevice(DESKTOP_AUDIO_2, 2, data);
    LoadAudioDevice(AUX_AUDIO_1, 3, data);
    LoadAudioDevice(AUX_AUDIO_2, 4, data);
    LoadAudioDevice(AUX_AUDIO_3, 5, data);
    LoadAudioDevice(AUX_AUDIO_4, 6, data);

    SetTransition(curTransition)  ==> obs_set_output_source(0, transition);
    ....
    SetCurrentScene(curScene, true);
}

OBSBasic::LoadData函数则是根据配置文件来初始化OBS.

说完了数据结构的初始化后,再看渲染过程。

bool obs_graphics_thread_loop(struct obs_graphics_context *context)
{
    output_frames()
    {
        for (size_t i = 0, num = obs->video.mixes.num; i < num; i++) 
        {
            struct obs_core_video_mix *mix = obs->video.mixes.array[i];
            if (mix->view) 
            {
                output_frame(mix);
            }
        }
    }
}

output_frame调用render_video来进行渲染

  • output_frame
    • render_video
      • render_main_texture
        • obs_view_render
void obs_view_render(obs_view_t *view)
{
    for (size_t i = 0; i < MAX_CHANNELS; i++) 
    {
        struct obs_source *source = view->channels[i];
        if (source)
        {
                obs_source_video_render(source);
        }
    }
}

渲染的0通道是fade_transition,故渲染调用的是其回调函数fade_video_render,里面调用的其实scene的obs_source_video_render。

scence与transition

scene是被transition封装。
在viewe的channels通道0中的是transition,故在渲染时其实调用transition的渲染函数最终调用的是scene的渲染,而在scene中渲染所有它的子对象。

void OBSBasic::LoadData(obs_data_t *data, const char *file)
{
...
    SetTransition(curTransition);
...
    SetCurrentScene(curScene, true);
    ....
}

SetTransition将是将当前curTransition设置为0通道
而SetCurrentScene是将当前的curScene调用obs_transition_set(transition, source)的源。

  • SetCurrentScene
    • obs_transition_set
      • obs_source_add_active_child

以上是正常的流程,本人强制使用代码将

    #if 1
    obs_set_output_source(0, curScene);//这里强制将转换设置为当前场景
    #endif

将channel[0]中的内容替换为curScene也是可以正常工作的。所以这里不再分析transition是干什么用。

0 篇笔记 写笔记

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

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

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