提交 6aa50b3e 编写于 作者: J jpark37

libobs: Use autoreleasepool for graphics thread

Apparently necessary to clean up macOS leaks.
上级 05c9ddd2
......@@ -1804,3 +1804,17 @@ bool obs_hotkeys_platform_is_pressed(obs_hotkeys_platform_t *plat,
return false;
}
void *obs_graphics_thread_autorelease(void *param)
{
@autoreleasepool {
return obs_graphics_thread(param);
}
}
bool obs_graphics_thread_loop_autorelease(struct obs_graphics_context *context)
{
@autoreleasepool {
return obs_graphics_thread_loop(context);
}
}
......@@ -434,7 +434,27 @@ struct obs_core {
extern struct obs_core *obs;
struct obs_graphics_context {
uint64_t last_time;
uint64_t interval;
uint64_t frame_time_total_ns;
uint64_t fps_total_ns;
uint32_t fps_total_frames;
#ifdef _WIN32
bool gpu_was_active;
#endif
bool raw_was_active;
bool was_active;
const char *video_thread_name;
};
extern void *obs_graphics_thread(void *param);
extern bool obs_graphics_thread_loop(struct obs_graphics_context *context);
#ifdef __APPLE__
extern void *obs_graphics_thread_autorelease(void *param);
extern bool
obs_graphics_thread_loop_autorelease(struct obs_graphics_context *context);
#endif
extern gs_effect_t *obs_load_effect(gs_effect_t **effect, const char *file);
......
......@@ -921,124 +921,135 @@ static void uninit_winrt_state(struct winrt_state *winrt)
static const char *tick_sources_name = "tick_sources";
static const char *render_displays_name = "render_displays";
static const char *output_frame_name = "output_frame";
void *obs_graphics_thread(void *param)
bool obs_graphics_thread_loop(struct obs_graphics_context *context)
{
#ifdef _WIN32
struct winrt_state winrt;
init_winrt_state(&winrt);
#endif // #ifdef _WIN32
/* defer loop break to clean up sources */
const bool stop_requested = video_output_stopped(obs->video.video);
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;
uint64_t frame_start = os_gettime_ns();
uint64_t frame_time_ns;
bool raw_active = obs->video.raw_active > 0;
#ifdef _WIN32
bool gpu_was_active = false;
const bool gpu_active = obs->video.gpu_encoder_active > 0;
const bool active = raw_active || gpu_active;
#else
const bool gpu_active = 0;
const bool active = raw_active;
#endif
bool raw_was_active = false;
bool was_active = false;
is_graphics_thread = true;
if (!context->was_active && active)
clear_base_frame_data();
if (!context->raw_was_active && raw_active)
clear_raw_frame_data();
#ifdef _WIN32
if (!context->gpu_was_active && gpu_active)
clear_gpu_frame_data();
obs->video.video_time = os_gettime_ns();
obs->video.video_frame_interval_ns = interval;
context->gpu_was_active = gpu_active;
#endif
context->raw_was_active = raw_active;
context->was_active = active;
os_set_thread_name("libobs: graphics thread");
profile_start(context->video_thread_name);
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);
gs_enter_context(obs->video.graphics);
gs_begin_frame();
gs_leave_context();
srand((unsigned int)time(NULL));
profile_start(tick_sources_name);
context->last_time =
tick_sources(obs->video.video_time, context->last_time);
profile_end(tick_sources_name);
for (;;) {
/* defer loop break to clean up sources */
const bool stop_requested =
video_output_stopped(obs->video.video);
execute_graphics_tasks();
uint64_t frame_start = os_gettime_ns();
uint64_t frame_time_ns;
bool raw_active = obs->video.raw_active > 0;
#ifdef _WIN32
const bool gpu_active = obs->video.gpu_encoder_active > 0;
const bool active = raw_active || gpu_active;
#else
const bool gpu_active = 0;
const bool active = raw_active;
MSG msg;
while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
#endif
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();
profile_start(output_frame_name);
output_frame(raw_active, gpu_active);
profile_end(output_frame_name);
gpu_was_active = gpu_active;
#endif
raw_was_active = raw_active;
was_active = active;
profile_start(render_displays_name);
render_displays();
profile_end(render_displays_name);
profile_start(video_thread_name);
frame_time_ns = os_gettime_ns() - frame_start;
gs_enter_context(obs->video.graphics);
gs_begin_frame();
gs_leave_context();
profile_end(context->video_thread_name);
profile_start(tick_sources_name);
last_time = tick_sources(obs->video.video_time, last_time);
profile_end(tick_sources_name);
profile_reenable_thread();
execute_graphics_tasks();
video_sleep(&obs->video, raw_active, gpu_active, &obs->video.video_time,
context->interval);
#ifdef _WIN32
MSG msg;
while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
#endif
context->frame_time_total_ns += frame_time_ns;
context->fps_total_ns += (obs->video.video_time - context->last_time);
context->fps_total_frames++;
profile_start(output_frame_name);
output_frame(raw_active, gpu_active);
profile_end(output_frame_name);
if (context->fps_total_ns >= 1000000000ULL) {
obs->video.video_fps =
(double)context->fps_total_frames /
((double)context->fps_total_ns / 1000000000.0);
obs->video.video_avg_frame_time_ns =
context->frame_time_total_ns /
(uint64_t)context->fps_total_frames;
profile_start(render_displays_name);
render_displays();
profile_end(render_displays_name);
context->frame_time_total_ns = 0;
context->fps_total_ns = 0;
context->fps_total_frames = 0;
}
frame_time_ns = os_gettime_ns() - frame_start;
return !stop_requested;
}
profile_end(video_thread_name);
void *obs_graphics_thread(void *param)
{
#ifdef _WIN32
struct winrt_state winrt;
init_winrt_state(&winrt);
#endif // #ifdef _WIN32
profile_reenable_thread();
is_graphics_thread = true;
video_sleep(&obs->video, raw_active, gpu_active,
&obs->video.video_time, interval);
const uint64_t interval = video_output_get_frame_time(obs->video.video);
frame_time_total_ns += frame_time_ns;
fps_total_ns += (obs->video.video_time - last_time);
fps_total_frames++;
obs->video.video_time = os_gettime_ns();
obs->video.video_frame_interval_ns = interval;
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;
os_set_thread_name("libobs: graphics thread");
frame_time_total_ns = 0;
fps_total_ns = 0;
fps_total_frames = 0;
}
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);
if (stop_requested)
break;
}
srand((unsigned int)time(NULL));
struct obs_graphics_context context;
context.interval = video_output_get_frame_time(obs->video.video);
context.frame_time_total_ns = 0;
context.fps_total_ns = 0;
context.fps_total_frames = 0;
context.last_time = 0;
#ifdef _WIN32
context.gpu_was_active = false;
#endif
context.raw_was_active = false;
context.was_active = false;
context.video_thread_name = video_thread_name;
#ifdef __APPLE__
while (obs_graphics_thread_loop_autorelease(&context))
#else
while (obs_graphics_thread_loop(&context))
#endif
;
#ifdef _WIN32
uninit_winrt_state(&winrt);
......
......@@ -429,8 +429,13 @@ static int obs_init_video(struct obs_video_info *ovi)
if (pthread_mutex_init(&video->task_mutex, NULL) < 0)
return OBS_VIDEO_FAIL;
#ifdef __APPLE__
errorcode = pthread_create(&video->video_thread, NULL,
obs_graphics_thread_autorelease, obs);
#else
errorcode = pthread_create(&video->video_thread, NULL,
obs_graphics_thread, obs);
#endif
if (errorcode != 0)
return OBS_VIDEO_FAIL;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册