obs_core_video_mix使用
2024-07-01
13
0
obs_core_video_mix使用在视频线程,其总的入口调用函数为output_frames()。
bool obs_graphics_thread_loop(struct obs_graphics_context *context)
{
...
//GPU渲染并内容输出
profile_start(output_frame_name);
output_frames();
profile_end(output_frame_name);
...
}
output_frames中枚举所有的obs_core_video_mix,并分别调用output_frame。
所以这里的obs_core_video_mix最多有两个,一个是主的视图obs_core_video_mix,另一个就是启用了OBS虚拟相机的obs_core_video_mix。
static inline void output_frames(void)
{
pthread_mutex_lock(&obs->video.mixes_mutex);
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);
}
else
{
obs->video.mixes.array[i] = NULL;
obs_free_video_mix(mix);
da_erase(obs->video.mixes, i);
i--;
num--;
}
}
pthread_mutex_unlock(&obs->video.mixes_mutex);
}
在output_frame中,其调用render_video进行渲染到render_texure,再根据是否否大小一致进行转换到output_texture
static inline void render_video(struct obs_core_video_mix *video,
bool raw_active, const bool gpu_active,
int cur_texture)
{
...
//先渲染到render_texture
render_main_texture(video);
...
if (raw_active || gpu_active)
{
//渲染输出
gs_texture_t *output_texture = render_output_texture(video);
}
...
}
render_main_texture
render_main_texture函数如下:
static inline void render_main_texture(struct obs_core_video_mix *video)
{
uint32_t base_width = video->ovi.base_width;
uint32_t base_height = video->ovi.base_height;
profile_start(render_main_texture_name);
GS_DEBUG_MARKER_BEGIN(GS_DEBUG_COLOR_MAIN_TEXTURE, render_main_texture_name);
//设置背景颜色
struct vec4 clear_color;
vec4_set(&clear_color, 0.0f, 0.0f, 0.0f, 0.0f);
//设置颜色空间及当前渲染目标纹理
gs_set_render_target_with_color_space(video->render_texture, NULL, video->render_space);
//使用颜色清除背景空间
gs_clear(GS_CLEAR_COLOR, &clear_color, 1.0f, 0);
//设置尺寸
set_render_size(base_width, base_height);
//draw_callbacks
pthread_mutex_lock(&obs->data.draw_callbacks_mutex);
for (size_t i = obs->data.draw_callbacks.num; i > 0; i--)
{
struct draw_callback *const callback = obs->data.draw_callbacks.array + (i - 1);
callback->draw(callback->param, base_width, base_height);
}
pthread_mutex_unlock(&obs->data.draw_callbacks_mutex);
/* In some cases we can reuse a previous mix's texture and save re-rendering everything */
size_t reuse_idx;
if (can_reuse_mix_texture(video, &reuse_idx))
draw_mix_texture(reuse_idx);
else
obs_view_render(video->view);
video->texture_rendered = true;
//rendered_callbacks
pthread_mutex_lock(&obs->data.draw_callbacks_mutex);
for (size_t i = 0; i < obs->data.rendered_callbacks.num; ++i)
{
struct rendered_callback *const callback = &obs->data.rendered_callbacks.array[i];
callback->rendered(callback->param);
}
pthread_mutex_unlock(&obs->data.draw_callbacks_mutex);
GS_DEBUG_MARKER_END();
profile_end(render_main_texture_name);
}
而render_output_texture的
static inline gs_texture_t *
render_output_texture(struct obs_core_video_mix *mix)
{
struct obs_video_info *const ovi = &mix->ovi;
gs_texture_t *texture = mix->render_texture;
gs_texture_t *target = mix->output_texture;
const uint32_t width = gs_texture_get_width(target);
const uint32_t height = gs_texture_get_height(target);
//尺寸不一样,需要转换
if ((width == ovi->base_width) && (height == ovi->base_height))
return texture;
//转换
return target;
}