Skip to content

win-capture: Fix display capture for identical monitors #12248

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: master
Choose a base branch
from

Conversation

aarshivv
Copy link

@aarshivv aarshivv commented Jun 5, 2025

Description

Fixed an issue where OBS Studio is unable to properly select between identical monitors in Display Capture source.
In win-capture plugin, we use EnumDisplayDevicesA Windows API fn that enumerates display devices in the system.
Currently, we are using DeviceID to uniquely identify the monitor, it fails to work when the connected monitor are from
same manufacturer and same model, as DeviceID returned is same for both monitor, resulting in failure to select between multiple monitor.

This fix uses DeviceName instead of DeviceID, DeviceName is unique and works fine as identifier. I have passed the value of DeviceName for field monitor_id in obs_get_source_properties instead of DeviceID. Later, we register the source using the DeviceName.

For reference, these are the available fields on device returned by EnumDisplayDevicesA:
image

Motivation and Context

Fixes #12244

How Has This Been Tested?

Windows 11
Tested locally using both WGC and DXGI capture method on the set of BenQ GW2790 68.58 cm (27 inch) and set of BenQ GW2786TC 68.58 cm (27 inch) monitors, also normally tested the working on other monitors along with connecting and disconnecting these monitors.

Types of changes

  • Bug fix (non-breaking change which fixes an issue)

Checklist:

  • My code has been run through clang-format.
  • I have read the contributing document.
  • My code is not on the master branch.
  • The code has been tested.
  • All commit messages are properly formatted and commits squashed where appropriate.
  • I have included updates to all appropriate documentation.

@RytoEX
Copy link
Member

RytoEX commented Jun 5, 2025

Have you confirmed that you are not being affected by #5502 or #8181 where a disconnected display is causing display enumeration to behave unexpectedly?

@aarshivv
Copy link
Author

aarshivv commented Jun 5, 2025

Have you confirmed that you are not being affected by #5502 or #8181 where a disconnected display is causing display enumeration to behave unexpectedly?

I tested #5502 in recording mode, I selected the monitor then plugged off then plugged in, it selected the same one, but I will test it after connecting more monitors, I will try to recreate #5502.
For #8181 , as mentioned in #8181 (comment) comment, I was facing the same, selecting any of the identical monitor gets me back to the first one identical monitor, even the ordering of this is not consistent.

I checked and found that in my case the value returned for field monitor_id in fn obs_get_source_properties(id="monitor_capture") is coming same for both monitor. Also confirmed that the value of DeviceID returned by Windows API EnumDisplayDevicesA is same for both identical monitor, causing this issue.

@RytoEX
Copy link
Member

RytoEX commented Jun 5, 2025

Have you confirmed that you are not being affected by #5502 or #8181 where a disconnected display is causing display enumeration to behave unexpectedly?

I tested #5502 in recording mode, I selected the monitor then plugged off then plugged in, it selected the same one, but I will test it after connecting more monitors, I will try to recreate #5502. For #8181 , as mentioned in #8181 (comment) comment, I was facing the same, selecting any of the identical monitor gets me back to the first one identical monitor, even the ordering of this is not consistent.

I checked and found that in my case the value returned for field monitor_id in fn obs_get_source_properties(id="monitor_capture") is coming same for both monitor. Also confirmed that the value of DeviceID returned by Windows API EnumDisplayDevicesA is same for both identical monitor, causing this issue.

That does not answer my question.

Do you have any disabled displays?
#8181 (comment)

If the Windows API is returning bad data, I would prefer that Microsoft fixes that than just working around it.

@aarshivv
Copy link
Author

aarshivv commented Jun 5, 2025

Have you confirmed that you are not being affected by #5502 or #8181 where a disconnected display is causing display enumeration to behave unexpectedly?

I tested #5502 in recording mode, I selected the monitor then plugged off then plugged in, it selected the same one, but I will test it after connecting more monitors, I will try to recreate #5502. For #8181 , as mentioned in #8181 (comment) comment, I was facing the same, selecting any of the identical monitor gets me back to the first one identical monitor, even the ordering of this is not consistent.
I checked and found that in my case the value returned for field monitor_id in fn obs_get_source_properties(id="monitor_capture") is coming same for both monitor. Also confirmed that the value of DeviceID returned by Windows API EnumDisplayDevicesA is same for both identical monitor, causing this issue.

That does not answer my question.

Do you have any disabled displays? #8181 (comment)

If the Windows API is returning bad data, I would prefer that Microsoft fixes that than just working around it.

Ooh, my bad, I checked this and I do have some grayed out monitors, I have removed it, but I am away from identical monitors, I will check this once with those and see if this resolves this.

@WizardCM WizardCM added the Bug Fix Non-breaking change which fixes an issue label Jun 7, 2025
@aarshivv
Copy link
Author

aarshivv commented Jun 9, 2025

@RytoEX,
Update:

I tested this after removing all the grayed-out monitors from Device ManagerMonitors and restarted my PC, just to make sure everything is clean.
image

Scenario 1:
When I set the display mode to Second screen only, I still face the same issue. I see two monitors in the dropdown, but selecting either one results in capturing the first monitor.
image
image

Scenario 2:
When I set the display mode to Extend, everything works as expected. I see three monitors in the dropdown, and selecting any of them correctly captures the corresponding monitor. To be honest, I hadn’t tested this mode before removing the grayed-out monitors, so it’s possible this was already working before.

To provide more context, here are the monitor_ids returned by obs_get_source_properties:

Scenario 1: Second screen only:
\\\\?\\DISPLAY#LEN403D#5&162715c2&0&UID256#{e6f07b5f-ee97-4a90-b076-33f57bf4eaa7},
\\\\?\\DISPLAY#LEN403D#5&162715c2&0&UID256#{e6f07b5f-ee97-4a90-b076-33f57bf4eaa7}

Scenario 2: Extend:
\\\\?\\DISPLAY#BNQ78E6#5&162715c2&0&UID257#{e6f07b5f-ee97-4a90-b076-33f57bf4eaa7},
\\\\?\\DISPLAY#BNQ78E6#5&162715c2&0&UID277#{e6f07b5f-ee97-4a90-b076-33f57bf4eaa7} and
\\\\?\\DISPLAY#LEN403D#5&162715c2&0&UID256#{e6f07b5f-ee97-4a90-b076-33f57bf4eaa7}

As you can see, the id assigned to both the monitor is same in first scenario, resulting in failure to capture correct monitor.

@aarshivv
Copy link
Author

aarshivv commented Jun 9, 2025

I will check the windows API why it is giving same id in above case.

@aarshivv aarshivv force-pushed the monitor-capture branch 2 times, most recently from 44dfa64 to 388d177 Compare June 10, 2025 15:20
@aarshivv aarshivv marked this pull request as draft June 10, 2025 15:21
@aarshivv
Copy link
Author

aarshivv commented Jun 11, 2025

@RytoEX, can you check the change now.

In existing code:
Issue 1: Only Querying First Monitor (Index 0)
Microsoft Documentation Reference:

"To query all monitor devices associated with an adapter, call EnumDisplayDevices in a loop with lpDevice set to the adapter name, iDevNum set to start at 0, and iDevNum set to increment until the function fails."

Source: https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-enumdisplaydevicesa

Issue 2: No State Flag Validation
Microsoft Documentation Reference:

"StateFlags: Device state flags. DISPLAY_DEVICE_ACTIVE specifies whether a monitor is presented as being 'on' by the respective GDI view."

Source: https://docs.microsoft.com/en-us/windows/win32/api/wingdi/ns-wingdi-display_devicea

Solution:
I am now iterating over all monitors and selecting only the active one, this ensures we are taking all monitors into consideration and filtering the active one out. This should also fix the issue where user have to remove grayed out monitor from device manager to capture monitors properly.

I have tested above changes with variety of monitor on my windows machince and it works without any issue. I have reverted the change where I proposed the use of DeviceName instead of DeviceID.

Let me know if you have any query, please review the final changes.

@aarshivv aarshivv marked this pull request as ready for review June 11, 2025 06:03
@WizardCM WizardCM added the Windows Affects Windows label Jun 11, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Bug Fix Non-breaking change which fixes an issue Windows Affects Windows
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[Windows] Display Capture unable to select between identical monitors
3 participants