OBS桌面采集分析

3种桌面采集

win8以上系统,支持Dx11的,可以采用 1. IDXGIOutputDuplication方式抓取桌面图像,也可以使用 2. winrt的方式获取。
win7等系统则可以采用DC句柄,采用 3. BitBlt的方式将桌面窗口数据抓取到。

1、显示器描述字符串是如何显示在属性页的

点击显示器源的属性时,会触发到插件的.get_properties接口。
当使用IDXGIOutputDuplication方式抓取时,在plugins\win-capture\duplicator-monitor-capture.c插件的接口duplicator_capture_properties中调用Windows的系统接口EnumDisplayMonitors完成了对本地显示器的枚举。并且在EnumDisplayMonitors的回调中enum_monitor_props,将数据添加到obs_property_t *monitors中。
duplicator_capture_properties分成三段,一段描述捕获方式,一段描述显示器信息,一段描述是否捕获鼠标。
1、设置属性参数,将struct duplicator_capture类型的指针设置进去。

    struct duplicator_capture *capture = data;

    obs_properties_t *props = obs_properties_create();
    obs_properties_set_param(props, capture, NULL);

2、描述捕获方式

    obs_property_t *p = obs_properties_add_list(props, "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_DXGI, METHOD_DXGI);
    obs_property_list_add_int(p, TEXT_METHOD_WGC, METHOD_WGC);
    obs_property_list_item_disable(p, 2, !wgc_supported);
    obs_property_set_modified_callback(p, display_capture_method_changed);

3、 描述显示器信息

    obs_property_t *monitors = obs_properties_add_list(
        props, "monitor", TEXT_MONITOR, OBS_COMBO_TYPE_LIST,
        OBS_COMBO_FORMAT_INT);

    EnumDisplayMonitors(NULL, NULL, enum_monitor_props, (LPARAM)monitors);

4、描述是否捕获鼠标

    obs_properties_ad
d_bool(props, "capture_cursor", TEXT_CAPTURE_CURSOR);

看看UI拿到props指针后如何操作

激活预览窗口时,桌面采集显示当前采集的桌面combox

未激活状态
激活状态

调用堆栈如下:


创建一个DisplayCaptureToolbar,初始化后将其添加到ui->emptySpace中,初始化中调用关键接口UpdateSourceComboToolbarPropertiescombox添加到ui->emptySpace中。

DisplayCaptureToolbar *c = new DisplayCaptureToolbar(ui->emptySpace, source);
c->Init();
ui->emptySpace->layout()->addWidget(c);

ui->emptySpace在ui界面中的层次关系如下:

DisplayCaptureToolbar等类视图

2、改变显示器抓取ID时相关配置是如何传递到插件层

从Dispaly1改到Dispaly2时触发的操作
  1. 在渲染线程的调用堆栈如下,渲染线程循环检查defer_update_count是否大于0,如果有改变该值会大于零,则会进入到插件层的.update接口中。
    if (os_atomic_load_long(&source->defer_update_count) > 0)
        obs_source_deferred_update(source);
  1. 在UI层combox改变时触发对defer_update_count的增加,调用堆栈如下:

你可能感兴趣的:(OBS桌面采集分析)