瀏覽代碼

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.
jpark37 5 年之前
父節點
當前提交
097ea77488
共有 3 個文件被更改,包括 38 次插入4 次删除
  1. 21 1
      libobs-winrt/winrt-capture.cpp
  2. 1 0
      libobs-winrt/winrt-capture.h
  3. 16 3
      plugins/win-capture/window-capture.c

+ 21 - 1
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) {

+ 1 - 0
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,

+ 16 - 3
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);
 }