obs_source_get_frame
2024-07-03
27
0
obs_source_get_frame用于获取一个输入源的frame数据。其大致被调用过程如下:
- scene_video_render
- render_item(item)
- obs_source_video_render(item->source);
- render_video(source)
- obs_source_update_async_video(source);//更输出源的frame数据到相应的纹理中
- obs_source_get_frame(source);
- update_async_textures //实际应是将frame的数据复制到纹理中
- obs_source_release_frame(source, frame);//释放frame
- obs_source_update_async_video(source);//更输出源的frame数据到相应的纹理中
- render_video(source)
- obs_source_video_render(item->source);
- render_item(item)
obs_source_get_frame源码如下:
struct obs_source_frame *obs_source_get_frame(obs_source_t *source)
{
struct obs_source_frame *frame = NULL;
if (!obs_source_valid(source, "obs_source_get_frame"))
return NULL;
pthread_mutex_lock(&source->async_mutex);
frame = source->cur_async_frame;
source->cur_async_frame = NULL;
if (frame) {
os_atomic_inc_long(&frame->refs);
}
pthread_mutex_unlock(&source->async_mutex);
return frame;
}
这里看到,其实是获取的是cur_async_frame成员,而cur_async_frame成员是在async_tick函数中通过get_closest_frame获取设置的。
static void async_tick(obs_source_t *source)
{
uint64_t sys_time = obs->video.video_time;
pthread_mutex_lock(&source->async_mutex);
if (deinterlacing_enabled(source)) {
deinterlace_process_last_frame(source, sys_time);
}
else
{
if (source->cur_async_frame)
{
remove_async_frame(source, source->cur_async_frame);
source->cur_async_frame = NULL;
}
//设置cur_async_frame内容
source->cur_async_frame = get_closest_frame(source, sys_time);
}
source->last_sys_timestamp = sys_time;
if (deinterlacing_enabled(source))
filter_frame(source, &source->prev_async_frame);
filter_frame(source, &source->cur_async_frame);
if (source->cur_async_frame)
source->async_update_texture = set_async_texture_size(source, source->cur_async_frame);
pthread_mutex_unlock(&source->async_mutex);
}
而async_tick的调用是在obs_source_video_tick函数中调用的,而async_tick又是被tick_sources调用的。
bool obs_graphics_thread_loop(struct obs_graphics_context *context)
{
context->last_time = tick_sources(obs->video.video_time, context->last_time)
{
obs_source_video_tick(s, seconds)
{
static void async_tick(obs_source_t *source)
{
//设置cur_async_frame内容
source->cur_async_frame = get_closest_frame(source, sys_time);
}
}
}
}
所以对于异步的设备,其tick_sources其实是用于进行时间戳同步,用于准备数据源的,当准备好时,再调用该设备的render时,会直接使用准备好的纹理进行渲染。