diff --git a/libobs/obs-video.c b/libobs/obs-video.c index 894a9fcf6..82b37b492 100644 --- a/libobs/obs-video.c +++ b/libobs/obs-video.c @@ -539,7 +539,7 @@ static const uint8_t *set_gpu_converted_plane(uint32_t width, uint32_t height, const uint8_t *in, uint8_t *out) { if ((width == linesize_input) && (width == linesize_output)) { - size_t total = width * height; + size_t total = (size_t)width * (size_t)height; memcpy(out, in, total); in += total; } else { @@ -672,10 +672,12 @@ static inline void copy_rgbx_frame(struct video_frame *output, /* if the line sizes match, do a single copy */ if (input->linesize[0] == output->linesize[0]) { - memcpy(out_ptr, in_ptr, input->linesize[0] * info->height); + memcpy(out_ptr, in_ptr, + (size_t)input->linesize[0] * (size_t)info->height); } else { + const size_t copy_size = (size_t)info->width * 4; for (size_t y = 0; y < info->height; y++) { - memcpy(out_ptr, in_ptr, info->width * 4); + memcpy(out_ptr, in_ptr, copy_size); in_ptr += input->linesize[0]; out_ptr += output->linesize[0]; } @@ -835,11 +837,97 @@ static void execute_graphics_tasks(void) } } +#ifdef _WIN32 + +struct winrt_exports { + void (*winrt_initialize)(); + void (*winrt_uninitialize)(); + struct winrt_disaptcher *(*winrt_dispatcher_init)(); + void (*winrt_dispatcher_free)(struct winrt_disaptcher *dispatcher); + void (*winrt_capture_thread_start)(); + void (*winrt_capture_thread_stop)(); +}; + +#define WINRT_IMPORT(func) \ + do { \ + exports->func = os_dlsym(module, #func); \ + if (!exports->func) { \ + success = false; \ + blog(LOG_ERROR, \ + "Could not load function '%s' from " \ + "module '%s'", \ + #func, module_name); \ + } \ + } while (false) + +static bool load_winrt_imports(struct winrt_exports *exports, void *module, + const char *module_name) +{ + bool success = true; + + WINRT_IMPORT(winrt_initialize); + WINRT_IMPORT(winrt_uninitialize); + WINRT_IMPORT(winrt_dispatcher_init); + WINRT_IMPORT(winrt_dispatcher_free); + WINRT_IMPORT(winrt_capture_thread_start); + WINRT_IMPORT(winrt_capture_thread_stop); + + return success; +} + +struct winrt_state { + bool loaded; + void *winrt_module; + struct winrt_exports exports; + struct winrt_disaptcher *dispatcher; +}; + +static void init_winrt_state(struct winrt_state *winrt) +{ + static const char *const module_name = "libobs-winrt"; + + winrt->winrt_module = os_dlopen(module_name); + winrt->loaded = winrt->winrt_module && + load_winrt_imports(&winrt->exports, winrt->winrt_module, + module_name); + winrt->dispatcher = NULL; + if (winrt->loaded) { + winrt->exports.winrt_initialize(); + winrt->dispatcher = winrt->exports.winrt_dispatcher_init(); + + gs_enter_context(obs->video.graphics); + winrt->exports.winrt_capture_thread_start(); + gs_leave_context(); + } +} + +static void uninit_winrt_state(struct winrt_state *winrt) +{ + if (winrt->winrt_module) { + if (winrt->loaded) { + winrt->exports.winrt_capture_thread_stop(); + if (winrt->dispatcher) + winrt->exports.winrt_dispatcher_free( + winrt->dispatcher); + winrt->exports.winrt_uninitialize(); + } + + os_dlclose(winrt->winrt_module); + } +} + +#endif // #ifdef _WIN32 + 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) { +#ifdef _WIN32 + struct winrt_state winrt; + init_winrt_state(&winrt); +#endif // #ifdef _WIN32 + uint64_t last_time = 0; uint64_t interval = video_output_get_frame_time(obs->video.video); uint64_t frame_time_total_ns = 0; @@ -952,6 +1040,10 @@ void *obs_graphics_thread(void *param) break; } +#ifdef _WIN32 + uninit_winrt_state(&winrt); +#endif + UNUSED_PARAMETER(param); return NULL; }