static inline void output_frame(uint64_t *cur_time, uint64_t interval) { struct obs_core_video *video = &obs->video; int cur_texture = video->cur_texture; int prev_texture = cur_texture == 0 ? NUM_TEXTURES-1 : cur_texture-1; struct video_data frame; bool frame_ready; memset(&frame, 0, sizeof(struct video_data)); gs_enter_context(video->graphics); render_video(video, cur_texture, prev_texture); frame_ready = download_frame(video, prev_texture, &frame); gs_flush(); gs_leave_context(); if (frame_ready) { struct obs_vframe_info vframe_info; circlebuf_pop_front(&video->vframe_info_buffer, &vframe_info, sizeof(vframe_info)); frame.timestamp = vframe_info.timestamp; output_video_data(video, &frame, vframe_info.count); } if (++video->cur_texture == NUM_TEXTURES) video->cur_texture = 0; video_sleep(video, cur_time, interval); }
void *obs_video_thread(void *param) { uint64_t last_time = 0; uint64_t interval = video_output_get_frame_time(obs->video.video); obs->video.video_time = os_gettime_ns(); os_set_thread_name("libobs: graphics thread"); const char *video_thread_name = profile_store_name(obs_get_profiler_name_store(), "obs_video_thread(%g ms)", interval / 1000000.); profile_register_root(video_thread_name, interval); while (!video_output_stopped(obs->video.video)) { profile_start(video_thread_name); profile_start(tick_sources_name); last_time = tick_sources(obs->video.video_time, last_time); profile_end(tick_sources_name); profile_start(render_displays_name); render_displays(); profile_end(render_displays_name); profile_start(output_frame_name); output_frame(); profile_end(output_frame_name); profile_end(video_thread_name); profile_reenable_thread(); video_sleep(&obs->video, &obs->video.video_time, interval); } UNUSED_PARAMETER(param); return NULL; }
void *obs_graphics_thread(void *param) { uint64_t last_time = 0; uint64_t interval = video_output_get_frame_time(obs->video.video); uint64_t frame_time_total_ns = 0; uint64_t fps_total_ns = 0; uint32_t fps_total_frames = 0; obs->video.video_time = os_gettime_ns(); os_set_thread_name("libobs: graphics thread"); const char *video_thread_name = profile_store_name(obs_get_profiler_name_store(), "obs_graphics_thread(%g"NBSP"ms)", interval / 1000000.); profile_register_root(video_thread_name, interval); srand((unsigned int)time(NULL)); while (!video_output_stopped(obs->video.video)) { uint64_t frame_start = os_gettime_ns(); uint64_t frame_time_ns; profile_start(video_thread_name); profile_start(tick_sources_name); last_time = tick_sources(obs->video.video_time, last_time); profile_end(tick_sources_name); profile_start(render_displays_name); render_displays(); profile_end(render_displays_name); profile_start(output_frame_name); output_frame(); profile_end(output_frame_name); frame_time_ns = os_gettime_ns() - frame_start; profile_end(video_thread_name); profile_reenable_thread(); video_sleep(&obs->video, &obs->video.video_time, interval); frame_time_total_ns += frame_time_ns; fps_total_ns += (obs->video.video_time - last_time); fps_total_frames++; if (fps_total_ns >= 1000000000ULL) { obs->video.video_fps = (double)fps_total_frames / ((double)fps_total_ns / 1000000000.0); obs->video.video_avg_frame_time_ns = frame_time_total_ns / (uint64_t)fps_total_frames; frame_time_total_ns = 0; fps_total_ns = 0; fps_total_frames = 0; } } UNUSED_PARAMETER(param); return NULL; }
void *obs_graphics_thread(void *param) { uint64_t last_time = 0; uint64_t interval = video_output_get_frame_time(obs->video.video); uint64_t frame_time_total_ns = 0; uint64_t fps_total_ns = 0; uint32_t fps_total_frames = 0; bool gpu_was_active = false; bool raw_was_active = false; bool was_active = false; obs->video.video_time = os_gettime_ns(); os_set_thread_name("libobs: graphics thread"); const char *video_thread_name = profile_store_name(obs_get_profiler_name_store(), "obs_graphics_thread(%g"NBSP"ms)", interval / 1000000.); profile_register_root(video_thread_name, interval); srand((unsigned int)time(NULL)); while (!video_output_stopped(obs->video.video)) { uint64_t frame_start = os_gettime_ns(); uint64_t frame_time_ns; bool raw_active = obs->video.raw_active > 0; #ifdef _WIN32 bool gpu_active = obs->video.gpu_encoder_active > 0; #else const bool gpu_active = 0; #endif bool active = raw_active || gpu_active; if (!was_active && active) clear_base_frame_data(); if (!raw_was_active && raw_active) clear_raw_frame_data(); #ifdef _WIN32 if (!gpu_was_active && gpu_active) clear_gpu_frame_data(); #endif raw_was_active = raw_active; gpu_was_active = gpu_active; was_active = active; profile_start(video_thread_name); profile_start(tick_sources_name); last_time = tick_sources(obs->video.video_time, last_time); profile_end(tick_sources_name); profile_start(output_frame_name); output_frame(raw_active, gpu_active); profile_end(output_frame_name); profile_start(render_displays_name); render_displays(); profile_end(render_displays_name); frame_time_ns = os_gettime_ns() - frame_start; profile_end(video_thread_name); profile_reenable_thread(); video_sleep(&obs->video, raw_active, gpu_active, &obs->video.video_time, interval); frame_time_total_ns += frame_time_ns; fps_total_ns += (obs->video.video_time - last_time); fps_total_frames++; if (fps_total_ns >= 1000000000ULL) { obs->video.video_fps = (double)fps_total_frames / ((double)fps_total_ns / 1000000000.0); obs->video.video_avg_frame_time_ns = frame_time_total_ns / (uint64_t)fps_total_frames; frame_time_total_ns = 0; fps_total_ns = 0; fps_total_frames = 0; } } UNUSED_PARAMETER(param); return NULL; }