Reland "Wait for frames to arrive in WgcCapturer instead of returning nothing."

This reverts commit dd32562f242b247aed8add4efecaf3e20c623b9a.

Reason for revert: Updated the original change to dynamically load
the CoreMessaging.dll instead of statically linking with the .lib.

Original change's description:
> Revert "Wait for frames to arrive in WgcCapturer instead of returning nothing."
>
> This reverts commit 93bb3051490253d56dc1cdab4701b91138a151c3.
>
> Reason for revert: It breaks a test while rolling into Chromium,
> see https://webrtc-review.googlesource.com/c/src/+/261780/21#message-4a96e33bfb475f19a618be82bbe72951b23085ef for details.
>
> Original change's description:
> > Wait for frames to arrive in WgcCapturer instead of returning nothing.
> >
> > We're seeing a high instance of "first capture failed" in Chromium when
> > using WGC. We can reduce this by waiting for frames to arrive if there
> > are none in the frame pool instead of returning a temporary error.
> >
> > I've set the maximum time to wait for a frame to 50ms. If no frame
> > arrives before 50ms has elapsed, we will return a temporary error.
> > Added a new test, FirstCaptureSucceeds, to verify that this is working
> > as expected.
> >
> > As part of this I updated the name of the `kCreateFreeThreadedFailed`
> > enum value to `kCreateFramePoolFailed`. The value remains the same
> > since they both report failures in frame pool creation.
> >
> > I also increased `kNumBuffers` from 1 to 2, so that the frame pool can
> > store two frames. This should prevent us from having to wait on the
> > event as frequently. This will increase the latency between capture
> > and display, however. High frame rate applications should not be
> > noticeably affected.
> >
> > Additionally, we uncovered a bug in the OS that prevents window capture
> > when there are displays attached, but none of them are active. Added
> > a new check to `IsWgcSupported` to cover this scenario.
> >
> > Finally, some issues with other WGC tests blocked moving the TryBots
> > to a newer version of Windows. This CL fixes those issues and updates
> > the TryBot configuration.
> >
> > bug: chromium:1314868
> > Change-Id: Id9c4d5ee98621e682ef04864c3848d50e761cdb7
> > Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/261780
> > Reviewed-by: Alexander Cooper <alcooper@chromium.org>
> > Reviewed-by: Jeremy Leconte <jleconte@webrtc.org>
> > Commit-Queue: Austin Orion <auorion@microsoft.com>
> > Reviewed-by: Jeremy Leconte <jleconte@google.com>
> > Cr-Commit-Position: refs/heads/main@{#37404}
>
> Change-Id: If237df4826fe20b6fe2ca4b57253623321bf33c5
> No-Presubmit: true
> No-Tree-Checks: true
> No-Try: true
> Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/267460
> Bot-Commit: rubber-stamper@appspot.gserviceaccount.com <rubber-stamper@appspot.gserviceaccount.com>
> Owners-Override: Mirko Bonadei <mbonadei@webrtc.org>
> Commit-Queue: Mirko Bonadei <mbonadei@webrtc.org>
> Auto-Submit: Mirko Bonadei <mbonadei@webrtc.org>
> Cr-Commit-Position: refs/heads/main@{#37408}

Change-Id: I6cc2becd9ed363782ab2f326f58d9401bc8fb820
Bug: chromium:1314868
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/267902
Reviewed-by: Jeremy Leconte <jleconte@webrtc.org>
Reviewed-by: Alexander Cooper <alcooper@chromium.org>
Commit-Queue: Austin Orion <auorion@microsoft.com>
Cr-Commit-Position: refs/heads/main@{#37470}
This commit is contained in:
Austin Orion 2022-07-05 14:20:54 -07:00 committed by WebRTC LUCI CQ
parent 298450eb73
commit 81797744fd
12 changed files with 443 additions and 286 deletions

View File

@ -8436,7 +8436,7 @@
"dimension_sets": [
{
"cpu": "x86-64",
"os": "Windows-7-SP1"
"os": "Windows-10-19042"
}
],
"shards": 4
@ -8464,7 +8464,7 @@
"dimension_sets": [
{
"cpu": "x86-64",
"os": "Windows-7-SP1"
"os": "Windows-10-19042"
}
]
},
@ -8485,7 +8485,7 @@
"dimension_sets": [
{
"cpu": "x86-64",
"os": "Windows-7-SP1"
"os": "Windows-10-19042"
}
]
},
@ -8506,7 +8506,7 @@
"dimension_sets": [
{
"cpu": "x86-64",
"os": "Windows-7-SP1"
"os": "Windows-10-19042"
}
]
},
@ -8527,7 +8527,7 @@
"dimension_sets": [
{
"cpu": "x86-64",
"os": "Windows-7-SP1"
"os": "Windows-10-19042"
}
]
},
@ -8551,7 +8551,7 @@
"dimension_sets": [
{
"cpu": "x86-64",
"os": "Windows-7-SP1"
"os": "Windows-10-19042"
}
]
},
@ -8572,7 +8572,7 @@
"dimension_sets": [
{
"cpu": "x86-64",
"os": "Windows-7-SP1"
"os": "Windows-10-19042"
}
],
"shards": 2
@ -8594,7 +8594,7 @@
"dimension_sets": [
{
"cpu": "x86-64",
"os": "Windows-7-SP1"
"os": "Windows-10-19042"
}
],
"shards": 6
@ -8616,7 +8616,7 @@
"dimension_sets": [
{
"cpu": "x86-64",
"os": "Windows-7-SP1"
"os": "Windows-10-19042"
}
],
"shards": 4
@ -8638,7 +8638,7 @@
"dimension_sets": [
{
"cpu": "x86-64",
"os": "Windows-7-SP1"
"os": "Windows-10-19042"
}
]
},
@ -8659,7 +8659,7 @@
"dimension_sets": [
{
"cpu": "x86-64",
"os": "Windows-7-SP1"
"os": "Windows-10-19042"
}
]
},
@ -8680,7 +8680,7 @@
"dimension_sets": [
{
"cpu": "x86-64",
"os": "Windows-7-SP1"
"os": "Windows-10-19042"
}
]
},
@ -8701,7 +8701,7 @@
"dimension_sets": [
{
"cpu": "x86-64",
"os": "Windows-7-SP1"
"os": "Windows-10-19042"
}
],
"shards": 6
@ -8723,7 +8723,7 @@
"dimension_sets": [
{
"cpu": "x86-64",
"os": "Windows-7-SP1"
"os": "Windows-10-19042"
}
]
},
@ -8744,7 +8744,7 @@
"dimension_sets": [
{
"cpu": "x86-64",
"os": "Windows-7-SP1"
"os": "Windows-10-19042"
}
]
},
@ -8765,7 +8765,7 @@
"dimension_sets": [
{
"cpu": "x86-64",
"os": "Windows-7-SP1"
"os": "Windows-10-19042"
}
]
},
@ -8786,7 +8786,7 @@
"dimension_sets": [
{
"cpu": "x86-64",
"os": "Windows-7-SP1"
"os": "Windows-10-19042"
}
]
},
@ -8807,7 +8807,7 @@
"dimension_sets": [
{
"cpu": "x86-64",
"os": "Windows-7-SP1"
"os": "Windows-10-19042"
}
]
},
@ -8850,7 +8850,7 @@
"dimension_sets": [
{
"cpu": "x86-64",
"os": "Windows-7-SP1"
"os": "Windows-10-19042"
}
],
"shards": 4
@ -8872,7 +8872,7 @@
"dimension_sets": [
{
"cpu": "x86-64",
"os": "Windows-7-SP1"
"os": "Windows-10-19042"
}
]
},
@ -8893,7 +8893,7 @@
"dimension_sets": [
{
"cpu": "x86-64",
"os": "Windows-7-SP1"
"os": "Windows-10-19042"
}
]
},
@ -8918,7 +8918,7 @@
"dimension_sets": [
{
"cpu": "x86-64",
"os": "Windows-10-15063"
"os": "Windows-10-19042"
}
]
},
@ -8939,7 +8939,7 @@
"dimension_sets": [
{
"cpu": "x86-64",
"os": "Windows-10-15063"
"os": "Windows-10-19042"
}
]
},
@ -8960,7 +8960,7 @@
"dimension_sets": [
{
"cpu": "x86-64",
"os": "Windows-10-15063"
"os": "Windows-10-19042"
}
]
},
@ -8981,7 +8981,7 @@
"dimension_sets": [
{
"cpu": "x86-64",
"os": "Windows-10-15063"
"os": "Windows-10-19042"
}
]
},
@ -9005,7 +9005,7 @@
"dimension_sets": [
{
"cpu": "x86-64",
"os": "Windows-10-15063"
"os": "Windows-10-19042"
}
]
},
@ -9026,7 +9026,7 @@
"dimension_sets": [
{
"cpu": "x86-64",
"os": "Windows-10-15063"
"os": "Windows-10-19042"
}
],
"shards": 2
@ -9048,7 +9048,7 @@
"dimension_sets": [
{
"cpu": "x86-64",
"os": "Windows-10-15063"
"os": "Windows-10-19042"
}
],
"shards": 6
@ -9070,7 +9070,7 @@
"dimension_sets": [
{
"cpu": "x86-64",
"os": "Windows-10-15063"
"os": "Windows-10-19042"
}
],
"shards": 4
@ -9092,7 +9092,7 @@
"dimension_sets": [
{
"cpu": "x86-64",
"os": "Windows-10-15063"
"os": "Windows-10-19042"
}
]
},
@ -9113,7 +9113,7 @@
"dimension_sets": [
{
"cpu": "x86-64",
"os": "Windows-10-15063"
"os": "Windows-10-19042"
}
]
},
@ -9134,7 +9134,7 @@
"dimension_sets": [
{
"cpu": "x86-64",
"os": "Windows-10-15063"
"os": "Windows-10-19042"
}
]
},
@ -9155,7 +9155,7 @@
"dimension_sets": [
{
"cpu": "x86-64",
"os": "Windows-10-15063"
"os": "Windows-10-19042"
}
],
"shards": 6
@ -9177,7 +9177,7 @@
"dimension_sets": [
{
"cpu": "x86-64",
"os": "Windows-10-15063"
"os": "Windows-10-19042"
}
]
},
@ -9198,7 +9198,7 @@
"dimension_sets": [
{
"cpu": "x86-64",
"os": "Windows-10-15063"
"os": "Windows-10-19042"
}
]
},
@ -9219,7 +9219,7 @@
"dimension_sets": [
{
"cpu": "x86-64",
"os": "Windows-10-15063"
"os": "Windows-10-19042"
}
]
},
@ -9240,7 +9240,7 @@
"dimension_sets": [
{
"cpu": "x86-64",
"os": "Windows-10-15063"
"os": "Windows-10-19042"
}
]
},
@ -9261,7 +9261,7 @@
"dimension_sets": [
{
"cpu": "x86-64",
"os": "Windows-10-15063"
"os": "Windows-10-19042"
}
]
},
@ -9282,7 +9282,7 @@
"dimension_sets": [
{
"cpu": "x86-64",
"os": "Windows-10-15063"
"os": "Windows-10-19042"
}
],
"shards": 4
@ -9304,7 +9304,7 @@
"dimension_sets": [
{
"cpu": "x86-64",
"os": "Windows-10-15063"
"os": "Windows-10-19042"
}
]
},
@ -9325,7 +9325,7 @@
"dimension_sets": [
{
"cpu": "x86-64",
"os": "Windows-10-15063"
"os": "Windows-10-19042"
}
]
},

View File

@ -322,17 +322,10 @@
}
}
},
'win10-1703': {
'win10': {
'swarming': {
'dimensions': {
'os': 'Windows-10-15063'
}
}
},
'win7': {
'swarming': {
'dimensions': {
'os': 'Windows-7-SP1'
'os': 'Windows-10-19042'
}
}
},

View File

@ -259,12 +259,5 @@
'os': 'Windows'
}
}
},
'win10-1703': {
'swarming': {
'dimensions': {
'os': 'Windows-10-15063',
},
},
},
}
}

View File

@ -220,13 +220,11 @@
},
'win_video_capture_tests': {
'video_capture_tests': {
'remove_mixins': ['win7'],
'mixins': ['win', 'baremetal-pool'],
}
},
'win_video_capture_tests_tryserver': {
'video_capture_tests': {
'remove_mixins': ['win7'],
'mixins': ['win', 'baremetal-try-pool'],
}
},

View File

@ -12364,7 +12364,7 @@
"dimension_sets": [
{
"cpu": "x86-64",
"os": "Windows-10-15063"
"os": "Windows-10-19042"
}
]
},
@ -12385,7 +12385,7 @@
"dimension_sets": [
{
"cpu": "x86-64",
"os": "Windows-10-15063"
"os": "Windows-10-19042"
}
]
},
@ -12406,7 +12406,7 @@
"dimension_sets": [
{
"cpu": "x86-64",
"os": "Windows-10-15063"
"os": "Windows-10-19042"
}
]
},
@ -12427,7 +12427,7 @@
"dimension_sets": [
{
"cpu": "x86-64",
"os": "Windows-10-15063"
"os": "Windows-10-19042"
}
]
},
@ -12451,7 +12451,7 @@
"dimension_sets": [
{
"cpu": "x86-64",
"os": "Windows-10-15063"
"os": "Windows-10-19042"
}
]
},
@ -12472,7 +12472,7 @@
"dimension_sets": [
{
"cpu": "x86-64",
"os": "Windows-10-15063"
"os": "Windows-10-19042"
}
],
"shards": 2
@ -12494,7 +12494,7 @@
"dimension_sets": [
{
"cpu": "x86-64",
"os": "Windows-10-15063"
"os": "Windows-10-19042"
}
],
"shards": 6
@ -12516,7 +12516,7 @@
"dimension_sets": [
{
"cpu": "x86-64",
"os": "Windows-10-15063"
"os": "Windows-10-19042"
}
],
"shards": 4
@ -12538,7 +12538,7 @@
"dimension_sets": [
{
"cpu": "x86-64",
"os": "Windows-10-15063"
"os": "Windows-10-19042"
}
]
},
@ -12559,7 +12559,7 @@
"dimension_sets": [
{
"cpu": "x86-64",
"os": "Windows-10-15063"
"os": "Windows-10-19042"
}
]
},
@ -12580,7 +12580,7 @@
"dimension_sets": [
{
"cpu": "x86-64",
"os": "Windows-10-15063"
"os": "Windows-10-19042"
}
]
},
@ -12601,7 +12601,7 @@
"dimension_sets": [
{
"cpu": "x86-64",
"os": "Windows-10-15063"
"os": "Windows-10-19042"
}
],
"shards": 6
@ -12623,7 +12623,7 @@
"dimension_sets": [
{
"cpu": "x86-64",
"os": "Windows-10-15063"
"os": "Windows-10-19042"
}
]
},
@ -12644,7 +12644,7 @@
"dimension_sets": [
{
"cpu": "x86-64",
"os": "Windows-10-15063"
"os": "Windows-10-19042"
}
]
},
@ -12665,7 +12665,7 @@
"dimension_sets": [
{
"cpu": "x86-64",
"os": "Windows-10-15063"
"os": "Windows-10-19042"
}
]
},
@ -12686,7 +12686,7 @@
"dimension_sets": [
{
"cpu": "x86-64",
"os": "Windows-10-15063"
"os": "Windows-10-19042"
}
]
},
@ -12707,7 +12707,7 @@
"dimension_sets": [
{
"cpu": "x86-64",
"os": "Windows-10-15063"
"os": "Windows-10-19042"
}
]
},
@ -12728,7 +12728,7 @@
"dimension_sets": [
{
"cpu": "x86-64",
"os": "Windows-10-15063"
"os": "Windows-10-19042"
}
],
"shards": 4
@ -12750,7 +12750,7 @@
"dimension_sets": [
{
"cpu": "x86-64",
"os": "Windows-10-15063"
"os": "Windows-10-19042"
}
]
},
@ -12771,7 +12771,7 @@
"dimension_sets": [
{
"cpu": "x86-64",
"os": "Windows-10-15063"
"os": "Windows-10-19042"
}
]
},
@ -12800,7 +12800,7 @@
"dimension_sets": [
{
"cpu": "x86-64",
"os": "Windows-7-SP1"
"os": "Windows-10-19042"
}
]
},
@ -12821,7 +12821,7 @@
"dimension_sets": [
{
"cpu": "x86-64",
"os": "Windows-7-SP1"
"os": "Windows-10-19042"
}
]
},
@ -12842,7 +12842,7 @@
"dimension_sets": [
{
"cpu": "x86-64",
"os": "Windows-7-SP1"
"os": "Windows-10-19042"
}
]
},
@ -12863,7 +12863,7 @@
"dimension_sets": [
{
"cpu": "x86-64",
"os": "Windows-7-SP1"
"os": "Windows-10-19042"
}
]
},
@ -12887,7 +12887,7 @@
"dimension_sets": [
{
"cpu": "x86-64",
"os": "Windows-7-SP1"
"os": "Windows-10-19042"
}
]
},
@ -12908,7 +12908,7 @@
"dimension_sets": [
{
"cpu": "x86-64",
"os": "Windows-7-SP1"
"os": "Windows-10-19042"
}
],
"shards": 2
@ -12930,7 +12930,7 @@
"dimension_sets": [
{
"cpu": "x86-64",
"os": "Windows-7-SP1"
"os": "Windows-10-19042"
}
],
"shards": 6
@ -12952,7 +12952,7 @@
"dimension_sets": [
{
"cpu": "x86-64",
"os": "Windows-7-SP1"
"os": "Windows-10-19042"
}
],
"shards": 4
@ -12974,7 +12974,7 @@
"dimension_sets": [
{
"cpu": "x86-64",
"os": "Windows-7-SP1"
"os": "Windows-10-19042"
}
]
},
@ -12995,7 +12995,7 @@
"dimension_sets": [
{
"cpu": "x86-64",
"os": "Windows-7-SP1"
"os": "Windows-10-19042"
}
]
},
@ -13016,7 +13016,7 @@
"dimension_sets": [
{
"cpu": "x86-64",
"os": "Windows-7-SP1"
"os": "Windows-10-19042"
}
]
},
@ -13037,7 +13037,7 @@
"dimension_sets": [
{
"cpu": "x86-64",
"os": "Windows-7-SP1"
"os": "Windows-10-19042"
}
],
"shards": 6
@ -13059,7 +13059,7 @@
"dimension_sets": [
{
"cpu": "x86-64",
"os": "Windows-7-SP1"
"os": "Windows-10-19042"
}
]
},
@ -13080,7 +13080,7 @@
"dimension_sets": [
{
"cpu": "x86-64",
"os": "Windows-7-SP1"
"os": "Windows-10-19042"
}
]
},
@ -13101,7 +13101,7 @@
"dimension_sets": [
{
"cpu": "x86-64",
"os": "Windows-7-SP1"
"os": "Windows-10-19042"
}
]
},
@ -13122,7 +13122,7 @@
"dimension_sets": [
{
"cpu": "x86-64",
"os": "Windows-7-SP1"
"os": "Windows-10-19042"
}
]
},
@ -13143,7 +13143,7 @@
"dimension_sets": [
{
"cpu": "x86-64",
"os": "Windows-7-SP1"
"os": "Windows-10-19042"
}
]
},
@ -13164,7 +13164,7 @@
"dimension_sets": [
{
"cpu": "x86-64",
"os": "Windows-7-SP1"
"os": "Windows-10-19042"
}
],
"shards": 4
@ -13186,7 +13186,7 @@
"dimension_sets": [
{
"cpu": "x86-64",
"os": "Windows-7-SP1"
"os": "Windows-10-19042"
}
]
},
@ -13207,7 +13207,7 @@
"dimension_sets": [
{
"cpu": "x86-64",
"os": "Windows-7-SP1"
"os": "Windows-10-19042"
}
]
},
@ -13232,7 +13232,7 @@
"dimension_sets": [
{
"cpu": "x86-64",
"os": "Windows-10-15063"
"os": "Windows-10-19042"
}
]
},
@ -13253,7 +13253,7 @@
"dimension_sets": [
{
"cpu": "x86-64",
"os": "Windows-10-15063"
"os": "Windows-10-19042"
}
]
},
@ -13274,7 +13274,7 @@
"dimension_sets": [
{
"cpu": "x86-64",
"os": "Windows-10-15063"
"os": "Windows-10-19042"
}
]
},
@ -13295,7 +13295,7 @@
"dimension_sets": [
{
"cpu": "x86-64",
"os": "Windows-10-15063"
"os": "Windows-10-19042"
}
]
},
@ -13319,7 +13319,7 @@
"dimension_sets": [
{
"cpu": "x86-64",
"os": "Windows-10-15063"
"os": "Windows-10-19042"
}
]
},
@ -13340,7 +13340,7 @@
"dimension_sets": [
{
"cpu": "x86-64",
"os": "Windows-10-15063"
"os": "Windows-10-19042"
}
],
"shards": 2
@ -13362,7 +13362,7 @@
"dimension_sets": [
{
"cpu": "x86-64",
"os": "Windows-10-15063"
"os": "Windows-10-19042"
}
],
"shards": 6
@ -13384,7 +13384,7 @@
"dimension_sets": [
{
"cpu": "x86-64",
"os": "Windows-10-15063"
"os": "Windows-10-19042"
}
],
"shards": 4
@ -13406,7 +13406,7 @@
"dimension_sets": [
{
"cpu": "x86-64",
"os": "Windows-10-15063"
"os": "Windows-10-19042"
}
]
},
@ -13427,7 +13427,7 @@
"dimension_sets": [
{
"cpu": "x86-64",
"os": "Windows-10-15063"
"os": "Windows-10-19042"
}
]
},
@ -13448,7 +13448,7 @@
"dimension_sets": [
{
"cpu": "x86-64",
"os": "Windows-10-15063"
"os": "Windows-10-19042"
}
]
},
@ -13469,7 +13469,7 @@
"dimension_sets": [
{
"cpu": "x86-64",
"os": "Windows-10-15063"
"os": "Windows-10-19042"
}
],
"shards": 6
@ -13491,7 +13491,7 @@
"dimension_sets": [
{
"cpu": "x86-64",
"os": "Windows-10-15063"
"os": "Windows-10-19042"
}
]
},
@ -13512,7 +13512,7 @@
"dimension_sets": [
{
"cpu": "x86-64",
"os": "Windows-10-15063"
"os": "Windows-10-19042"
}
]
},
@ -13533,7 +13533,7 @@
"dimension_sets": [
{
"cpu": "x86-64",
"os": "Windows-10-15063"
"os": "Windows-10-19042"
}
]
},
@ -13554,7 +13554,7 @@
"dimension_sets": [
{
"cpu": "x86-64",
"os": "Windows-10-15063"
"os": "Windows-10-19042"
}
]
},
@ -13575,7 +13575,7 @@
"dimension_sets": [
{
"cpu": "x86-64",
"os": "Windows-10-15063"
"os": "Windows-10-19042"
}
]
},
@ -13596,7 +13596,7 @@
"dimension_sets": [
{
"cpu": "x86-64",
"os": "Windows-10-15063"
"os": "Windows-10-19042"
}
],
"shards": 4
@ -13618,7 +13618,7 @@
"dimension_sets": [
{
"cpu": "x86-64",
"os": "Windows-10-15063"
"os": "Windows-10-19042"
}
]
},
@ -13639,7 +13639,7 @@
"dimension_sets": [
{
"cpu": "x86-64",
"os": "Windows-10-15063"
"os": "Windows-10-19042"
}
]
},
@ -13664,7 +13664,7 @@
"dimension_sets": [
{
"cpu": "x86-64",
"os": "Windows-7-SP1"
"os": "Windows-10-19042"
}
]
},
@ -13685,7 +13685,7 @@
"dimension_sets": [
{
"cpu": "x86-64",
"os": "Windows-7-SP1"
"os": "Windows-10-19042"
}
]
},
@ -13706,7 +13706,7 @@
"dimension_sets": [
{
"cpu": "x86-64",
"os": "Windows-7-SP1"
"os": "Windows-10-19042"
}
]
},
@ -13727,7 +13727,7 @@
"dimension_sets": [
{
"cpu": "x86-64",
"os": "Windows-7-SP1"
"os": "Windows-10-19042"
}
]
},
@ -13751,7 +13751,7 @@
"dimension_sets": [
{
"cpu": "x86-64",
"os": "Windows-7-SP1"
"os": "Windows-10-19042"
}
]
},
@ -13772,7 +13772,7 @@
"dimension_sets": [
{
"cpu": "x86-64",
"os": "Windows-7-SP1"
"os": "Windows-10-19042"
}
],
"shards": 2
@ -13794,7 +13794,7 @@
"dimension_sets": [
{
"cpu": "x86-64",
"os": "Windows-7-SP1"
"os": "Windows-10-19042"
}
],
"shards": 6
@ -13816,7 +13816,7 @@
"dimension_sets": [
{
"cpu": "x86-64",
"os": "Windows-7-SP1"
"os": "Windows-10-19042"
}
],
"shards": 4
@ -13838,7 +13838,7 @@
"dimension_sets": [
{
"cpu": "x86-64",
"os": "Windows-7-SP1"
"os": "Windows-10-19042"
}
]
},
@ -13859,7 +13859,7 @@
"dimension_sets": [
{
"cpu": "x86-64",
"os": "Windows-7-SP1"
"os": "Windows-10-19042"
}
]
},
@ -13880,7 +13880,7 @@
"dimension_sets": [
{
"cpu": "x86-64",
"os": "Windows-7-SP1"
"os": "Windows-10-19042"
}
]
},
@ -13901,7 +13901,7 @@
"dimension_sets": [
{
"cpu": "x86-64",
"os": "Windows-7-SP1"
"os": "Windows-10-19042"
}
],
"shards": 6
@ -13923,7 +13923,7 @@
"dimension_sets": [
{
"cpu": "x86-64",
"os": "Windows-7-SP1"
"os": "Windows-10-19042"
}
]
},
@ -13944,7 +13944,7 @@
"dimension_sets": [
{
"cpu": "x86-64",
"os": "Windows-7-SP1"
"os": "Windows-10-19042"
}
]
},
@ -13965,7 +13965,7 @@
"dimension_sets": [
{
"cpu": "x86-64",
"os": "Windows-7-SP1"
"os": "Windows-10-19042"
}
]
},
@ -13986,7 +13986,7 @@
"dimension_sets": [
{
"cpu": "x86-64",
"os": "Windows-7-SP1"
"os": "Windows-10-19042"
}
]
},
@ -14007,7 +14007,7 @@
"dimension_sets": [
{
"cpu": "x86-64",
"os": "Windows-7-SP1"
"os": "Windows-10-19042"
}
]
},
@ -14028,7 +14028,7 @@
"dimension_sets": [
{
"cpu": "x86-64",
"os": "Windows-7-SP1"
"os": "Windows-10-19042"
}
],
"shards": 4
@ -14050,7 +14050,7 @@
"dimension_sets": [
{
"cpu": "x86-64",
"os": "Windows-7-SP1"
"os": "Windows-10-19042"
}
]
},
@ -14071,7 +14071,7 @@
"dimension_sets": [
{
"cpu": "x86-64",
"os": "Windows-7-SP1"
"os": "Windows-10-19042"
}
]
},
@ -14096,7 +14096,7 @@
"dimension_sets": [
{
"cpu": "x86-64",
"os": "Windows-7-SP1"
"os": "Windows-10-19042"
}
]
},
@ -14117,7 +14117,7 @@
"dimension_sets": [
{
"cpu": "x86-64",
"os": "Windows-7-SP1"
"os": "Windows-10-19042"
}
]
},
@ -14138,7 +14138,7 @@
"dimension_sets": [
{
"cpu": "x86-64",
"os": "Windows-7-SP1"
"os": "Windows-10-19042"
}
]
},
@ -14159,7 +14159,7 @@
"dimension_sets": [
{
"cpu": "x86-64",
"os": "Windows-7-SP1"
"os": "Windows-10-19042"
}
]
},
@ -14183,7 +14183,7 @@
"dimension_sets": [
{
"cpu": "x86-64",
"os": "Windows-7-SP1"
"os": "Windows-10-19042"
}
]
},
@ -14204,7 +14204,7 @@
"dimension_sets": [
{
"cpu": "x86-64",
"os": "Windows-7-SP1"
"os": "Windows-10-19042"
}
],
"shards": 2
@ -14226,7 +14226,7 @@
"dimension_sets": [
{
"cpu": "x86-64",
"os": "Windows-7-SP1"
"os": "Windows-10-19042"
}
],
"shards": 6
@ -14248,7 +14248,7 @@
"dimension_sets": [
{
"cpu": "x86-64",
"os": "Windows-7-SP1"
"os": "Windows-10-19042"
}
],
"shards": 4
@ -14270,7 +14270,7 @@
"dimension_sets": [
{
"cpu": "x86-64",
"os": "Windows-7-SP1"
"os": "Windows-10-19042"
}
]
},
@ -14291,7 +14291,7 @@
"dimension_sets": [
{
"cpu": "x86-64",
"os": "Windows-7-SP1"
"os": "Windows-10-19042"
}
]
},
@ -14312,7 +14312,7 @@
"dimension_sets": [
{
"cpu": "x86-64",
"os": "Windows-7-SP1"
"os": "Windows-10-19042"
}
]
},
@ -14333,7 +14333,7 @@
"dimension_sets": [
{
"cpu": "x86-64",
"os": "Windows-7-SP1"
"os": "Windows-10-19042"
}
],
"shards": 6
@ -14355,7 +14355,7 @@
"dimension_sets": [
{
"cpu": "x86-64",
"os": "Windows-7-SP1"
"os": "Windows-10-19042"
}
]
},
@ -14376,7 +14376,7 @@
"dimension_sets": [
{
"cpu": "x86-64",
"os": "Windows-7-SP1"
"os": "Windows-10-19042"
}
]
},
@ -14397,7 +14397,7 @@
"dimension_sets": [
{
"cpu": "x86-64",
"os": "Windows-7-SP1"
"os": "Windows-10-19042"
}
]
},
@ -14418,7 +14418,7 @@
"dimension_sets": [
{
"cpu": "x86-64",
"os": "Windows-7-SP1"
"os": "Windows-10-19042"
}
]
},
@ -14439,7 +14439,7 @@
"dimension_sets": [
{
"cpu": "x86-64",
"os": "Windows-7-SP1"
"os": "Windows-10-19042"
}
]
},
@ -14460,7 +14460,7 @@
"dimension_sets": [
{
"cpu": "x86-64",
"os": "Windows-7-SP1"
"os": "Windows-10-19042"
}
],
"shards": 4
@ -14482,7 +14482,7 @@
"dimension_sets": [
{
"cpu": "x86-64",
"os": "Windows-7-SP1"
"os": "Windows-10-19042"
}
]
},
@ -14503,7 +14503,7 @@
"dimension_sets": [
{
"cpu": "x86-64",
"os": "Windows-7-SP1"
"os": "Windows-10-19042"
}
]
},
@ -14528,7 +14528,7 @@
"dimension_sets": [
{
"cpu": "x86-64",
"os": "Windows-7-SP1"
"os": "Windows-10-19042"
}
]
},
@ -14549,7 +14549,7 @@
"dimension_sets": [
{
"cpu": "x86-64",
"os": "Windows-7-SP1"
"os": "Windows-10-19042"
}
]
},
@ -14570,7 +14570,7 @@
"dimension_sets": [
{
"cpu": "x86-64",
"os": "Windows-7-SP1"
"os": "Windows-10-19042"
}
]
},
@ -14591,7 +14591,7 @@
"dimension_sets": [
{
"cpu": "x86-64",
"os": "Windows-7-SP1"
"os": "Windows-10-19042"
}
]
},
@ -14615,7 +14615,7 @@
"dimension_sets": [
{
"cpu": "x86-64",
"os": "Windows-7-SP1"
"os": "Windows-10-19042"
}
]
},
@ -14636,7 +14636,7 @@
"dimension_sets": [
{
"cpu": "x86-64",
"os": "Windows-7-SP1"
"os": "Windows-10-19042"
}
],
"shards": 2
@ -14658,7 +14658,7 @@
"dimension_sets": [
{
"cpu": "x86-64",
"os": "Windows-7-SP1"
"os": "Windows-10-19042"
}
],
"shards": 6
@ -14680,7 +14680,7 @@
"dimension_sets": [
{
"cpu": "x86-64",
"os": "Windows-7-SP1"
"os": "Windows-10-19042"
}
],
"shards": 4
@ -14702,7 +14702,7 @@
"dimension_sets": [
{
"cpu": "x86-64",
"os": "Windows-7-SP1"
"os": "Windows-10-19042"
}
]
},
@ -14723,7 +14723,7 @@
"dimension_sets": [
{
"cpu": "x86-64",
"os": "Windows-7-SP1"
"os": "Windows-10-19042"
}
]
},
@ -14744,7 +14744,7 @@
"dimension_sets": [
{
"cpu": "x86-64",
"os": "Windows-7-SP1"
"os": "Windows-10-19042"
}
]
},
@ -14765,7 +14765,7 @@
"dimension_sets": [
{
"cpu": "x86-64",
"os": "Windows-7-SP1"
"os": "Windows-10-19042"
}
],
"shards": 6
@ -14787,7 +14787,7 @@
"dimension_sets": [
{
"cpu": "x86-64",
"os": "Windows-7-SP1"
"os": "Windows-10-19042"
}
]
},
@ -14808,7 +14808,7 @@
"dimension_sets": [
{
"cpu": "x86-64",
"os": "Windows-7-SP1"
"os": "Windows-10-19042"
}
]
},
@ -14829,7 +14829,7 @@
"dimension_sets": [
{
"cpu": "x86-64",
"os": "Windows-7-SP1"
"os": "Windows-10-19042"
}
]
},
@ -14850,7 +14850,7 @@
"dimension_sets": [
{
"cpu": "x86-64",
"os": "Windows-7-SP1"
"os": "Windows-10-19042"
}
]
},
@ -14871,7 +14871,7 @@
"dimension_sets": [
{
"cpu": "x86-64",
"os": "Windows-7-SP1"
"os": "Windows-10-19042"
}
]
},
@ -14914,7 +14914,7 @@
"dimension_sets": [
{
"cpu": "x86-64",
"os": "Windows-7-SP1"
"os": "Windows-10-19042"
}
],
"shards": 4
@ -14936,7 +14936,7 @@
"dimension_sets": [
{
"cpu": "x86-64",
"os": "Windows-7-SP1"
"os": "Windows-10-19042"
}
]
},
@ -14957,7 +14957,7 @@
"dimension_sets": [
{
"cpu": "x86-64",
"os": "Windows-7-SP1"
"os": "Windows-10-19042"
}
]
},
@ -14984,7 +14984,7 @@
"dimension_sets": [
{
"cpu": "x86-64",
"os": "Windows-7-SP1"
"os": "Windows-10-19042"
}
]
},
@ -15009,7 +15009,7 @@
"dimension_sets": [
{
"cpu": "x86-64",
"os": "Windows-7-SP1"
"os": "Windows-10-19042"
}
],
"shards": 4

View File

@ -179,7 +179,7 @@
'MacArm64 Builder': {},
'Win (more configs)': {
'os_type': 'win',
'mixins': ['win7', 'x86-64', 'resultdb-json-format'],
'mixins': ['win10', 'x86-64', 'resultdb-json-format'],
'test_suites': {
'isolated_scripts': 'more_configs_tests',
},
@ -188,14 +188,14 @@
'Win32 Debug (Clang)': {},
'Win32 Release (Clang)': {
'os_type': 'win',
'mixins': ['win7', 'x86-64', 'resultdb-json-format'],
'mixins': ['win10', 'x86-64', 'resultdb-json-format'],
'test_suites': {
'isolated_scripts': 'win_tests',
},
},
'Win64 ASan': {
'os_type': 'win',
'mixins': ['win10-1703', 'x86-64', 'resultdb-json-format'],
'mixins': ['win10', 'x86-64', 'resultdb-json-format'],
'test_suites': {
'isolated_scripts': 'desktop_tests',
},
@ -581,7 +581,7 @@
},
'win_asan': {
'os_type': 'win',
'mixins': ['win10-1703', 'x86-64', 'resultdb-json-format'],
'mixins': ['win10', 'x86-64', 'resultdb-json-format'],
'test_suites': {
'isolated_scripts': 'desktop_tests',
},
@ -592,42 +592,42 @@
'win_compile_x86_clang_rel': {},
'win_x64_clang_dbg': {
'os_type': 'win',
'mixins': ['win7', 'x86-64', 'resultdb-json-format'],
'mixins': ['win10', 'x86-64', 'resultdb-json-format'],
'test_suites': {
'isolated_scripts': 'desktop_tests',
},
},
'win_x64_clang_dbg_win10': {
'os_type': 'win',
'mixins': ['win10-1703', 'x86-64', 'resultdb-json-format'],
'mixins': ['win10', 'x86-64', 'resultdb-json-format'],
'test_suites': {
'isolated_scripts': 'desktop_tests',
},
},
'win_x64_clang_rel': {
'os_type': 'win',
'mixins': ['win7', 'x86-64', 'resultdb-json-format'],
'mixins': ['win10', 'x86-64', 'resultdb-json-format'],
'test_suites': {
'isolated_scripts': 'desktop_tests',
},
},
'win_x86_clang_dbg': {
'os_type': 'win',
'mixins': ['win7', 'x86-64', 'resultdb-json-format'],
'mixins': ['win10', 'x86-64', 'resultdb-json-format'],
'test_suites': {
'isolated_scripts': 'desktop_tests',
},
},
'win_x86_clang_rel': {
'os_type': 'win',
'mixins': ['win7', 'x86-64', 'resultdb-json-format'],
'mixins': ['win10', 'x86-64', 'resultdb-json-format'],
'test_suites': {
'isolated_scripts': 'win_tests_tryserver',
},
},
'win_x86_more_configs': {
'os_type': 'win',
'mixins': ['win7', 'x86-64', 'resultdb-json-format'],
'mixins': ['win10', 'x86-64', 'resultdb-json-format'],
'test_suites': {
'isolated_scripts': 'more_configs_tests',
},

View File

@ -636,7 +636,10 @@ rtc_library("desktop_capture") {
"win/wgc_desktop_frame.h",
]
libs += [ "dwmapi.lib" ]
deps += [ "../../rtc_base/win:hstring" ]
deps += [
"../../rtc_base:rtc_event",
"../../rtc_base/win:hstring",
]
}
}

View File

@ -10,6 +10,7 @@
#include "modules/desktop_capture/win/wgc_capture_session.h"
#include <DispatcherQueue.h>
#include <windows.graphics.capture.interop.h>
#include <windows.graphics.directX.direct3d11.interop.h>
#include <windows.graphics.h>
@ -36,13 +37,13 @@ namespace {
// We must use a BGRA pixel format that has 4 bytes per pixel, as required by
// the DesktopFrame interface.
const auto kPixelFormat = ABI::Windows::Graphics::DirectX::DirectXPixelFormat::
DirectXPixelFormat_B8G8R8A8UIntNormalized;
constexpr auto kPixelFormat = ABI::Windows::Graphics::DirectX::
DirectXPixelFormat::DirectXPixelFormat_B8G8R8A8UIntNormalized;
// We only want 1 buffer in our frame pool to reduce latency. If we had more,
// they would sit in the pool for longer and be stale by the time we are asked
// for a new frame.
const int kNumBuffers = 1;
// The maximum time `GetFrame` will wait for a frame to arrive, if we don't have
// any in the pool.
constexpr int kMaxWaitForFrameMs = 50;
constexpr int kMaxWaitForFirstFrameMs = 500;
// These values are persisted to logs. Entries should not be renumbered and
// numeric values should never be reused.
@ -54,9 +55,9 @@ enum class StartCaptureResult {
kD3dDelayLoadFailed = 4,
kD3dDeviceCreationFailed = 5,
kFramePoolActivationFailed = 6,
kFramePoolCastFailed = 7,
kGetItemSizeFailed = 8,
kCreateFreeThreadedFailed = 9,
// kFramePoolCastFailed = 7, (deprecated)
// kGetItemSizeFailed = 8, (deprecated)
kCreateFramePoolFailed = 9,
kCreateCaptureSessionFailed = 10,
kStartCaptureFailed = 11,
kMaxValue = kStartCaptureFailed
@ -100,7 +101,9 @@ WgcCaptureSession::WgcCaptureSession(ComPtr<ID3D11Device> d3d11_device,
: d3d11_device_(std::move(d3d11_device)),
item_(std::move(item)),
size_(size) {}
WgcCaptureSession::~WgcCaptureSession() = default;
WgcCaptureSession::~WgcCaptureSession() {
RemoveEventHandlers();
}
HRESULT WgcCaptureSession::StartCapture() {
RTC_DCHECK_RUN_ON(&sequence_checker_);
@ -118,12 +121,13 @@ HRESULT WgcCaptureSession::StartCapture() {
// Listen for the Closed event, to detect if the source we are capturing is
// closed (e.g. application window is closed or monitor is disconnected). If
// it is, we should abort the capture.
item_closed_token_ = std::make_unique<EventRegistrationToken>();
auto closed_handler =
Microsoft::WRL::Callback<ABI::Windows::Foundation::ITypedEventHandler<
WGC::GraphicsCaptureItem*, IInspectable*>>(
this, &WgcCaptureSession::OnItemClosed);
EventRegistrationToken item_closed_token;
HRESULT hr = item_->add_Closed(closed_handler.Get(), &item_closed_token);
HRESULT hr =
item_->add_Closed(closed_handler.Get(), item_closed_token_.get());
if (FAILED(hr)) {
RecordStartCaptureResult(StartCaptureResult::kAddClosedFailed);
return hr;
@ -157,22 +161,25 @@ HRESULT WgcCaptureSession::StartCapture() {
return hr;
}
// Cast to FramePoolStatics2 so we can use CreateFreeThreaded and avoid the
// need to have a DispatcherQueue. We don't listen for the FrameArrived event,
// so there's no difference.
ComPtr<WGC::IDirect3D11CaptureFramePoolStatics2> frame_pool_statics2;
hr = frame_pool_statics->QueryInterface(IID_PPV_ARGS(&frame_pool_statics2));
hr = frame_pool_statics->Create(direct3d_device_.Get(), kPixelFormat,
kNumBuffers, size_, &frame_pool_);
if (FAILED(hr)) {
RecordStartCaptureResult(StartCaptureResult::kFramePoolCastFailed);
RecordStartCaptureResult(StartCaptureResult::kCreateFramePoolFailed);
return hr;
}
hr = frame_pool_statics2->CreateFreeThreaded(
direct3d_device_.Get(), kPixelFormat, kNumBuffers, size_, &frame_pool_);
if (FAILED(hr)) {
RecordStartCaptureResult(StartCaptureResult::kCreateFreeThreadedFailed);
return hr;
}
frames_in_pool_ = 0;
// Because `WgcCapturerWin` created a `DispatcherQueue`, and we created
// `frame_pool_` via `Create`, the `FrameArrived` event will be delivered on
// the current thread.
frame_arrived_token_ = std::make_unique<EventRegistrationToken>();
auto frame_arrived_handler =
Microsoft::WRL::Callback<ABI::Windows::Foundation::ITypedEventHandler<
WGC::Direct3D11CaptureFramePool*, IInspectable*>>(
this, &WgcCaptureSession::OnFrameArrived);
hr = frame_pool_->add_FrameArrived(frame_arrived_handler.Get(),
frame_arrived_token_.get());
hr = frame_pool_->CreateCaptureSession(item_.Get(), &session_);
if (FAILED(hr)) {
@ -205,6 +212,10 @@ HRESULT WgcCaptureSession::GetFrame(
RTC_DCHECK(is_capture_started_);
if (frames_in_pool_ < 1)
wait_for_frame_event_.Wait(first_frame_ ? kMaxWaitForFirstFrameMs
: kMaxWaitForFrameMs);
ComPtr<WGC::IDirect3D11CaptureFrame> capture_frame;
HRESULT hr = frame_pool_->TryGetNextFrame(&capture_frame);
if (FAILED(hr)) {
@ -218,6 +229,9 @@ HRESULT WgcCaptureSession::GetFrame(
return hr;
}
first_frame_ = false;
--frames_in_pool_;
// We need to get `capture_frame` as an `ID3D11Texture2D` so that we can get
// the raw image data in the format required by the `DesktopFrame` interface.
ComPtr<ABI::Windows::Graphics::DirectX::Direct3D11::IDirect3DSurface>
@ -358,6 +372,16 @@ HRESULT WgcCaptureSession::CreateMappedTexture(
return d3d11_device_->CreateTexture2D(&map_desc, nullptr, &mapped_texture_);
}
HRESULT WgcCaptureSession::OnFrameArrived(
WGC::IDirect3D11CaptureFramePool* sender,
IInspectable* event_args) {
RTC_DCHECK_RUN_ON(&sequence_checker_);
RTC_DCHECK_LT(frames_in_pool_, kNumBuffers);
++frames_in_pool_;
wait_for_frame_event_.Set();
return S_OK;
}
HRESULT WgcCaptureSession::OnItemClosed(WGC::IGraphicsCaptureItem* sender,
IInspectable* event_args) {
RTC_DCHECK_RUN_ON(&sequence_checker_);
@ -366,6 +390,8 @@ HRESULT WgcCaptureSession::OnItemClosed(WGC::IGraphicsCaptureItem* sender,
item_closed_ = true;
is_capture_started_ = false;
RemoveEventHandlers();
mapped_texture_ = nullptr;
session_ = nullptr;
frame_pool_ = nullptr;
@ -376,4 +402,22 @@ HRESULT WgcCaptureSession::OnItemClosed(WGC::IGraphicsCaptureItem* sender,
return S_OK;
}
void WgcCaptureSession::RemoveEventHandlers() {
HRESULT hr;
if (frame_pool_ && frame_arrived_token_) {
hr = frame_pool_->remove_FrameArrived(*frame_arrived_token_);
frame_arrived_token_.reset();
if (FAILED(hr)) {
RTC_LOG(LS_WARNING) << "Failed to remove FrameArrived event handler: "
<< hr;
}
}
if (item_ && item_closed_token_) {
hr = item_->remove_Closed(*item_closed_token_);
item_closed_token_.reset();
if (FAILED(hr))
RTC_LOG(LS_WARNING) << "Failed to remove Closed event handler: " << hr;
}
}
} // namespace webrtc

View File

@ -21,6 +21,7 @@
#include "api/sequence_checker.h"
#include "modules/desktop_capture/desktop_capture_options.h"
#include "modules/desktop_capture/win/wgc_capture_source.h"
#include "rtc_base/event.h"
namespace webrtc {
@ -48,6 +49,12 @@ class WgcCaptureSession final {
return is_capture_started_;
}
// We keep 2 buffers in the frame pool to balance the staleness of the frame
// with having to wait for frames to arrive too frequently. Too many buffers
// will lead to a high latency, and too few will lead to poor performance.
// We make this public for tests.
static constexpr int kNumBuffers = 2;
private:
// Initializes `mapped_texture_` with the properties of the `src_texture`,
// overrides the values of some necessary properties like the
@ -64,6 +71,24 @@ class WgcCaptureSession final {
ABI::Windows::Graphics::Capture::IGraphicsCaptureItem* sender,
IInspectable* event_args);
// Event handler for `frame_pool_`'s FrameArrived event.
HRESULT OnFrameArrived(
ABI::Windows::Graphics::Capture::IDirect3D11CaptureFramePool* sender,
IInspectable* event_args);
void RemoveEventHandlers();
// We wait on this event in `GetFrame` if there are no frames in the pool.
// `OnFrameArrived` will set the event so we can proceed.
rtc::Event wait_for_frame_event_;
int frames_in_pool_;
// We're willing to wait for a frame a little longer if it's the first one.
bool first_frame_ = true;
std::unique_ptr<EventRegistrationToken> frame_arrived_token_;
std::unique_ptr<EventRegistrationToken> item_closed_token_;
// A Direct3D11 Device provided by the caller. We use this to create an
// IDirect3DDevice, and also to create textures that will hold the image data.
Microsoft::WRL::ComPtr<ID3D11Device> d3d11_device_;

View File

@ -10,6 +10,7 @@
#include "modules/desktop_capture/win/wgc_capturer_win.h"
#include <DispatcherQueue.h>
#include <windows.foundation.metadata.h>
#include <windows.graphics.capture.h>
@ -32,10 +33,12 @@ namespace webrtc {
namespace {
const wchar_t kWgcSessionType[] =
constexpr wchar_t kCoreMessagingDll[] = L"CoreMessaging.dll";
constexpr wchar_t kWgcSessionType[] =
L"Windows.Graphics.Capture.GraphicsCaptureSession";
const wchar_t kApiContract[] = L"Windows.Foundation.UniversalApiContract";
const UINT16 kRequiredApiContractVersion = 8;
constexpr wchar_t kApiContract[] = L"Windows.Foundation.UniversalApiContract";
constexpr UINT16 kRequiredApiContractVersion = 8;
enum class WgcCapturerResult {
kSuccess = 0,
@ -45,7 +48,8 @@ enum class WgcCapturerResult {
kSessionStartFailure = 4,
kGetFrameFailure = 5,
kFrameDropped = 6,
kMaxValue = kFrameDropped
kCreateDispatcherQueueFailure = 7,
kMaxValue = kCreateDispatcherQueueFailure
};
void RecordWgcCapturerResult(WgcCapturerResult error) {
@ -57,20 +61,34 @@ void RecordWgcCapturerResult(WgcCapturerResult error) {
} // namespace
bool IsWgcSupported(CaptureType capture_type) {
if (capture_type == CaptureType::kScreen) {
// A bug in the WGC API `CreateForMonitor` was fixed in 20H1.
if (rtc::rtc_win::GetVersion() < rtc::rtc_win::Version::VERSION_WIN10_20H1)
if (!HasActiveDisplay()) {
// There is a bug in `CreateForMonitor` that causes a crash if there are no
// active displays. The crash was fixed in Win11, but we are still unable
// to capture screens without an active display.
if (capture_type == CaptureType::kScreen)
return false;
// There is another bug in `CreateForMonitor` that causes a crash if there
// are no active displays.
if (!HasActiveDisplay())
// There is a bug in the DWM (Desktop Window Manager) that prevents it from
// providing image data if there are no displays attached. This was fixed in
// Windows 11.
if (rtc::rtc_win::GetVersion() < rtc::rtc_win::Version::VERSION_WIN11)
return false;
}
// A bug in the WGC API `CreateForMonitor` prevents capturing the entire
// virtual screen (all monitors simultaneously), this was fixed in 20H1. Since
// we can't assert that we won't be asked to capture the entire virtual
// screen, we report unsupported so we can fallback to another capturer.
if (capture_type == CaptureType::kScreen &&
rtc::rtc_win::GetVersion() < rtc::rtc_win::Version::VERSION_WIN10_20H1) {
return false;
}
if (!ResolveCoreWinRTDelayload())
return false;
// We need to check if the WGC APIs are presesnt on the system. Certain SKUs
// of Windows ship without these APIs.
ComPtr<ABI::Windows::Foundation::Metadata::IApiInformationStatics>
api_info_statics;
HRESULT hr = GetActivationFactory<
@ -104,6 +122,7 @@ bool IsWgcSupported(CaptureType capture_type) {
if (FAILED(hr) || !is_type_present)
return false;
// If the APIs are present, we need to check that they are supported.
ComPtr<WGC::IGraphicsCaptureSessionStatics> capture_session_statics;
hr = GetActivationFactory<
WGC::IGraphicsCaptureSessionStatics,
@ -126,8 +145,21 @@ WgcCapturerWin::WgcCapturerWin(
bool allow_delayed_capturable_check)
: source_factory_(std::move(source_factory)),
source_enumerator_(std::move(source_enumerator)),
allow_delayed_capturable_check_(allow_delayed_capturable_check) {}
WgcCapturerWin::~WgcCapturerWin() = default;
allow_delayed_capturable_check_(allow_delayed_capturable_check) {
if (!core_messaging_library_)
core_messaging_library_ = LoadLibraryW(kCoreMessagingDll);
if (core_messaging_library_) {
create_dispatcher_queue_controller_func_ =
reinterpret_cast<CreateDispatcherQueueControllerFunc>(GetProcAddress(
core_messaging_library_, "CreateDispatcherQueueController"));
}
}
WgcCapturerWin::~WgcCapturerWin() {
if (core_messaging_library_)
FreeLibrary(core_messaging_library_);
}
// static
std::unique_ptr<DesktopCapturer> WgcCapturerWin::CreateRawWindowCapturer(
@ -224,9 +256,32 @@ void WgcCapturerWin::CaptureFrame() {
return;
}
HRESULT hr;
if (!dispatcher_queue_created_) {
// Set the apartment type to NONE because this thread should already be COM
// initialized.
DispatcherQueueOptions options{
sizeof(DispatcherQueueOptions),
DISPATCHERQUEUE_THREAD_TYPE::DQTYPE_THREAD_CURRENT,
DISPATCHERQUEUE_THREAD_APARTMENTTYPE::DQTAT_COM_NONE};
ComPtr<ABI::Windows::System::IDispatcherQueueController> queue_controller;
hr = create_dispatcher_queue_controller_func_(options, &queue_controller);
// If there is already a DispatcherQueue on this thread, that is fine. Its
// lifetime is tied to the thread's, and as long as the thread has one, even
// if we didn't create it, the capture session's events will be delivered on
// this thread.
if (FAILED(hr) && hr != RPC_E_WRONG_THREAD) {
RecordWgcCapturerResult(WgcCapturerResult::kCreateDispatcherQueueFailure);
callback_->OnCaptureResult(DesktopCapturer::Result::ERROR_PERMANENT,
/*frame=*/nullptr);
} else {
dispatcher_queue_created_ = true;
}
}
int64_t capture_start_time_nanos = rtc::TimeNanos();
HRESULT hr;
WgcCaptureSession* capture_session = nullptr;
std::map<SourceId, WgcCaptureSession>::iterator session_iter =
ongoing_captures_.find(capture_source_->GetSourceId());

View File

@ -11,6 +11,7 @@
#ifndef MODULES_DESKTOP_CAPTURE_WIN_WGC_CAPTURER_WIN_H_
#define MODULES_DESKTOP_CAPTURE_WIN_WGC_CAPTURER_WIN_H_
#include <DispatcherQueue.h>
#include <d3d11.h>
#include <wrl/client.h>
@ -109,6 +110,23 @@ class WgcCapturerWin : public DesktopCapturer {
bool IsSourceBeingCaptured(SourceId id);
private:
typedef HRESULT(WINAPI* CreateDispatcherQueueControllerFunc)(
DispatcherQueueOptions,
ABI::Windows::System::IDispatcherQueueController**);
// We need to either create or ensure that someone else created a
// `DispatcherQueue` on the current thread so that events will be delivered
// on the current thread rather than an arbitrary thread. A
// `DispatcherQueue`'s lifetime is tied to the thread's, and we don't post
// any work to it, so we don't need to hold a reference.
bool dispatcher_queue_created_ = false;
// Statically linking to CoreMessaging.lib is disallowed in Chromium, so we
// load it at runtime.
HMODULE core_messaging_library_ = NULL;
CreateDispatcherQueueControllerFunc create_dispatcher_queue_controller_func_ =
nullptr;
// Factory to create a WgcCaptureSource for us whenever SelectSource is
// called. Initialized at construction with a source-specific implementation.
std::unique_ptr<WgcCaptureSourceFactory> source_factory_;

View File

@ -18,12 +18,14 @@
#include "modules/desktop_capture/desktop_capture_types.h"
#include "modules/desktop_capture/desktop_capturer.h"
#include "modules/desktop_capture/win/test_support/test_window.h"
#include "modules/desktop_capture/win/wgc_capture_session.h"
#include "modules/desktop_capture/win/window_capture_utils.h"
#include "rtc_base/checks.h"
#include "rtc_base/logging.h"
#include "rtc_base/thread.h"
#include "rtc_base/time_utils.h"
#include "rtc_base/win/scoped_com_initializer.h"
#include "rtc_base/win/windows_version.h"
#include "system_wrappers/include/metrics.h"
#include "system_wrappers/include/sleep.h"
#include "test/gtest.h"
@ -31,40 +33,54 @@
namespace webrtc {
namespace {
const char kWindowThreadName[] = "wgc_capturer_test_window_thread";
const WCHAR kWindowTitle[] = L"WGC Capturer Test Window";
constexpr char kWindowThreadName[] = "wgc_capturer_test_window_thread";
constexpr WCHAR kWindowTitle[] = L"WGC Capturer Test Window";
const char kCapturerImplHistogram[] =
constexpr char kCapturerImplHistogram[] =
"WebRTC.DesktopCapture.Win.DesktopCapturerImpl";
const char kCapturerResultHistogram[] =
constexpr char kCapturerResultHistogram[] =
"WebRTC.DesktopCapture.Win.WgcCapturerResult";
const int kSuccess = 0;
const int kSessionStartFailure = 4;
constexpr int kSuccess = 0;
constexpr int kSessionStartFailure = 4;
const char kCaptureSessionResultHistogram[] =
constexpr char kCaptureSessionResultHistogram[] =
"WebRTC.DesktopCapture.Win.WgcCaptureSessionStartResult";
const int kSourceClosed = 1;
constexpr int kSourceClosed = 1;
const char kCaptureTimeHistogram[] =
constexpr char kCaptureTimeHistogram[] =
"WebRTC.DesktopCapture.Win.WgcCapturerFrameTime";
const int kSmallWindowWidth = 200;
const int kSmallWindowHeight = 100;
const int kMediumWindowWidth = 300;
const int kMediumWindowHeight = 200;
const int kLargeWindowWidth = 400;
const int kLargeWindowHeight = 500;
// The capturer keeps `kNumBuffers` in its frame pool, so we need to request
// that many frames to clear those out. The next frame will have the new size
// (if the size has changed) so we will resize the frame pool at this point.
// Then, we need to clear any frames that may have delivered to the frame pool
// before the resize. Finally, the next frame will be guaranteed to be the new
// size.
constexpr int kNumCapturesToFlushBuffers =
WgcCaptureSession::kNumBuffers * 2 + 1;
constexpr int kSmallWindowWidth = 200;
constexpr int kSmallWindowHeight = 100;
constexpr int kMediumWindowWidth = 300;
constexpr int kMediumWindowHeight = 200;
constexpr int kLargeWindowWidth = 400;
constexpr int kLargeWindowHeight = 500;
// The size of the image we capture is slightly smaller than the actual size of
// the window.
const int kWindowWidthSubtrahend = 14;
const int kWindowHeightSubtrahend = 7;
constexpr int kWindowWidthSubtrahend = 14;
constexpr int kWindowHeightSubtrahend = 7;
// Custom message constants so we can direct our thread to close windows
// and quit running.
const UINT kDestroyWindow = WM_APP;
const UINT kQuitRunning = WM_APP + 1;
// Custom message constants so we can direct our thread to close windows and
// quit running.
constexpr UINT kDestroyWindow = WM_APP;
constexpr UINT kQuitRunning = WM_APP + 1;
// When testing changes to real windows, sometimes the effects (close or resize)
// don't happen immediately, we want to keep trying until we see the effect but
// only for a reasonable amount of time.
constexpr int kMaxTries = 50;
} // namespace
@ -185,20 +201,26 @@ class WgcCapturerWinTest : public ::testing::TestWithParam<CaptureType>,
return sources[0].id;
}
void DoCapture() {
// Sometimes the first few frames are empty becaues the capture engine is
// still starting up. We also may drop a few frames when the window is
// resized or un-minimized.
do {
void DoCapture(int num_captures = 1) {
// Capture the requested number of frames. We expect the first capture to
// always succeed. If we're asked for multiple frames, we do expect to see a
// a couple dropped frames due to resizing the window.
const int max_tries = num_captures == 1 ? 1 : kMaxTries;
int success_count = 0;
for (int i = 0; success_count < num_captures && i < max_tries; i++) {
capturer_->CaptureFrame();
} while (result_ == DesktopCapturer::Result::ERROR_TEMPORARY);
if (result_ == DesktopCapturer::Result::ERROR_PERMANENT)
break;
if (result_ == DesktopCapturer::Result::SUCCESS)
success_count++;
}
total_successful_captures_ += success_count;
EXPECT_EQ(success_count, num_captures);
EXPECT_EQ(result_, DesktopCapturer::Result::SUCCESS);
EXPECT_TRUE(frame_);
EXPECT_GT(metrics::NumEvents(kCapturerResultHistogram, kSuccess),
successful_captures_);
++successful_captures_;
EXPECT_GE(metrics::NumEvents(kCapturerResultHistogram, kSuccess),
total_successful_captures_);
}
void ValidateFrame(int expected_width, int expected_height) {
@ -206,8 +228,7 @@ class WgcCapturerWinTest : public ::testing::TestWithParam<CaptureType>,
EXPECT_EQ(frame_->size().height(),
expected_height - kWindowHeightSubtrahend);
// Verify the buffer contains as much data as it should, and that the right
// colors are found.
// Verify the buffer contains as much data as it should.
int data_length = frame_->stride() * frame_->size().height();
// The first and last pixel should have the same color because they will be
@ -219,7 +240,7 @@ class WgcCapturerWinTest : public ::testing::TestWithParam<CaptureType>,
EXPECT_EQ(first_pixel, last_pixel);
// Let's also check a pixel from the middle of the content area, which the
// TestWindow will paint a consistent color for us to verify.
// test window will paint a consistent color for us to verify.
uint8_t* middle_pixel = frame_->data() + (data_length / 2);
int sub_pixel_offset = DesktopFrame::kBytesPerPixel / 4;
@ -251,7 +272,7 @@ class WgcCapturerWinTest : public ::testing::TestWithParam<CaptureType>,
intptr_t source_id_;
bool window_open_ = false;
DesktopCapturer::Result result_;
int successful_captures_ = 0;
int total_successful_captures_ = 0;
std::unique_ptr<DesktopFrame> frame_;
std::unique_ptr<DesktopCapturer> capturer_;
};
@ -310,13 +331,12 @@ TEST_P(WgcCapturerWinTest, CaptureTime) {
capturer_->Start(this);
int64_t start_time;
do {
start_time = rtc::TimeNanos();
capturer_->CaptureFrame();
} while (result_ == DesktopCapturer::Result::ERROR_TEMPORARY);
start_time = rtc::TimeNanos();
capturer_->CaptureFrame();
int capture_time_ms =
(rtc::TimeNanos() - start_time) / rtc::kNumNanosecsPerMillisec;
EXPECT_EQ(result_, DesktopCapturer::Result::SUCCESS);
EXPECT_TRUE(frame_);
// The test may measure the time slightly differently than the capturer. So we
@ -332,6 +352,8 @@ INSTANTIATE_TEST_SUITE_P(SourceAgnostic,
CaptureType::kScreen));
TEST(WgcCapturerNoMonitorTest, NoMonitors) {
ScopedCOMInitializer com_initializer(ScopedCOMInitializer::kMTA);
EXPECT_TRUE(com_initializer.Succeeded());
if (HasActiveDisplay()) {
RTC_LOG(LS_INFO) << "Skip WgcCapturerWinTest designed specifically for "
"systems with no monitors";
@ -341,6 +363,13 @@ TEST(WgcCapturerNoMonitorTest, NoMonitors) {
// A bug in `CreateForMonitor` prevents screen capture when no displays are
// attached.
EXPECT_FALSE(IsWgcSupported(CaptureType::kScreen));
// A bug in the DWM (Desktop Window Manager) prevents it from providing image
// data if there are no displays attached. This was fixed in Windows 11.
if (rtc::rtc_win::GetVersion() < rtc::rtc_win::Version::VERSION_WIN11)
EXPECT_FALSE(IsWgcSupported(CaptureType::kWindow));
else
EXPECT_TRUE(IsWgcSupported(CaptureType::kWindow));
}
class WgcCapturerMonitorTest : public WgcCapturerWinTest {
@ -452,15 +481,11 @@ TEST_F(WgcCapturerWindowTest, IncreaseWindowSizeMidCapture) {
ValidateFrame(kSmallWindowWidth, kSmallWindowHeight);
ResizeTestWindow(window_info_.hwnd, kSmallWindowWidth, kMediumWindowHeight);
DoCapture();
// We don't expect to see the new size until the next capture, as the frame
// pool hadn't had a chance to resize yet to fit the new, larger image.
DoCapture();
DoCapture(kNumCapturesToFlushBuffers);
ValidateFrame(kSmallWindowWidth, kMediumWindowHeight);
ResizeTestWindow(window_info_.hwnd, kLargeWindowWidth, kMediumWindowHeight);
DoCapture();
DoCapture();
DoCapture(kNumCapturesToFlushBuffers);
ValidateFrame(kLargeWindowWidth, kMediumWindowHeight);
}
@ -473,13 +498,11 @@ TEST_F(WgcCapturerWindowTest, ReduceWindowSizeMidCapture) {
ValidateFrame(kLargeWindowWidth, kLargeWindowHeight);
ResizeTestWindow(window_info_.hwnd, kLargeWindowWidth, kMediumWindowHeight);
// We expect to see the new size immediately because the image data has shrunk
// and will fit in the existing buffer.
DoCapture();
DoCapture(kNumCapturesToFlushBuffers);
ValidateFrame(kLargeWindowWidth, kMediumWindowHeight);
ResizeTestWindow(window_info_.hwnd, kSmallWindowWidth, kMediumWindowHeight);
DoCapture();
DoCapture(kNumCapturesToFlushBuffers);
ValidateFrame(kSmallWindowWidth, kMediumWindowHeight);
}
@ -491,7 +514,7 @@ TEST_F(WgcCapturerWindowTest, MinimizeWindowMidCapture) {
// Minmize the window and capture should continue but return temporary errors.
MinimizeTestWindow(window_info_.hwnd);
for (int i = 0; i < 10; ++i) {
for (int i = 0; i < 5; ++i) {
capturer_->CaptureFrame();
EXPECT_EQ(result_, DesktopCapturer::Result::ERROR_TEMPORARY);
}
@ -520,19 +543,24 @@ TEST_F(WgcCapturerWindowTest, CloseWindowMidCapture) {
// stops.
auto* wgc_capturer = static_cast<WgcCapturerWin*>(capturer_.get());
MSG msg;
while (wgc_capturer->IsSourceBeingCaptured(source_id_)) {
for (int i = 0;
wgc_capturer->IsSourceBeingCaptured(source_id_) && i < kMaxTries; ++i) {
// Unlike GetMessage, PeekMessage will not hang if there are no messages in
// the queue.
PeekMessage(&msg, 0, 0, 0, PM_REMOVE);
SleepMs(1);
}
// Occasionally, one last frame will have made it into the frame pool before
// the window closed. The first call will consume it, and in that case we need
// to make one more call to CaptureFrame.
capturer_->CaptureFrame();
if (result_ == DesktopCapturer::Result::SUCCESS)
EXPECT_FALSE(wgc_capturer->IsSourceBeingCaptured(source_id_));
// The frame pool can buffer `kNumBuffers` frames. We must consume these
// and then make one more call to CaptureFrame before we expect to see the
// failure.
int num_tries = 0;
do {
capturer_->CaptureFrame();
} while (result_ == DesktopCapturer::Result::SUCCESS &&
++num_tries <= WgcCaptureSession::kNumBuffers);
EXPECT_GE(metrics::NumEvents(kCapturerResultHistogram, kSessionStartFailure),
1);