From 097ea7748864e991c113bdd9255d0c49c94e8793 Mon Sep 17 00:00:00 2001 From: jpark37 Date: Wed, 6 May 2020 21:32:57 -0700 Subject: [PATCH] libobs-winrt: win-capture: Detect GraphicsCaptureItem closure Make WGC window capture recover from GraphicsCaptureItem closure, which can occur when following links in fullscreen Chrome for example. --- libobs-winrt/winrt-capture.cpp | 22 +++++++++++++++++++++- libobs-winrt/winrt-capture.h | 1 + plugins/win-capture/window-capture.c | 19 ++++++++++++++++--- 3 files changed, 38 insertions(+), 4 deletions(-) diff --git a/libobs-winrt/winrt-capture.cpp b/libobs-winrt/winrt-capture.cpp index 189300130..533b83d07 100644 --- a/libobs-winrt/winrt-capture.cpp +++ b/libobs-winrt/winrt-capture.cpp @@ -123,6 +123,8 @@ struct winrt_capture { winrt::Windows::Graphics::Capture::GraphicsCaptureSession session{ nullptr}; winrt::Windows::Graphics::SizeInt32 last_size; + winrt::Windows::Graphics::Capture::GraphicsCaptureItem::Closed_revoker + closed; winrt::Windows::Graphics::Capture::Direct3D11CaptureFramePool:: FrameArrived_revoker frame_arrived; @@ -132,6 +134,7 @@ struct winrt_capture { bool client_box_available; bool thread_changed; + bool active; struct winrt_capture *next; void draw_cursor() @@ -186,6 +189,14 @@ struct winrt_capture { DestroyIcon(icon); } + void + on_closed(winrt::Windows::Graphics::Capture::GraphicsCaptureItem const + &sender, + winrt::Windows::Foundation::IInspectable const &) + { + active = FALSE; + } + void on_frame_arrived(winrt::Windows::Graphics::Capture:: Direct3D11CaptureFramePool const &sender, winrt::Windows::Foundation::IInspectable const &) @@ -402,9 +413,12 @@ try { capture->frame_pool = frame_pool; capture->session = session; capture->last_size = size; + capture->closed = item.Closed(winrt::auto_revoke, + {capture, &winrt_capture::on_closed}); capture->frame_arrived = frame_pool.FrameArrived( winrt::auto_revoke, {capture, &winrt_capture::on_frame_arrived}); + capture->active = TRUE; capture->next = capture_list; capture_list = capture; @@ -449,6 +463,7 @@ extern "C" EXPORT void winrt_capture_free(struct winrt_capture *capture) obs_leave_graphics(); capture->frame_arrived.revoke(); + capture->closed.revoke(); capture->frame_pool.Close(); capture->session.Close(); @@ -476,6 +491,11 @@ static void draw_texture(struct winrt_capture *capture, gs_effect_t *effect) gs_technique_end(tech); } +extern "C" EXPORT BOOL winrt_capture_active(const struct winrt_capture *capture) +{ + return capture->active; +} + extern "C" EXPORT void winrt_capture_show_cursor(struct winrt_capture *capture, BOOL visible) { @@ -485,7 +505,7 @@ extern "C" EXPORT void winrt_capture_show_cursor(struct winrt_capture *capture, extern "C" EXPORT void winrt_capture_render(struct winrt_capture *capture, gs_effect_t *effect) { - if (capture && capture->texture_written) { + if (capture->texture_written) { if (!initialized_tls) { struct winrt_capture *current = capture_list; while (current) { diff --git a/libobs-winrt/winrt-capture.h b/libobs-winrt/winrt-capture.h index 33c237dee..815395946 100644 --- a/libobs-winrt/winrt-capture.h +++ b/libobs-winrt/winrt-capture.h @@ -15,6 +15,7 @@ EXPORT struct winrt_capture *winrt_capture_init(BOOL cursor, HWND window, BOOL client_area); EXPORT void winrt_capture_free(struct winrt_capture *capture); +EXPORT BOOL winrt_capture_supported(const struct winrt_capture *capture); EXPORT void winrt_capture_show_cursor(struct winrt_capture *capture, BOOL visible); EXPORT void winrt_capture_render(struct winrt_capture *capture, diff --git a/plugins/win-capture/window-capture.c b/plugins/win-capture/window-capture.c index 2794087f1..f01d75fdd 100644 --- a/plugins/win-capture/window-capture.c +++ b/plugins/win-capture/window-capture.c @@ -31,6 +31,7 @@ struct winrt_exports { struct winrt_capture *(*winrt_capture_init)(BOOL cursor, HWND window, BOOL client_area); void (*winrt_capture_free)(struct winrt_capture *capture); + BOOL *(*winrt_capture_active)(const struct winrt_capture *capture); void (*winrt_capture_show_cursor)(struct winrt_capture *capture, BOOL visible); void (*winrt_capture_render)(struct winrt_capture *capture, @@ -178,6 +179,7 @@ static bool load_winrt_imports(struct winrt_exports *exports, void *module, WINRT_IMPORT(winrt_capture_cursor_toggle_supported); WINRT_IMPORT(winrt_capture_init); WINRT_IMPORT(winrt_capture_free); + WINRT_IMPORT(winrt_capture_active); WINRT_IMPORT(winrt_capture_show_cursor); WINRT_IMPORT(winrt_capture_render); WINRT_IMPORT(winrt_capture_width); @@ -501,10 +503,21 @@ static void wc_render(void *data, gs_effect_t *effect) { struct window_capture *wc = data; gs_effect_t *const opaque = obs_get_base_effect(OBS_EFFECT_OPAQUE); - if (wc->method == METHOD_WGC) - wc->exports.winrt_capture_render(wc->capture_winrt, opaque); - else + if (wc->method == METHOD_WGC) { + if (wc->capture_winrt) { + if (wc->exports.winrt_capture_active( + wc->capture_winrt)) { + wc->exports.winrt_capture_render( + wc->capture_winrt, opaque); + } else { + wc->exports.winrt_capture_free( + wc->capture_winrt); + wc->capture_winrt = NULL; + } + } + } else { dc_capture_render(&wc->capture, opaque); + } UNUSED_PARAMETER(effect); }