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.
master
jpark37 2020-05-06 21:32:57 -07:00
parent 078ea5222d
commit 097ea77488
3 changed files with 38 additions and 4 deletions

View File

@ -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) {

View File

@ -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,

View File

@ -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);
}