OBS渲染架构
2024-07-24
18
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
- render_main_texture
- render_video
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
- obs_transition_set
以上是正常的流程,本人强制使用代码将
#if 1
obs_set_output_source(0, curScene);//这里强制将转换设置为当前场景
#endif
将channel[0]中的内容替换为curScene也是可以正常工作的。所以这里不再分析transition是干什么用。