win-capture: Add 'auto' method to window capture

Adds an "Automatic" method to the capture method property of window
capture.  This allows the ability for window capture to automatically
determine the best capture method to use.  Primarily, it prefers BitBlt
in most cases, but will use WGC when it detects the window is a browser,
microsoft office, or a UWP program.

This was implemented because the new capture method has a number of
undesired effects associated with it -- the issue of the capture border
that we can do nothing about, the fact that we can't control the capture
of the cursor, and the fact that Microsoft designed it to switch the
cursor away from hardware cursor mode when the capture is active (there
was absolutely no reason to do this because even OBS can capture the
hardware cursor with no issue).  Until we get a new version of this API
that doesn't absolutely blow, we're stuck preferring BitBlt instead.

But hey, at least people will be able to capture browser windows now.
master
jp9000 2020-02-21 22:32:38 -08:00
parent cc5918fdb4
commit 572ce73115
2 changed files with 58 additions and 5 deletions

View File

@ -2,6 +2,7 @@ MonitorCapture="Display Capture"
WindowCapture="Window Capture"
WindowCapture.Window="Window"
WindowCapture.Method="Capture Method"
WindowCapture.Method.Auto="Automatic"
WindowCapture.Method.BitBlt="BitBlt (Windows 7 and up)"
WindowCapture.Method.WindowsGraphicsCapture="Windows Graphics Capture (Windows 10 1903 and up)"
WindowCapture.Priority="Window Match Priority"

View File

@ -10,6 +10,7 @@
#define TEXT_WINDOW_CAPTURE obs_module_text("WindowCapture")
#define TEXT_WINDOW obs_module_text("WindowCapture.Window")
#define TEXT_METHOD obs_module_text("WindowCapture.Method")
#define TEXT_METHOD_AUTO obs_module_text("WindowCapture.Method.Auto")
#define TEXT_METHOD_BITBLT obs_module_text("WindowCapture.Method.BitBlt")
#define TEXT_METHOD_WGC obs_module_text("WindowCapture.Method.WindowsGraphicsCapture")
#define TEXT_MATCH_PRIORITY obs_module_text("WindowCapture.Priority")
@ -34,6 +35,7 @@ struct winrt_exports {
};
enum window_capture_method {
METHOD_AUTO,
METHOD_BITBLT,
METHOD_WGC,
};
@ -46,6 +48,7 @@ struct window_capture {
char *executable;
enum window_capture_method method;
enum window_priority priority;
bool auto_choose_method;
bool cursor;
bool compatibility;
bool use_wildcards; /* TODO */
@ -85,11 +88,13 @@ static void update_settings(struct window_capture *wc, obs_data_t *s)
blog(LOG_DEBUG, "\tclass: %s", wc->class);
}
if ((method == METHOD_WGC) && !wc->wgc_supported)
if (!wc->wgc_supported) {
method = METHOD_BITBLT;
}
wc->method = method;
wc->priority = (enum window_priority)priority;
wc->auto_choose_method = (method == METHOD_AUTO);
wc->cursor = obs_data_get_bool(s, "cursor");
wc->use_wildcards = obs_data_get_bool(s, "use_wildcards");
wc->compatibility = obs_data_get_bool(s, "compatibility");
@ -203,7 +208,7 @@ static uint32_t wc_height(void *data)
static void wc_defaults(obs_data_t *defaults)
{
obs_data_set_default_int(defaults, "method", METHOD_BITBLT);
obs_data_set_default_int(defaults, "method", METHOD_AUTO);
obs_data_set_default_bool(defaults, "cursor", true);
obs_data_set_default_bool(defaults, "compatibility", false);
}
@ -212,13 +217,13 @@ static bool wc_capture_method_changed(obs_properties_t *props,
obs_property_t *p, obs_data_t *settings)
{
const int method = (int)obs_data_get_int(settings, "method");
const bool use_bitblt = method == METHOD_BITBLT;
const bool show_options = method != METHOD_WGC;
p = obs_properties_get(props, "cursor");
obs_property_set_visible(p, use_bitblt);
obs_property_set_visible(p, show_options);
p = obs_properties_get(props, "compatibility");
obs_property_set_visible(p, use_bitblt);
obs_property_set_visible(p, show_options);
return true;
}
@ -232,6 +237,7 @@ static obs_properties_t *wc_properties(void *data)
p = obs_properties_add_list(ppts, "method", TEXT_METHOD,
OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_INT);
obs_property_list_add_int(p, TEXT_METHOD_AUTO, METHOD_AUTO);
obs_property_list_add_int(p, TEXT_METHOD_BITBLT, METHOD_BITBLT);
obs_property_list_add_int(p, TEXT_METHOD_WGC, METHOD_WGC);
obs_property_list_item_disable(p, 1, !wc->wgc_supported);
@ -267,6 +273,48 @@ static void wc_hide(void *data)
memset(&wc->last_rect, 0, sizeof(wc->last_rect));
}
static const char *wgc_partial_match_classes[] = {
"Chrome",
"Mozilla",
NULL,
};
static const char *wgc_whole_match_classes[] = {
"ApplicationFrameWindow",
"Windows.UI.Core.CoreWindow",
"XLMAIN", /* excel*/
"PPTFrameClass", /* powerpoint */
"OpusApp", /* word */
NULL,
};
static void auto_choose_method(struct window_capture *wc)
{
wc->method = METHOD_BITBLT;
if (!wc->class) {
return;
}
const char **class = wgc_partial_match_classes;
while (*class) {
if (astrstri(wc->class, *class) != NULL) {
wc->method = METHOD_WGC;
return;
}
class ++;
}
class = wgc_whole_match_classes;
while (*class) {
if (astrcmpi(wc->class, *class) == 0) {
wc->method = METHOD_WGC;
return;
}
class ++;
}
}
#define RESIZE_CHECK_TIME 0.2f
#define CURSOR_CHECK_TIME 0.2f
@ -296,6 +344,10 @@ static void wc_tick(void *data, float seconds)
wc->capture_winrt = NULL;
}
if (wc->auto_choose_method) {
auto_choose_method(wc);
}
wc->check_window_timer = 0.0f;
wc->window = (wc->method == METHOD_WGC)