Title: [260561] trunk
Revision
260561
Author
[email protected]
Date
2020-04-23 01:59:31 -0700 (Thu, 23 Apr 2020)

Log Message

getDisplayMedia is not respecting aspect ratio with max constraints
https://bugs.webkit.org/show_bug.cgi?id=210858

Reviewed by Eric Carlson.

Source/WebCore:

Add computation of exact frame size to respect aspect ratio in DisplayCaptureSourceCocoa::updateFrameSize.
Refactor code to have one source class DisplayCaptureSourceCocoa and specific capturer for screen and window.
This simplifies code and allows reusing DisplayCaptureSourceCocoa with a mock capturer.
Update mock code to use DisplayCaptureSourceCocoa.

Tests: fast/mediastream/getDisplayMedia-max-constraints.html
       fast/mediastream/getDisplayMedia-max-constraints1.html
       fast/mediastream/getDisplayMedia-max-constraints2.html
       fast/mediastream/getDisplayMedia-max-constraints3.html

* SourcesCocoa.txt:
* WebCore.xcodeproj/project.pbxproj:
* platform/mediastream/mac/DisplayCaptureManagerCocoa.cpp:
(WebCore::DisplayCaptureManagerCocoa::updateDisplayCaptureDevices):
(WebCore::DisplayCaptureManagerCocoa::updateWindowCaptureDevices):
(WebCore::DisplayCaptureManagerCocoa::screenCaptureDeviceWithPersistentID):
(WebCore::DisplayCaptureManagerCocoa::windowCaptureDeviceWithPersistentID):
* platform/mediastream/mac/DisplayCaptureSourceCocoa.cpp:
(WebCore::DisplayCaptureSourceCocoa::create):
(WebCore::DisplayCaptureSourceCocoa::DisplayCaptureSourceCocoa):
(WebCore::DisplayCaptureSourceCocoa::~DisplayCaptureSourceCocoa):
(WebCore::DisplayCaptureSourceCocoa::capabilities):
(WebCore::DisplayCaptureSourceCocoa::settings):
(WebCore::DisplayCaptureSourceCocoa::startProducingData):
(WebCore::DisplayCaptureSourceCocoa::stopProducingData):
(WebCore::DisplayCaptureSourceCocoa::updateFrameSize):
(WebCore::DisplayCaptureSourceCocoa::emitFrame):
(WebCore::DisplayCaptureSourceCocoa::Capturer::setLogger):
(WebCore::DisplayCaptureSourceCocoa::Capturer::logChannel const):
* platform/mediastream/mac/DisplayCaptureSourceCocoa.h:
* platform/mediastream/mac/MockRealtimeVideoSourceMac.h:
* platform/mediastream/mac/MockRealtimeVideoSourceMac.mm:
(WebCore::MockRealtimeVideoSourceMac::createForMockDisplayCapturer):
* platform/mediastream/mac/RealtimeMediaSourceCenterMac.cpp:
* platform/mediastream/mac/ScreenDisplayCapturerMac.h: Added.
* platform/mediastream/mac/ScreenDisplayCapturerMac.mm: Added.
(WebCore::ScreenDisplayCapturerMac::create):
(WebCore::ScreenDisplayCapturerMac::ScreenDisplayCapturerMac):
(WebCore::ScreenDisplayCapturerMac::~ScreenDisplayCapturerMac):
(WebCore::ScreenDisplayCapturerMac::createDisplayStream):
(WebCore::ScreenDisplayCapturerMac::start):
(WebCore::ScreenDisplayCapturerMac::stop):
(WebCore::ScreenDisplayCapturerMac::generateFrame):
(WebCore::ScreenDisplayCapturerMac::startDisplayStream):
(WebCore::ScreenDisplayCapturerMac::commitConfiguration):
(WebCore::ScreenDisplayCapturerMac::displayWasReconfigured):
(WebCore::ScreenDisplayCapturerMac::displayReconfigurationCallBack):
(WebCore::ScreenDisplayCapturerMac::newFrame):
(WebCore::ScreenDisplayCapturerMac::screenCaptureDeviceWithPersistentID):
(WebCore::ScreenDisplayCapturerMac::screenCaptureDevices):
* platform/mediastream/mac/WindowDisplayCapturerMac.h: Added.
* platform/mediastream/mac/WindowDisplayCapturerMac.mm: ddedAdded.
(WebCore::WindowDisplayCapturerMac::create):
(WebCore::WindowDisplayCapturerMac::WindowDisplayCapturerMac):
(WebCore::WindowDisplayCapturerMac::windowImage):
(WebCore::WindowDisplayCapturerMac::generateFrame):
(WebCore::WindowDisplayCapturerMac::windowCaptureDeviceWithPersistentID):
(WebCore::WindowDisplayCapturerMac::windowCaptureDevices):
* platform/mock/MockRealtimeMediaSourceCenter.cpp:
(WebCore::MockDisplayCapturer::MockDisplayCapturer):
(WebCore::MockDisplayCapturer::start):
(WebCore::MockDisplayCapturer::generateFrame):
* platform/mock/MockRealtimeVideoSource.h:
(isType):

LayoutTests:

* fast/mediastream/getDisplayMedia-max-constraints-expected.txt: Added.
* fast/mediastream/getDisplayMedia-max-constraints.html: Added.
* fast/mediastream/getDisplayMedia-max-constraints1-expected.txt: Added.
* fast/mediastream/getDisplayMedia-max-constraints1.html: Added.
* fast/mediastream/getDisplayMedia-max-constraints2-expected.txt: Added.
* fast/mediastream/getDisplayMedia-max-constraints2.html: Added.
* fast/mediastream/getDisplayMedia-max-constraints3-expected.txt: Added.
* fast/mediastream/getDisplayMedia-max-constraints3.html: Added.
* fast/mediastream/resources/getDisplayMedia-utils.js: Added.
(async callGetDisplayMedia):
(async waitForHeight):
(async waitForWidth):
* platform/ios/TestExpectations:
Skip new tests as getDisplayMedia is not supported on iOS.

Modified Paths

Added Paths

Removed Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (260560 => 260561)


--- trunk/LayoutTests/ChangeLog	2020-04-23 08:47:37 UTC (rev 260560)
+++ trunk/LayoutTests/ChangeLog	2020-04-23 08:59:31 UTC (rev 260561)
@@ -1,3 +1,25 @@
+2020-04-23  Youenn Fablet  <[email protected]>
+
+        getDisplayMedia is not respecting aspect ratio with max constraints
+        https://bugs.webkit.org/show_bug.cgi?id=210858
+
+        Reviewed by Eric Carlson.
+
+        * fast/mediastream/getDisplayMedia-max-constraints-expected.txt: Added.
+        * fast/mediastream/getDisplayMedia-max-constraints.html: Added.
+        * fast/mediastream/getDisplayMedia-max-constraints1-expected.txt: Added.
+        * fast/mediastream/getDisplayMedia-max-constraints1.html: Added.
+        * fast/mediastream/getDisplayMedia-max-constraints2-expected.txt: Added.
+        * fast/mediastream/getDisplayMedia-max-constraints2.html: Added.
+        * fast/mediastream/getDisplayMedia-max-constraints3-expected.txt: Added.
+        * fast/mediastream/getDisplayMedia-max-constraints3.html: Added.
+        * fast/mediastream/resources/getDisplayMedia-utils.js: Added.
+        (async callGetDisplayMedia):
+        (async waitForHeight):
+        (async waitForWidth):
+        * platform/ios/TestExpectations:
+        Skip new tests as getDisplayMedia is not supported on iOS.
+
 2020-04-23  Diego Pino Garcia  <[email protected]>
 
         [GTK][WPE] Gardening, update baselines and test expectations

Modified: trunk/LayoutTests/fast/mediastream/constraint-intrinsic-size.html (260560 => 260561)


--- trunk/LayoutTests/fast/mediastream/constraint-intrinsic-size.html	2020-04-23 08:47:37 UTC (rev 260560)
+++ trunk/LayoutTests/fast/mediastream/constraint-intrinsic-size.html	2020-04-23 08:59:31 UTC (rev 260561)
@@ -5,22 +5,11 @@
         <title>video track width and height should be set correctly when only one constraint is passed to getDisplayMedia</title>
         <script src=""
         <script src=""
+        <script src=""
     </head>
     <body>
 
         <script>
-            if (window.internals)
-                window.internals.settings.setScreenCaptureEnabled(true);
-
-            function callGetDisplayMedia(options)
-            {
-                let promise;
-                window.internals.withUserGesture(() => {
-                    promise = navigator.mediaDevices.getDisplayMedia(options);
-                });
-                return promise;
-            }
-
             let defaultWidth;
             let defaultHeight;
             promise_test(async () => {

Added: trunk/LayoutTests/fast/mediastream/getDisplayMedia-max-constraints-expected.txt (0 => 260561)


--- trunk/LayoutTests/fast/mediastream/getDisplayMedia-max-constraints-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/fast/mediastream/getDisplayMedia-max-constraints-expected.txt	2020-04-23 08:59:31 UTC (rev 260561)
@@ -0,0 +1,6 @@
+
+PASS setup 
+PASS Maximize the width if max height is too big 
+PASS Maximize the height if max width is too big 
+PASS No effect of the max values if they are too big 
+

Added: trunk/LayoutTests/fast/mediastream/getDisplayMedia-max-constraints.html (0 => 260561)


--- trunk/LayoutTests/fast/mediastream/getDisplayMedia-max-constraints.html	                        (rev 0)
+++ trunk/LayoutTests/fast/mediastream/getDisplayMedia-max-constraints.html	2020-04-23 08:59:31 UTC (rev 260561)
@@ -0,0 +1,93 @@
+<!doctype html>
+<html>
+    <head>
+        <meta charset="utf-8">
+        <title>getDisplayMedia track support of max constraints</title>
+        <script src=""
+        <script src=""
+    </head>
+    <body>
+
+        <script>
+            if (window.internals)
+                window.internals.settings.setScreenCaptureEnabled(true);
+
+            async function callGetDisplayMedia(options)
+            {
+                let promise;
+                window.internals.withUserGesture(() => {
+                    promise = navigator.mediaDevices.getDisplayMedia(options);
+                });
+                const stream = await promise; 
+                const track = stream.getVideoTracks()[0];
+
+                // getSettings is not computing the correct parameters right away. We should probably fix this.
+                while (true) {
+                    const settings = track.getSettings();
+                    if (settings.width && settings.height)
+                        break;
+                    await new Promise(resolve => setTimeout(resolve, 50));
+                }
+                return stream;
+            }
+
+            // getSettings is not computing the correct parameters right away. We should probably fix this.
+            async function waitForHeight(track, value) {
+                while (true) {
+                    const settings = track.getSettings();
+                    if (settings.height === value)
+                        break;
+                    await new Promise(resolve => setTimeout(resolve, 50));
+                }
+            }
+
+            // getSettings is not computing the correct parameters right away. We should probably fix this.
+            async function waitForWidth(track, value) {
+                while (true) {
+                    const settings = track.getSettings();
+                    if (settings.width === value)
+                        break;
+                    await new Promise(resolve => setTimeout(resolve, 50));
+                }
+            }
+
+            let defaultWidth;
+            let defaultHeight;
+            promise_test(async () => {
+                stream = await callGetDisplayMedia({ video: true });
+                let settings = stream.getVideoTracks()[0].getSettings();
+                defaultWidth = settings.width;
+                defaultHeight = settings.height;
+            }, "setup");
+            
+            promise_test(async (test) => {
+                const stream = await callGetDisplayMedia({ video: { height: { max: 500 }, width : { max : 500 } } });
+
+                const expectedHeight =Math.floor(500 * (defaultHeight / defaultWidth)) 
+                await waitForHeight(stream.getVideoTracks()[0], expectedHeight);
+
+                const settings = stream.getVideoTracks()[0].getSettings()
+                assert_equals(settings.width, 500);
+            }, "Maximize the width if max height is too big");
+
+            promise_test(async (test) => {
+                const stream = await callGetDisplayMedia({ video: { height: { max: 100 }, width : { max : 500 } } });
+
+                const expectedWidth = Math.floor(100 * (defaultWidth / defaultHeight)) 
+                await waitForWidth(stream.getVideoTracks()[0], expectedWidth);
+
+                const settings = stream.getVideoTracks()[0].getSettings()
+                assert_equals(settings.height, 100);
+            }, "Maximize the height if max width is too big");
+
+            promise_test(async (test) => {
+                const stream = await callGetDisplayMedia({ video: { height: { max: 500000 }, width : { max : 500000 } } });
+
+                await waitForHeight(stream.getVideoTracks()[0], defaultHeight);
+
+                const settings = stream.getVideoTracks()[0].getSettings()
+                assert_equals(settings.width, defaultWidth);
+            }, "No effect of the max values if they are too big");
+        </script>
+    </body>
+</html>

Added: trunk/LayoutTests/fast/mediastream/getDisplayMedia-max-constraints1-expected.txt (0 => 260561)


--- trunk/LayoutTests/fast/mediastream/getDisplayMedia-max-constraints1-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/fast/mediastream/getDisplayMedia-max-constraints1-expected.txt	2020-04-23 08:59:31 UTC (rev 260561)
@@ -0,0 +1,4 @@
+
+PASS setup 
+PASS Maximize the width if max height is too big 
+

Added: trunk/LayoutTests/fast/mediastream/getDisplayMedia-max-constraints1.html (0 => 260561)


--- trunk/LayoutTests/fast/mediastream/getDisplayMedia-max-constraints1.html	                        (rev 0)
+++ trunk/LayoutTests/fast/mediastream/getDisplayMedia-max-constraints1.html	2020-04-23 08:59:31 UTC (rev 260561)
@@ -0,0 +1,32 @@
+<!doctype html>
+<html>
+    <head>
+        <meta charset="utf-8">
+        <title>getDisplayMedia track support of max constraints</title>
+        <script src=""
+        <script src=""
+        <script src=""
+    </head>
+    <body>
+        <script>
+let defaultWidth;
+let defaultHeight;
+promise_test(async () => {
+    stream = await callGetDisplayMedia({ video: true });
+    let settings = stream.getVideoTracks()[0].getSettings();
+    defaultWidth = settings.width;
+    defaultHeight = settings.height;
+}, "setup");
+
+promise_test(async (test) => {
+    const stream = await callGetDisplayMedia({ video: { height: { max: 500 }, width : { max : 500 } } });
+
+    const expectedHeight =Math.floor(500 * (defaultHeight / defaultWidth)) 
+    await waitForHeight(stream.getVideoTracks()[0], expectedHeight);
+
+    const settings = stream.getVideoTracks()[0].getSettings()
+    assert_equals(settings.width, 500);
+}, "Maximize the width if max height is too big");
+        </script>
+    </body>
+</html>

Added: trunk/LayoutTests/fast/mediastream/getDisplayMedia-max-constraints2-expected.txt (0 => 260561)


--- trunk/LayoutTests/fast/mediastream/getDisplayMedia-max-constraints2-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/fast/mediastream/getDisplayMedia-max-constraints2-expected.txt	2020-04-23 08:59:31 UTC (rev 260561)
@@ -0,0 +1,4 @@
+
+PASS setup 
+PASS Maximize the height if max width is too big 
+

Added: trunk/LayoutTests/fast/mediastream/getDisplayMedia-max-constraints2.html (0 => 260561)


--- trunk/LayoutTests/fast/mediastream/getDisplayMedia-max-constraints2.html	                        (rev 0)
+++ trunk/LayoutTests/fast/mediastream/getDisplayMedia-max-constraints2.html	2020-04-23 08:59:31 UTC (rev 260561)
@@ -0,0 +1,32 @@
+<!doctype html>
+<html>
+    <head>
+        <meta charset="utf-8">
+        <title>getDisplayMedia track support of max constraints</title>
+        <script src=""
+        <script src=""
+        <script src=""
+    </head>
+    <body>
+        <script>
+let defaultWidth;
+let defaultHeight;
+promise_test(async () => {
+    stream = await callGetDisplayMedia({ video: true });
+    let settings = stream.getVideoTracks()[0].getSettings();
+    defaultWidth = settings.width;
+    defaultHeight = settings.height;
+}, "setup");
+
+promise_test(async (test) => {
+    const stream = await callGetDisplayMedia({ video: { height: { max: 100 }, width : { max : 500 } } });
+
+    const expectedWidth = Math.floor(100 * (defaultWidth / defaultHeight)) 
+    await waitForWidth(stream.getVideoTracks()[0], expectedWidth);
+
+    const settings = stream.getVideoTracks()[0].getSettings()
+    assert_equals(settings.height, 100);
+}, "Maximize the height if max width is too big");
+        </script>
+    </body>
+</html>

Added: trunk/LayoutTests/fast/mediastream/getDisplayMedia-max-constraints3-expected.txt (0 => 260561)


--- trunk/LayoutTests/fast/mediastream/getDisplayMedia-max-constraints3-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/fast/mediastream/getDisplayMedia-max-constraints3-expected.txt	2020-04-23 08:59:31 UTC (rev 260561)
@@ -0,0 +1,4 @@
+
+PASS setup 
+PASS No effect of the max values if they are too big 
+

Added: trunk/LayoutTests/fast/mediastream/getDisplayMedia-max-constraints3.html (0 => 260561)


--- trunk/LayoutTests/fast/mediastream/getDisplayMedia-max-constraints3.html	                        (rev 0)
+++ trunk/LayoutTests/fast/mediastream/getDisplayMedia-max-constraints3.html	2020-04-23 08:59:31 UTC (rev 260561)
@@ -0,0 +1,31 @@
+<!doctype html>
+<html>
+    <head>
+        <meta charset="utf-8">
+        <title>getDisplayMedia track support of max constraints</title>
+        <script src=""
+        <script src=""
+        <script src=""
+    </head>
+    <body>
+        <script>
+let defaultWidth;
+let defaultHeight;
+promise_test(async () => {
+    stream = await callGetDisplayMedia({ video: true });
+    let settings = stream.getVideoTracks()[0].getSettings();
+    defaultWidth = settings.width;
+    defaultHeight = settings.height;
+}, "setup");
+
+promise_test(async (test) => {
+    const stream = await callGetDisplayMedia({ video: { height: { max: 500000 }, width : { max : 500000 } } });
+
+    await waitForHeight(stream.getVideoTracks()[0], defaultHeight);
+
+    const settings = stream.getVideoTracks()[0].getSettings()
+    assert_equals(settings.width, defaultWidth);
+}, "No effect of the max values if they are too big");
+        </script>
+    </body>
+</html>

Added: trunk/LayoutTests/fast/mediastream/resources/getDisplayMedia-utils.js (0 => 260561)


--- trunk/LayoutTests/fast/mediastream/resources/getDisplayMedia-utils.js	                        (rev 0)
+++ trunk/LayoutTests/fast/mediastream/resources/getDisplayMedia-utils.js	2020-04-23 08:59:31 UTC (rev 260561)
@@ -0,0 +1,39 @@
+if (window.internals)
+    window.internals.settings.setScreenCaptureEnabled(true);
+
+async function callGetDisplayMedia(options)
+{
+    let promise;
+    window.internals.withUserGesture(() => {
+        promise = navigator.mediaDevices.getDisplayMedia(options);
+    });
+    const stream = await promise; 
+    const track = stream.getVideoTracks()[0];
+
+    // getSettings is not computing the correct parameters right away. We should probably fix this.
+    while (true) {
+        const settings = track.getSettings();
+        if (settings.width && settings.height)
+            break;
+        await new Promise(resolve => setTimeout(resolve, 50));
+    }
+    return stream;
+}
+
+async function waitForHeight(track, value) {
+    while (true) {
+        const settings = track.getSettings();
+        if (settings.height === value)
+            break;
+        await new Promise(resolve => setTimeout(resolve, 50));
+    }
+}
+
+async function waitForWidth(track, value) {
+    while (true) {
+        const settings = track.getSettings();
+        if (settings.width === value)
+            break;
+        await new Promise(resolve => setTimeout(resolve, 50));
+    }
+}

Modified: trunk/LayoutTests/platform/ios/TestExpectations (260560 => 260561)


--- trunk/LayoutTests/platform/ios/TestExpectations	2020-04-23 08:47:37 UTC (rev 260560)
+++ trunk/LayoutTests/platform/ios/TestExpectations	2020-04-23 08:59:31 UTC (rev 260561)
@@ -2895,6 +2895,9 @@
 
 # screen capture not supported on iOS.
 fast/mediastream/screencapture-user-gesture.html [ Skip ]
+fast/mediastream/getDisplayMedia-max-constraints1.html [ Skip ]
+fast/mediastream/getDisplayMedia-max-constraints2.html [ Skip ]
+fast/mediastream/getDisplayMedia-max-constraints3.html [ Skip ]
 
 webkit.org/b/177401 webrtc/captureCanvas-webrtc.html [ Pass Timeout Failure ]
 

Modified: trunk/Source/WebCore/ChangeLog (260560 => 260561)


--- trunk/Source/WebCore/ChangeLog	2020-04-23 08:47:37 UTC (rev 260560)
+++ trunk/Source/WebCore/ChangeLog	2020-04-23 08:59:31 UTC (rev 260561)
@@ -1,3 +1,75 @@
+2020-04-23  Youenn Fablet  <[email protected]>
+
+        getDisplayMedia is not respecting aspect ratio with max constraints
+        https://bugs.webkit.org/show_bug.cgi?id=210858
+
+        Reviewed by Eric Carlson.
+
+        Add computation of exact frame size to respect aspect ratio in DisplayCaptureSourceCocoa::updateFrameSize.
+        Refactor code to have one source class DisplayCaptureSourceCocoa and specific capturer for screen and window.
+        This simplifies code and allows reusing DisplayCaptureSourceCocoa with a mock capturer.
+        Update mock code to use DisplayCaptureSourceCocoa.
+
+        Tests: fast/mediastream/getDisplayMedia-max-constraints.html
+               fast/mediastream/getDisplayMedia-max-constraints1.html
+               fast/mediastream/getDisplayMedia-max-constraints2.html
+               fast/mediastream/getDisplayMedia-max-constraints3.html
+
+        * SourcesCocoa.txt:
+        * WebCore.xcodeproj/project.pbxproj:
+        * platform/mediastream/mac/DisplayCaptureManagerCocoa.cpp:
+        (WebCore::DisplayCaptureManagerCocoa::updateDisplayCaptureDevices):
+        (WebCore::DisplayCaptureManagerCocoa::updateWindowCaptureDevices):
+        (WebCore::DisplayCaptureManagerCocoa::screenCaptureDeviceWithPersistentID):
+        (WebCore::DisplayCaptureManagerCocoa::windowCaptureDeviceWithPersistentID):
+        * platform/mediastream/mac/DisplayCaptureSourceCocoa.cpp:
+        (WebCore::DisplayCaptureSourceCocoa::create):
+        (WebCore::DisplayCaptureSourceCocoa::DisplayCaptureSourceCocoa):
+        (WebCore::DisplayCaptureSourceCocoa::~DisplayCaptureSourceCocoa):
+        (WebCore::DisplayCaptureSourceCocoa::capabilities):
+        (WebCore::DisplayCaptureSourceCocoa::settings):
+        (WebCore::DisplayCaptureSourceCocoa::startProducingData):
+        (WebCore::DisplayCaptureSourceCocoa::stopProducingData):
+        (WebCore::DisplayCaptureSourceCocoa::updateFrameSize):
+        (WebCore::DisplayCaptureSourceCocoa::emitFrame):
+        (WebCore::DisplayCaptureSourceCocoa::Capturer::setLogger):
+        (WebCore::DisplayCaptureSourceCocoa::Capturer::logChannel const):
+        * platform/mediastream/mac/DisplayCaptureSourceCocoa.h:
+        * platform/mediastream/mac/MockRealtimeVideoSourceMac.h:
+        * platform/mediastream/mac/MockRealtimeVideoSourceMac.mm:
+        (WebCore::MockRealtimeVideoSourceMac::createForMockDisplayCapturer):
+        * platform/mediastream/mac/RealtimeMediaSourceCenterMac.cpp:
+        * platform/mediastream/mac/ScreenDisplayCapturerMac.h: Added.
+        * platform/mediastream/mac/ScreenDisplayCapturerMac.mm: Added.
+        (WebCore::ScreenDisplayCapturerMac::create):
+        (WebCore::ScreenDisplayCapturerMac::ScreenDisplayCapturerMac):
+        (WebCore::ScreenDisplayCapturerMac::~ScreenDisplayCapturerMac):
+        (WebCore::ScreenDisplayCapturerMac::createDisplayStream):
+        (WebCore::ScreenDisplayCapturerMac::start):
+        (WebCore::ScreenDisplayCapturerMac::stop):
+        (WebCore::ScreenDisplayCapturerMac::generateFrame):
+        (WebCore::ScreenDisplayCapturerMac::startDisplayStream):
+        (WebCore::ScreenDisplayCapturerMac::commitConfiguration):
+        (WebCore::ScreenDisplayCapturerMac::displayWasReconfigured):
+        (WebCore::ScreenDisplayCapturerMac::displayReconfigurationCallBack):
+        (WebCore::ScreenDisplayCapturerMac::newFrame):
+        (WebCore::ScreenDisplayCapturerMac::screenCaptureDeviceWithPersistentID):
+        (WebCore::ScreenDisplayCapturerMac::screenCaptureDevices):
+        * platform/mediastream/mac/WindowDisplayCapturerMac.h: Added.
+        * platform/mediastream/mac/WindowDisplayCapturerMac.mm: ddedAdded.
+        (WebCore::WindowDisplayCapturerMac::create):
+        (WebCore::WindowDisplayCapturerMac::WindowDisplayCapturerMac):
+        (WebCore::WindowDisplayCapturerMac::windowImage):
+        (WebCore::WindowDisplayCapturerMac::generateFrame):
+        (WebCore::WindowDisplayCapturerMac::windowCaptureDeviceWithPersistentID):
+        (WebCore::WindowDisplayCapturerMac::windowCaptureDevices):
+        * platform/mock/MockRealtimeMediaSourceCenter.cpp:
+        (WebCore::MockDisplayCapturer::MockDisplayCapturer):
+        (WebCore::MockDisplayCapturer::start):
+        (WebCore::MockDisplayCapturer::generateFrame):
+        * platform/mock/MockRealtimeVideoSource.h:
+        (isType):
+
 2020-04-22  Simon Fraser  <[email protected]>
 
         Make it possible to eagerly apply scrolling tree state from the main thread

Modified: trunk/Source/WebCore/SourcesCocoa.txt (260560 => 260561)


--- trunk/Source/WebCore/SourcesCocoa.txt	2020-04-23 08:47:37 UTC (rev 260560)
+++ trunk/Source/WebCore/SourcesCocoa.txt	2020-04-23 08:59:31 UTC (rev 260561)
@@ -570,8 +570,8 @@
 platform/mediastream/mac/RealtimeOutgoingAudioSourceCocoa.cpp
 platform/mediastream/mac/RealtimeOutgoingVideoSourceCocoa.cpp
 platform/mediastream/mac/RealtimeVideoUtilities.mm
-platform/mediastream/mac/ScreenDisplayCaptureSourceMac.mm
-platform/mediastream/mac/WindowDisplayCaptureSourceMac.mm
+platform/mediastream/mac/ScreenDisplayCapturerMac.mm
+platform/mediastream/mac/WindowDisplayCapturerMac.mm
 
 platform/audio/mac/AudioSampleDataSource.mm
 

Modified: trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj (260560 => 260561)


--- trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj	2020-04-23 08:47:37 UTC (rev 260560)
+++ trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj	2020-04-23 08:59:31 UTC (rev 260561)
@@ -215,7 +215,6 @@
 		07C1C0E51BFB60ED00BD2256 /* RealtimeMediaSourceSupportedConstraints.h in Headers */ = {isa = PBXBuildFile; fileRef = 07C1C0E41BFB60ED00BD2256 /* RealtimeMediaSourceSupportedConstraints.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		07CE77D516712A6A00C55A47 /* InbandTextTrackPrivateClient.h in Headers */ = {isa = PBXBuildFile; fileRef = 07CE77D416712A6A00C55A47 /* InbandTextTrackPrivateClient.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		07D12F5C23DE543F0080997D /* ISOVTTCue.h in Headers */ = {isa = PBXBuildFile; fileRef = CD871C651FB52B6700F0B965 /* ISOVTTCue.h */; settings = {ATTRIBUTES = (Private, ); }; };
-		07D60928214C5BFD00E7396C /* WindowDisplayCaptureSourceMac.h in Headers */ = {isa = PBXBuildFile; fileRef = 07D60926214C5BFC00E7396C /* WindowDisplayCaptureSourceMac.h */; };
 		07D637401BB0B11300256CE9 /* WebAudioSourceProviderAVFObjC.h in Headers */ = {isa = PBXBuildFile; fileRef = 07D6373E1BB0B11300256CE9 /* WebAudioSourceProviderAVFObjC.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		07D6A4F41BED5F8800174146 /* MockRealtimeAudioSource.h in Headers */ = {isa = PBXBuildFile; fileRef = 07D6A4F21BED5F8800174146 /* MockRealtimeAudioSource.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		07D6A4F81BF2307D00174146 /* AudioTrackPrivateMediaStream.h in Headers */ = {isa = PBXBuildFile; fileRef = 07D6A4F61BF2307D00174146 /* AudioTrackPrivateMediaStream.h */; };
@@ -5454,8 +5453,6 @@
 		0709D7911AE5557E004E42F8 /* WebMediaSessionManagerMac.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebMediaSessionManagerMac.h; sourceTree = "<group>"; };
 		0709D7941AE55A29004E42F8 /* WebMediaSessionManagerClient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebMediaSessionManagerClient.h; sourceTree = "<group>"; };
 		0709FC4D1025DEE30059CDBA /* AccessibilitySlider.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AccessibilitySlider.h; sourceTree = "<group>"; };
-		070A9F5E1FFECC70003DF649 /* ScreenDisplayCaptureSourceMac.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ScreenDisplayCaptureSourceMac.h; sourceTree = "<group>"; };
-		070A9F601FFECC71003DF649 /* ScreenDisplayCaptureSourceMac.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ScreenDisplayCaptureSourceMac.mm; sourceTree = "<group>"; };
 		070DD8F50F01868000727DEB /* mediaControls.css */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = mediaControls.css; sourceTree = "<group>"; };
 		070E09181875ED93003A1D3C /* PlatformMediaSession.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PlatformMediaSession.h; sourceTree = "<group>"; };
 		070E091A1875EF71003A1D3C /* PlatformMediaSession.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PlatformMediaSession.cpp; sourceTree = "<group>"; };
@@ -5667,8 +5664,6 @@
 		07C8AD111D073D630087C5CE /* AVAssetMIMETypeCache.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = AVAssetMIMETypeCache.mm; sourceTree = "<group>"; };
 		07C8AD121D073D630087C5CE /* AVAssetMIMETypeCache.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AVAssetMIMETypeCache.h; sourceTree = "<group>"; };
 		07CE77D416712A6A00C55A47 /* InbandTextTrackPrivateClient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InbandTextTrackPrivateClient.h; sourceTree = "<group>"; };
-		07D60924214C5BFB00E7396C /* WindowDisplayCaptureSourceMac.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = WindowDisplayCaptureSourceMac.mm; sourceTree = "<group>"; };
-		07D60926214C5BFC00E7396C /* WindowDisplayCaptureSourceMac.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WindowDisplayCaptureSourceMac.h; sourceTree = "<group>"; };
 		07D6373E1BB0B11300256CE9 /* WebAudioSourceProviderAVFObjC.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebAudioSourceProviderAVFObjC.h; sourceTree = "<group>"; };
 		07D6373F1BB0B11300256CE9 /* WebAudioSourceProviderAVFObjC.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = WebAudioSourceProviderAVFObjC.mm; sourceTree = "<group>"; };
 		07D6A4F11BED5F8800174146 /* MockRealtimeAudioSource.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MockRealtimeAudioSource.cpp; sourceTree = "<group>"; };
@@ -7449,6 +7444,10 @@
 		416D759F20C6441300D02D2C /* NetworkLoadInformation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NetworkLoadInformation.h; sourceTree = "<group>"; };
 		416E0B37209BC3C2004A95D9 /* FetchIdentifier.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FetchIdentifier.h; sourceTree = "<group>"; };
 		416E29A5102FA962007FC14E /* WorkerReportingProxy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WorkerReportingProxy.h; sourceTree = "<group>"; };
+		416F807924509F3200B68F02 /* WindowDisplayCapturerMac.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WindowDisplayCapturerMac.h; sourceTree = "<group>"; };
+		416F807A24509F3200B68F02 /* ScreenDisplayCapturerMac.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ScreenDisplayCapturerMac.mm; sourceTree = "<group>"; };
+		416F807B24509F3300B68F02 /* WindowDisplayCapturerMac.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = WindowDisplayCapturerMac.mm; sourceTree = "<group>"; };
+		416F807C24509F3300B68F02 /* ScreenDisplayCapturerMac.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ScreenDisplayCapturerMac.h; sourceTree = "<group>"; };
 		416FD25D240EE1AE006661D8 /* NowPlayingInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NowPlayingInfo.h; sourceTree = "<group>"; };
 		4170A2E91D8C0CC000318452 /* JSDOMWrapper.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSDOMWrapper.cpp; sourceTree = "<group>"; };
 		417253A81354BBBC00360F2A /* MediaControlTextTrackContainerElement.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MediaControlTextTrackContainerElement.cpp; sourceTree = "<group>"; };
@@ -16539,12 +16538,12 @@
 				419242472127B7CC00634FCF /* RealtimeOutgoingVideoSourceCocoa.mm */,
 				41D1938F2152C561006F14CA /* RealtimeVideoUtilities.h */,
 				4158649F23BF7B9300A0A61E /* RealtimeVideoUtilities.mm */,
-				070A9F5E1FFECC70003DF649 /* ScreenDisplayCaptureSourceMac.h */,
-				070A9F601FFECC71003DF649 /* ScreenDisplayCaptureSourceMac.mm */,
+				416F807C24509F3300B68F02 /* ScreenDisplayCapturerMac.h */,
+				416F807A24509F3200B68F02 /* ScreenDisplayCapturerMac.mm */,
 				07D6373E1BB0B11300256CE9 /* WebAudioSourceProviderAVFObjC.h */,
 				07D6373F1BB0B11300256CE9 /* WebAudioSourceProviderAVFObjC.mm */,
-				07D60926214C5BFC00E7396C /* WindowDisplayCaptureSourceMac.h */,
-				07D60924214C5BFB00E7396C /* WindowDisplayCaptureSourceMac.mm */,
+				416F807924509F3200B68F02 /* WindowDisplayCapturerMac.h */,
+				416F807B24509F3300B68F02 /* WindowDisplayCapturerMac.mm */,
 			);
 			path = mac;
 			sourceTree = "<group>";
@@ -33567,7 +33566,6 @@
 				1411DCB1164C39A800D49BC1 /* WidthCache.h in Headers */,
 				939B02EF0EA2DBC400C54570 /* WidthIterator.h in Headers */,
 				0F15ED5C1B7EC7C500EDDFEB /* WillChangeData.h in Headers */,
-				07D60928214C5BFD00E7396C /* WindowDisplayCaptureSourceMac.h in Headers */,
 				9B27FC60234D9ADB00394A46 /* WindowEventLoop.h in Headers */,
 				BC8243E90D0CFD7500460C8F /* WindowFeatures.h in Headers */,
 				7E99AF530B13846468FB01A5 /* WindowFocusAllowedIndicator.h in Headers */,

Modified: trunk/Source/WebCore/platform/mediastream/RealtimeMediaSourceFactory.h (260560 => 260561)


--- trunk/Source/WebCore/platform/mediastream/RealtimeMediaSourceFactory.h	2020-04-23 08:47:37 UTC (rev 260560)
+++ trunk/Source/WebCore/platform/mediastream/RealtimeMediaSourceFactory.h	2020-04-23 08:59:31 UTC (rev 260561)
@@ -89,7 +89,11 @@
     VideoCaptureFactory() = default;
 };
 
-class DisplayCaptureFactory {
+class DisplayCaptureFactory
+#if PLATFORM(IOS_FAMILY)
+    : public SingleSourceFactory
+#endif
+{
 public:
     virtual ~DisplayCaptureFactory() = default;
     virtual CaptureSourceOrError createDisplayCaptureSource(const CaptureDevice&, const MediaConstraints*) = 0;

Modified: trunk/Source/WebCore/platform/mediastream/mac/DisplayCaptureManagerCocoa.cpp (260560 => 260561)


--- trunk/Source/WebCore/platform/mediastream/mac/DisplayCaptureManagerCocoa.cpp	2020-04-23 08:47:37 UTC (rev 260560)
+++ trunk/Source/WebCore/platform/mediastream/mac/DisplayCaptureManagerCocoa.cpp	2020-04-23 08:59:31 UTC (rev 260561)
@@ -33,8 +33,8 @@
 #include <wtf/NeverDestroyed.h>
 
 #if PLATFORM(MAC)
-#include "ScreenDisplayCaptureSourceMac.h"
-#include "WindowDisplayCaptureSourceMac.h"
+#include "ScreenDisplayCapturerMac.h"
+#include "WindowDisplayCapturerMac.h"
 #include <CoreGraphics/CGDirectDisplay.h>
 #endif
 
@@ -61,7 +61,7 @@
 void DisplayCaptureManagerCocoa::updateDisplayCaptureDevices()
 {
 #if PLATFORM(MAC)
-    ScreenDisplayCaptureSourceMac::screenCaptureDevices(m_devices);
+    ScreenDisplayCapturerMac::screenCaptureDevices(m_devices);
 #endif
 }
 
@@ -68,7 +68,7 @@
 void DisplayCaptureManagerCocoa::updateWindowCaptureDevices()
 {
 #if PLATFORM(MAC)
-    WindowDisplayCaptureSourceMac::windowCaptureDevices(m_devices);
+    WindowDisplayCapturerMac::windowCaptureDevices(m_devices);
 #endif
 }
 
@@ -75,7 +75,7 @@
 Optional<CaptureDevice> DisplayCaptureManagerCocoa::screenCaptureDeviceWithPersistentID(const String& deviceID)
 {
 #if PLATFORM(MAC)
-    return ScreenDisplayCaptureSourceMac::screenCaptureDeviceWithPersistentID(deviceID);
+    return ScreenDisplayCapturerMac::screenCaptureDeviceWithPersistentID(deviceID);
 #else
     UNUSED_PARAM(deviceID);
     return WTF::nullopt;
@@ -85,7 +85,7 @@
 Optional<CaptureDevice> DisplayCaptureManagerCocoa::windowCaptureDeviceWithPersistentID(const String& deviceID)
 {
 #if PLATFORM(MAC)
-    return WindowDisplayCaptureSourceMac::windowCaptureDeviceWithPersistentID(deviceID);
+    return WindowDisplayCapturerMac::windowCaptureDeviceWithPersistentID(deviceID);
 #else
     UNUSED_PARAM(deviceID);
     return WTF::nullopt;

Modified: trunk/Source/WebCore/platform/mediastream/mac/DisplayCaptureSourceCocoa.cpp (260560 => 260561)


--- trunk/Source/WebCore/platform/mediastream/mac/DisplayCaptureSourceCocoa.cpp	2020-04-23 08:47:37 UTC (rev 260560)
+++ trunk/Source/WebCore/platform/mediastream/mac/DisplayCaptureSourceCocoa.cpp	2020-04-23 08:59:31 UTC (rev 260561)
@@ -53,8 +53,45 @@
 namespace WebCore {
 using namespace PAL;
 
-DisplayCaptureSourceCocoa::DisplayCaptureSourceCocoa(String&& name)
+CaptureSourceOrError DisplayCaptureSourceCocoa::create(const CaptureDevice& device, const MediaConstraints* constraints)
+{
+#if PLATFORM(MAC)
+    switch (device.type()) {
+    case CaptureDevice::DeviceType::Screen:
+        return create(ScreenDisplayCapturerMac::create(device.persistentId()), device, constraints);
+    case CaptureDevice::DeviceType::Window:
+        return create(WindowDisplayCapturerMac::create(device.persistentId()), device, constraints);
+    case CaptureDevice::DeviceType::Microphone:
+    case CaptureDevice::DeviceType::Camera:
+    case CaptureDevice::DeviceType::Unknown:
+        ASSERT_NOT_REACHED();
+        break;
+    }
+#else
+    UNUSED_PARAM(device);
+    UNUSED_PARAM(constraints);
+#endif
+    return { };
+}
+
+CaptureSourceOrError DisplayCaptureSourceCocoa::create(Expected<UniqueRef<Capturer>, String>&& capturer, const CaptureDevice& device, const MediaConstraints* constraints)
+{
+    if (!capturer.has_value())
+        return CaptureSourceOrError { WTFMove(capturer.error()) };
+
+    auto source = adoptRef(*new DisplayCaptureSourceCocoa(WTFMove(capturer.value()), String { device.label() }));
+    if (constraints) {
+        auto result = source->applyConstraints(*constraints);
+        if (result)
+            return WTFMove(result.value().badConstraint);
+    }
+
+    return CaptureSourceOrError(WTFMove(source));
+}
+
+DisplayCaptureSourceCocoa::DisplayCaptureSourceCocoa(UniqueRef<Capturer>&& capturer, String&& name)
     : RealtimeMediaSource(Type::Video, WTFMove(name))
+    , m_capturer(WTFMove(capturer))
     , m_timer(RunLoop::current(), this, &DisplayCaptureSourceCocoa::emitFrame)
 {
 }
@@ -62,7 +99,7 @@
 DisplayCaptureSourceCocoa::~DisplayCaptureSourceCocoa()
 {
 #if PLATFORM(IOS_FAMILY)
-    RealtimeMediaSourceCenter::singleton().videoCaptureFactory().unsetActiveSource(*this);
+    RealtimeMediaSourceCenter::singleton().displayCaptureFactory().unsetActiveSource(*this);
 #endif
 }
 
@@ -72,8 +109,8 @@
         RealtimeMediaSourceCapabilities capabilities(settings().supportedConstraints());
 
         // FIXME: what should these be?
-        capabilities.setWidth(CapabilityValueOrRange(72, 2880));
-        capabilities.setHeight(CapabilityValueOrRange(45, 1800));
+        capabilities.setWidth(CapabilityValueOrRange(1, 3840));
+        capabilities.setHeight(CapabilityValueOrRange(1, 2160));
         capabilities.setFrameRate(CapabilityValueOrRange(.01, 30.0));
 
         m_capabilities = WTFMove(capabilities);
@@ -91,7 +128,7 @@
         settings.setWidth(size.width());
         settings.setHeight(size.height());
 
-        settings.setDisplaySurface(surfaceType());
+        settings.setDisplaySurface(m_capturer->surfaceType());
         settings.setLogicalSurface(false);
 
         RealtimeMediaSourceSupportedConstraints supportedConstraints;
@@ -122,11 +159,14 @@
 void DisplayCaptureSourceCocoa::startProducingData()
 {
 #if PLATFORM(IOS_FAMILY)
-    RealtimeMediaSourceCenter::singleton().videoCaptureFactory().setActiveSource(*this);
+    RealtimeMediaSourceCenter::singleton().displayCaptureFactory().setActiveSource(*this);
 #endif
 
     m_startTime = MonotonicTime::now();
     m_timer.startRepeating(1_s / frameRate());
+
+    if (!m_capturer->start(frameRate()))
+        captureFailed();
 }
 
 void DisplayCaptureSourceCocoa::stopProducingData()
@@ -134,6 +174,8 @@
     m_timer.stop();
     m_elapsedTime += MonotonicTime::now() - m_startTime;
     m_startTime = MonotonicTime::nan();
+
+    m_capturer->stop();
 }
 
 Seconds DisplayCaptureSourceCocoa::elapsedTime()
@@ -144,13 +186,32 @@
     return m_elapsedTime + (MonotonicTime::now() - m_startTime);
 }
 
-IntSize DisplayCaptureSourceCocoa::frameSize() const
+// We keep the aspect ratio of the intrinsic size for the frame size as getDisplayMedia allows max constraints only.
+void DisplayCaptureSourceCocoa::updateFrameSize()
 {
-    IntSize frameSize = size();
-    if (frameSize.isEmpty())
-        return intrinsicSize();
+    auto intrinsicSize = this->intrinsicSize();
 
-    return frameSize;
+    auto frameSize = size();
+    if (!frameSize.height())
+        frameSize.setHeight(intrinsicSize.height());
+    if (!frameSize.width())
+        frameSize.setWidth(intrinsicSize.width());
+
+    auto maxHeight = std::min(frameSize.height(), intrinsicSize.height());
+    auto maxWidth = std::min(frameSize.width(), intrinsicSize.width());
+
+    auto heightForMaxWidth = maxWidth * intrinsicSize.height() / intrinsicSize.width();
+    auto widthForMaxHeight = maxHeight * intrinsicSize.width() / intrinsicSize.height();
+
+    if (heightForMaxWidth <= maxHeight) {
+        setSize({ maxWidth, heightForMaxWidth });
+        return;
+    }
+    if (widthForMaxHeight <= maxWidth) {
+        setSize({ widthForMaxHeight, maxHeight });
+        return;
+    }
+    setSize(intrinsicSize);
 }
 
 void DisplayCaptureSourceCocoa::emitFrame()
@@ -164,7 +225,7 @@
 
     auto sampleTime = MediaTime::createWithDouble((elapsedTime() + 100_ms).seconds());
 
-    auto frame = generateFrame();
+    auto frame = m_capturer->generateFrame();
     auto imageSize = WTF::switchOn(frame,
         [](RetainPtr<IOSurfaceRef> surface) -> IntSize {
             if (!surface)
@@ -184,22 +245,23 @@
     if (imageSize.isEmpty())
         return;
 
-    setIntrinsicSize(imageSize);
+    if (intrinsicSize() != imageSize) {
+        setIntrinsicSize(imageSize);
+        updateFrameSize();
+    }
 
-    auto mediaSampleSize = frameSize();
-
-    RefPtr<MediaSample> sample = WTF::switchOn(frame,
-        [this, sampleTime, mediaSampleSize](RetainPtr<IOSurfaceRef> surface) -> RefPtr<MediaSample> {
+    auto sample = WTF::switchOn(frame,
+        [this, sampleTime](RetainPtr<IOSurfaceRef> surface) -> RefPtr<MediaSample> {
             if (!surface)
                 return nullptr;
 
-            return m_imageTransferSession->createMediaSample(surface.get(), sampleTime, mediaSampleSize);
+            return m_imageTransferSession->createMediaSample(surface.get(), sampleTime, size());
         },
-        [this, sampleTime, mediaSampleSize](RetainPtr<CGImageRef> image) -> RefPtr<MediaSample> {
+        [this, sampleTime](RetainPtr<CGImageRef> image) -> RefPtr<MediaSample> {
             if (!image)
                 return nullptr;
 
-            return m_imageTransferSession->createMediaSample(image.get(), sampleTime, mediaSampleSize);
+            return m_imageTransferSession->createMediaSample(image.get(), sampleTime, size());
         }
     );
 
@@ -212,6 +274,19 @@
 #endif
 }
 
+#if !RELEASE_LOG_DISABLED
+void DisplayCaptureSourceCocoa::Capturer::setLogger(const Logger& newLogger, const void* newLogIdentifier)
+{
+    m_logger = &newLogger;
+    m_logIdentifier = newLogIdentifier;
+}
+
+WTFLogChannel& DisplayCaptureSourceCocoa::Capturer::logChannel() const
+{
+    return LogWebRTC;
+}
+#endif
+
 } // namespace WebCore
 
 #endif // ENABLE(MEDIA_STREAM)

Modified: trunk/Source/WebCore/platform/mediastream/mac/DisplayCaptureSourceCocoa.h (260560 => 260561)


--- trunk/Source/WebCore/platform/mediastream/mac/DisplayCaptureSourceCocoa.h	2020-04-23 08:47:37 UTC (rev 260560)
+++ trunk/Source/WebCore/platform/mediastream/mac/DisplayCaptureSourceCocoa.h	2020-04-23 08:59:31 UTC (rev 260561)
@@ -33,6 +33,7 @@
 #include <wtf/RefCounted.h>
 #include <wtf/RefPtr.h>
 #include <wtf/RunLoop.h>
+#include <wtf/UniqueRef.h>
 #include <wtf/text/WTFString.h>
 
 typedef struct CGImage *CGImageRef;
@@ -49,36 +50,66 @@
 class ImageTransferSessionVT;
 class PixelBufferConformerCV;
 
-class DisplayCaptureSourceCocoa : public RealtimeMediaSource {
+class DisplayCaptureSourceCocoa final : public RealtimeMediaSource {
 public:
+    using DisplayFrameType = WTF::Variant<RetainPtr<CGImageRef>, RetainPtr<IOSurfaceRef>>;
+    class Capturer
+#if !RELEASE_LOG_DISABLED
+        : public LoggerHelper
+#endif
+    {
+        WTF_MAKE_FAST_ALLOCATED;
+    public:
+        virtual ~Capturer() = default;
 
-protected:
-    DisplayCaptureSourceCocoa(String&& name);
-    virtual ~DisplayCaptureSourceCocoa();
+        virtual bool start(float frameRate) = 0;
+        virtual void stop() = 0;
+        virtual DisplayFrameType generateFrame() = 0;
+        virtual CaptureDevice::DeviceType deviceType() const = 0;
+        virtual RealtimeMediaSourceSettings::DisplaySurfaceType surfaceType() const = 0;
+        virtual void commitConfiguration(float frameRate) = 0;
 
-    using DisplayFrameType = WTF::Variant<RetainPtr<CGImageRef>, RetainPtr<IOSurfaceRef>>;
-    virtual DisplayFrameType generateFrame() = 0;
+#if !RELEASE_LOG_DISABLED
+        virtual void setLogger(const Logger&, const void*);
+        const Logger* loggerPtr() const { return m_logger.get(); }
+        const Logger& logger() const final { ASSERT(m_logger); return *m_logger.get(); }
+        const void* logIdentifier() const final { return m_logIdentifier; }
+        WTFLogChannel& logChannel() const final;
+#endif
 
-    virtual RealtimeMediaSourceSettings::DisplaySurfaceType surfaceType() const = 0;
+    private:
+#if !RELEASE_LOG_DISABLED
+        RefPtr<const Logger> m_logger;
+        const void* m_logIdentifier;
+#endif
+    };
 
-    void startProducingData() override;
-    void stopProducingData() override;
+    static CaptureSourceOrError create(const CaptureDevice&, const MediaConstraints*);
+    static CaptureSourceOrError create(Expected<UniqueRef<Capturer>, String>&&, const CaptureDevice&, const MediaConstraints*);
 
     Seconds elapsedTime();
+    void updateFrameSize();
 
-    void settingsDidChange(OptionSet<RealtimeMediaSourceSettings::Flag>) override;
-
-    IntSize frameSize() const;
-
 private:
+    DisplayCaptureSourceCocoa(UniqueRef<Capturer>&&, String&& name);
+    ~DisplayCaptureSourceCocoa();
 
+    void startProducingData() final;
+    void stopProducingData() final;
+    void settingsDidChange(OptionSet<RealtimeMediaSourceSettings::Flag>) final;
     bool isCaptureSource() const final { return true; }
-
     const RealtimeMediaSourceCapabilities& capabilities() final;
     const RealtimeMediaSourceSettings& settings() final;
+    CaptureDevice::DeviceType deviceType() const { return m_capturer->deviceType(); }
+    void commitConfiguration() final { return m_capturer->commitConfiguration(frameRate()); }
 
+#if !RELEASE_LOG_DISABLED
+    const char* logClassName() const final { return "DisplayCaptureSourceCocoa"; }
+#endif
+
     void emitFrame();
 
+    UniqueRef<Capturer> m_capturer;
     Optional<RealtimeMediaSourceCapabilities> m_capabilities;
     Optional<RealtimeMediaSourceSettings> m_currentSettings;
     RealtimeMediaSourceSupportedConstraints m_supportedConstraints;

Modified: trunk/Source/WebCore/platform/mediastream/mac/MockRealtimeVideoSourceMac.h (260560 => 260561)


--- trunk/Source/WebCore/platform/mediastream/mac/MockRealtimeVideoSourceMac.h	2020-04-23 08:47:37 UTC (rev 260560)
+++ trunk/Source/WebCore/platform/mediastream/mac/MockRealtimeVideoSourceMac.h	2020-04-23 08:59:31 UTC (rev 260561)
@@ -46,8 +46,10 @@
 
 class MockRealtimeVideoSourceMac final : public MockRealtimeVideoSource {
 public:
-    virtual ~MockRealtimeVideoSourceMac() = default;
+    static Ref<MockRealtimeVideoSource> createForMockDisplayCapturer(String&& deviceID, String&& name, String&& hashSalt);
 
+    ~MockRealtimeVideoSourceMac() = default;
+
 private:
     friend class MockRealtimeVideoSource;
     MockRealtimeVideoSourceMac(String&& deviceID, String&& name, String&& hashSalt);

Modified: trunk/Source/WebCore/platform/mediastream/mac/MockRealtimeVideoSourceMac.mm (260560 => 260561)


--- trunk/Source/WebCore/platform/mediastream/mac/MockRealtimeVideoSourceMac.mm	2020-04-23 08:47:37 UTC (rev 260560)
+++ trunk/Source/WebCore/platform/mediastream/mac/MockRealtimeVideoSourceMac.mm	2020-04-23 08:59:31 UTC (rev 260561)
@@ -71,6 +71,11 @@
     return CaptureSourceOrError(RealtimeVideoSource::create(WTFMove(source)));
 }
 
+Ref<MockRealtimeVideoSource> MockRealtimeVideoSourceMac::createForMockDisplayCapturer(String&& deviceID, String&& name, String&& hashSalt)
+{
+    return adoptRef(*new MockRealtimeVideoSourceMac(WTFMove(deviceID), WTFMove(name), WTFMove(hashSalt)));
+}
+
 MockRealtimeVideoSourceMac::MockRealtimeVideoSourceMac(String&& deviceID, String&& name, String&& hashSalt)
     : MockRealtimeVideoSource(WTFMove(deviceID), WTFMove(name), WTFMove(hashSalt))
 {

Modified: trunk/Source/WebCore/platform/mediastream/mac/RealtimeMediaSourceCenterMac.cpp (260560 => 260561)


--- trunk/Source/WebCore/platform/mediastream/mac/RealtimeMediaSourceCenterMac.cpp	2020-04-23 08:47:37 UTC (rev 260560)
+++ trunk/Source/WebCore/platform/mediastream/mac/RealtimeMediaSourceCenterMac.cpp	2020-04-23 08:59:31 UTC (rev 260561)
@@ -38,8 +38,8 @@
 #include "DisplayCaptureManagerCocoa.h"
 #include "Logging.h"
 #include "MediaStreamPrivate.h"
-#include "ScreenDisplayCaptureSourceMac.h"
-#include "WindowDisplayCaptureSourceMac.h"
+#include "ScreenDisplayCapturerMac.h"
+#include "WindowDisplayCapturerMac.h"
 #include <wtf/MainThread.h>
 
 namespace WebCore {
@@ -72,23 +72,11 @@
         UNUSED_PARAM(device);
         UNUSED_PARAM(constraints);
 #endif
-        switch (device.type()) {
-        case CaptureDevice::DeviceType::Screen:
 #if PLATFORM(MAC)
-            return ScreenDisplayCaptureSourceMac::create(String { device.persistentId() }, constraints);
+        return DisplayCaptureSourceCocoa::create(device, constraints);
+#else
+        return { };
 #endif
-        case CaptureDevice::DeviceType::Window:
-#if PLATFORM(MAC)
-            return WindowDisplayCaptureSourceMac::create(String { device.persistentId() }, constraints);
-#endif
-        case CaptureDevice::DeviceType::Microphone:
-        case CaptureDevice::DeviceType::Camera:
-        case CaptureDevice::DeviceType::Unknown:
-            ASSERT_NOT_REACHED();
-            break;
-        }
-
-        return { };
     }
 private:
     CaptureDeviceManager& displayCaptureDeviceManager() { return DisplayCaptureManagerCocoa::singleton(); }

Deleted: trunk/Source/WebCore/platform/mediastream/mac/ScreenDisplayCaptureSourceMac.h (260560 => 260561)


--- trunk/Source/WebCore/platform/mediastream/mac/ScreenDisplayCaptureSourceMac.h	2020-04-23 08:47:37 UTC (rev 260560)
+++ trunk/Source/WebCore/platform/mediastream/mac/ScreenDisplayCaptureSourceMac.h	2020-04-23 08:59:31 UTC (rev 260561)
@@ -1,117 +0,0 @@
-/*
- * Copyright (C) 2017-2019 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#pragma once
-
-#if ENABLE(MEDIA_STREAM) && PLATFORM(MAC)
-
-#include "DisplayCaptureSourceCocoa.h"
-#include "IOSurface.h"
-#include <CoreGraphics/CGDisplayConfiguration.h>
-#include <CoreGraphics/CGDisplayStream.h>
-#include <wtf/Lock.h>
-#include <wtf/OSObjectPtr.h>
-
-typedef struct __CVBuffer *CVPixelBufferRef;
-typedef struct opaqueCMSampleBuffer *CMSampleBufferRef;
-
-namespace WebCore {
-
-class ScreenDisplayCaptureSourceMac : public DisplayCaptureSourceCocoa {
-public:
-    static CaptureSourceOrError create(String&&, const MediaConstraints*);
-
-    static Optional<CaptureDevice> screenCaptureDeviceWithPersistentID(const String&);
-    static void screenCaptureDevices(Vector<CaptureDevice>&);
-
-private:
-    ScreenDisplayCaptureSourceMac(uint32_t, String&&);
-    virtual ~ScreenDisplayCaptureSourceMac();
-
-    static void displayReconfigurationCallBack(CGDirectDisplayID, CGDisplayChangeSummaryFlags, void*);
-
-    void displayWasReconfigured(CGDirectDisplayID, CGDisplayChangeSummaryFlags);
-
-    DisplayCaptureSourceCocoa::DisplayFrameType generateFrame() final;
-    RealtimeMediaSourceSettings::DisplaySurfaceType surfaceType() const final { return RealtimeMediaSourceSettings::DisplaySurfaceType::Monitor; }
-
-    void startProducingData() final;
-    void stopProducingData() final;
-    void commitConfiguration() final;
-    CaptureDevice::DeviceType deviceType() const final { return CaptureDevice::DeviceType::Screen; }
-
-    bool createDisplayStream();
-    void startDisplayStream();
-
-#if !RELEASE_LOG_DISABLED
-    const char* logClassName() const override { return "ScreenDisplayCaptureSourceMac"; }
-#endif
-
-    class DisplaySurface {
-    public:
-        DisplaySurface() = default;
-        explicit DisplaySurface(IOSurfaceRef surface)
-            : m_surface(surface)
-        {
-            if (m_surface)
-                IOSurfaceIncrementUseCount(m_surface.get());
-        }
-
-        ~DisplaySurface()
-        {
-            if (m_surface)
-                IOSurfaceDecrementUseCount(m_surface.get());
-        }
-
-        DisplaySurface& operator=(IOSurfaceRef surface)
-        {
-            if (m_surface)
-                IOSurfaceDecrementUseCount(m_surface.get());
-            if (surface)
-                IOSurfaceIncrementUseCount(surface);
-            m_surface = surface;
-            return *this;
-        }
-
-        IOSurfaceRef ioSurface() const { return m_surface.get(); }
-
-    private:
-        RetainPtr<IOSurfaceRef> m_surface;
-    };
-
-    void newFrame(CGDisplayStreamFrameStatus, DisplaySurface&&);
-
-    DisplaySurface m_currentFrame;
-    RetainPtr<CGDisplayStreamRef> m_displayStream;
-    OSObjectPtr<dispatch_queue_t> m_captureQueue;
-
-    uint32_t m_displayID { 0 };
-    bool m_isRunning { false };
-    bool m_observingDisplayChanges { false };
-};
-
-} // namespace WebCore
-
-#endif // ENABLE(MEDIA_STREAM) && PLATFORM(MAC)

Deleted: trunk/Source/WebCore/platform/mediastream/mac/ScreenDisplayCaptureSourceMac.mm (260560 => 260561)


--- trunk/Source/WebCore/platform/mediastream/mac/ScreenDisplayCaptureSourceMac.mm	2020-04-23 08:47:37 UTC (rev 260560)
+++ trunk/Source/WebCore/platform/mediastream/mac/ScreenDisplayCaptureSourceMac.mm	2020-04-23 08:59:31 UTC (rev 260561)
@@ -1,339 +0,0 @@
-/*
- * Copyright (C) 2017-2019 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#import "config.h"
-#import "ScreenDisplayCaptureSourceMac.h"
-
-#if ENABLE(MEDIA_STREAM) && PLATFORM(MAC)
-
-#import "GraphicsContextCG.h"
-#import "ImageBuffer.h"
-#import "Logging.h"
-#import "MediaConstraints.h"
-#import "MediaSampleAVFObjC.h"
-#import "NotImplemented.h"
-#import "PlatformLayer.h"
-#import "PlatformScreen.h"
-#import "RealtimeMediaSourceSettings.h"
-#import "RealtimeVideoUtilities.h"
-
-#import "CoreVideoSoftLink.h"
-
-extern "C" {
-size_t CGDisplayModeGetPixelsWide(CGDisplayModeRef);
-size_t CGDisplayModeGetPixelsHigh(CGDisplayModeRef);
-}
-
-namespace WebCore {
-
-static Optional<CGDirectDisplayID> updateDisplayID(CGDirectDisplayID displayID)
-{
-    uint32_t displayCount = 0;
-    auto err = CGGetActiveDisplayList(0, nullptr, &displayCount);
-    if (err) {
-        RELEASE_LOG(Media, "CGGetActiveDisplayList() returned error %d when trying to get display count", static_cast<int>(err));
-        return WTF::nullopt;
-    }
-
-    if (!displayCount) {
-        RELEASE_LOG(Media, "CGGetActiveDisplayList() returned a display count of 0");
-        return WTF::nullopt;
-    }
-
-    Vector<CGDirectDisplayID> activeDisplays(displayCount);
-    err = CGGetActiveDisplayList(displayCount, activeDisplays.data(), &displayCount);
-    if (err) {
-        RELEASE_LOG(Media, "CGGetActiveDisplayList() returned error %d when trying to get the active display list", static_cast<int>(err));
-        return WTF::nullopt;
-    }
-
-    auto displayMask = CGDisplayIDToOpenGLDisplayMask(displayID);
-    for (auto display : activeDisplays) {
-        if (displayMask == CGDisplayIDToOpenGLDisplayMask(display))
-            return display;
-    }
-
-    return WTF::nullopt;
-}
-
-CaptureSourceOrError ScreenDisplayCaptureSourceMac::create(String&& deviceID, const MediaConstraints* constraints)
-{
-    bool ok;
-    auto displayID = deviceID.toUIntStrict(&ok);
-    if (!ok) {
-        RELEASE_LOG(Media, "ScreenDisplayCaptureSourceMac::create: Display ID does not convert to 32-bit integer");
-        return { };
-    }
-
-    auto actualDisplayID = updateDisplayID(displayID);
-    if (!actualDisplayID)
-        return { };
-
-    auto source = adoptRef(*new ScreenDisplayCaptureSourceMac(actualDisplayID.value(), "Screen"_s)); // FIXME: figure out what title to use
-    if (constraints && source->applyConstraints(*constraints))
-        return { };
-
-    return CaptureSourceOrError(WTFMove(source));
-}
-
-ScreenDisplayCaptureSourceMac::ScreenDisplayCaptureSourceMac(uint32_t displayID, String&& title)
-    : DisplayCaptureSourceCocoa(WTFMove(title))
-    , m_displayID(displayID)
-{
-}
-
-ScreenDisplayCaptureSourceMac::~ScreenDisplayCaptureSourceMac()
-{
-    if (m_observingDisplayChanges)
-        CGDisplayRemoveReconfigurationCallback(displayReconfigurationCallBack, this);
-
-    m_currentFrame = nullptr;
-}
-
-bool ScreenDisplayCaptureSourceMac::createDisplayStream()
-{
-    static const int screenQueueMaximumLength = 6;
-
-    ALWAYS_LOG_IF(loggerPtr(), LOGIDENTIFIER);
-
-    auto actualDisplayID = updateDisplayID(m_displayID);
-    if (!actualDisplayID) {
-        ERROR_LOG_IF(loggerPtr(), LOGIDENTIFIER, "invalid display ID: ", m_displayID);
-        captureFailed();
-        return false;
-    }
-
-    if (m_displayID != actualDisplayID.value()) {
-        m_displayID = actualDisplayID.value();
-        ALWAYS_LOG_IF(loggerPtr(), LOGIDENTIFIER, "display ID changed to ", static_cast<int>(m_displayID));
-        m_displayStream = nullptr;
-    }
-
-    if (!m_displayStream) {
-        auto displayMode = adoptCF(CGDisplayCopyDisplayMode(m_displayID));
-        auto screenWidth = CGDisplayModeGetPixelsWide(displayMode.get());
-        auto screenHeight = CGDisplayModeGetPixelsHigh(displayMode.get());
-        if (!screenWidth || !screenHeight) {
-            ERROR_LOG_IF(loggerPtr(), LOGIDENTIFIER, "unable to get screen width/height");
-            captureFailed();
-            return false;
-        }
-        setIntrinsicSize(IntSize(screenWidth, screenHeight));
-
-        if (!m_captureQueue)
-            m_captureQueue = adoptOSObject(dispatch_queue_create("ScreenDisplayCaptureSourceMac Capture Queue", DISPATCH_QUEUE_SERIAL));
-
-        NSDictionary* streamOptions = @{
-            (__bridge NSString *)kCGDisplayStreamMinimumFrameTime : @(1 / frameRate()),
-            (__bridge NSString *)kCGDisplayStreamQueueDepth : @(screenQueueMaximumLength),
-            (__bridge NSString *)kCGDisplayStreamColorSpace : (__bridge id)sRGBColorSpaceRef(),
-            (__bridge NSString *)kCGDisplayStreamShowCursor : @YES,
-        };
-
-        auto weakThis = makeWeakPtr(*this);
-        auto frameAvailableBlock = ^(CGDisplayStreamFrameStatus status, uint64_t displayTime, IOSurfaceRef frameSurface, CGDisplayStreamUpdateRef updateRef) {
-
-            if (!frameSurface || !displayTime)
-                return;
-
-            size_t count;
-            auto* rects = CGDisplayStreamUpdateGetRects(updateRef, kCGDisplayStreamUpdateDirtyRects, &count);
-            if (!rects || !count)
-                return;
-
-            RunLoop::main().dispatch([weakThis, status, frame = DisplaySurface { frameSurface }]() mutable {
-                if (!weakThis)
-                    return;
-                weakThis->newFrame(status, WTFMove(frame));
-            });
-        };
-
-        m_displayStream = adoptCF(CGDisplayStreamCreateWithDispatchQueue(m_displayID, screenWidth, screenHeight, preferedPixelBufferFormat(), (__bridge CFDictionaryRef)streamOptions, m_captureQueue.get(), frameAvailableBlock));
-        if (!m_displayStream) {
-            ERROR_LOG_IF(loggerPtr(), LOGIDENTIFIER, "CGDisplayStreamCreate failed");
-            captureFailed();
-            return false;
-        }
-    }
-
-    if (!m_observingDisplayChanges) {
-        CGDisplayRegisterReconfigurationCallback(displayReconfigurationCallBack, this);
-        m_observingDisplayChanges = true;
-    }
-
-    return true;
-}
-
-void ScreenDisplayCaptureSourceMac::startProducingData()
-{
-    ALWAYS_LOG_IF(loggerPtr(), LOGIDENTIFIER);
-    DisplayCaptureSourceCocoa::startProducingData();
-
-    if (m_isRunning)
-        return;
-
-    startDisplayStream();
-}
-
-void ScreenDisplayCaptureSourceMac::stopProducingData()
-{
-    ALWAYS_LOG_IF(loggerPtr(), LOGIDENTIFIER);
-    DisplayCaptureSourceCocoa::stopProducingData();
-
-    if (!m_isRunning)
-        return;
-
-    if (m_displayStream)
-        CGDisplayStreamStop(m_displayStream.get());
-
-    m_isRunning = false;
-}
-
-DisplayCaptureSourceCocoa::DisplayFrameType ScreenDisplayCaptureSourceMac::generateFrame()
-{
-    return DisplayCaptureSourceCocoa::DisplayFrameType { RetainPtr<IOSurfaceRef> { m_currentFrame.ioSurface() } };
-}
-
-void ScreenDisplayCaptureSourceMac::startDisplayStream()
-{
-    auto actualDisplayID = updateDisplayID(m_displayID);
-    if (!actualDisplayID)
-        return;
-
-    if (m_displayID != actualDisplayID.value()) {
-        m_displayID = actualDisplayID.value();
-        ALWAYS_LOG_IF(loggerPtr(), LOGIDENTIFIER, "display ID changed to ", static_cast<int>(m_displayID));
-    }
-
-    if (!m_displayStream && !createDisplayStream())
-        return;
-
-    auto err = CGDisplayStreamStart(m_displayStream.get());
-    if (err) {
-        ERROR_LOG_IF(loggerPtr(), LOGIDENTIFIER, "CGDisplayStreamStart failed with error ", static_cast<int>(err));
-        captureFailed();
-        return;
-    }
-
-    m_isRunning = true;
-}
-
-void ScreenDisplayCaptureSourceMac::commitConfiguration()
-{
-    if (m_isRunning && !m_displayStream)
-        startDisplayStream();
-}
-
-void ScreenDisplayCaptureSourceMac::displayWasReconfigured(CGDirectDisplayID, CGDisplayChangeSummaryFlags)
-{
-    // FIXME: implement!
-}
-
-void ScreenDisplayCaptureSourceMac::displayReconfigurationCallBack(CGDirectDisplayID display, CGDisplayChangeSummaryFlags flags, void *userInfo)
-{
-    if (userInfo)
-        reinterpret_cast<ScreenDisplayCaptureSourceMac *>(userInfo)->displayWasReconfigured(display, flags);
-}
-
-void ScreenDisplayCaptureSourceMac::newFrame(CGDisplayStreamFrameStatus status, DisplaySurface&& newFrame)
-{
-    switch (status) {
-    case kCGDisplayStreamFrameStatusFrameComplete:
-        break;
-
-    case kCGDisplayStreamFrameStatusFrameIdle:
-        break;
-
-    case kCGDisplayStreamFrameStatusFrameBlank:
-        RELEASE_LOG(Media, "ScreenDisplayCaptureSourceMac::frameAvailable: kCGDisplayStreamFrameStatusFrameBlank");
-        break;
-
-    case kCGDisplayStreamFrameStatusStopped:
-        RELEASE_LOG(Media, "ScreenDisplayCaptureSourceMac::frameAvailable: kCGDisplayStreamFrameStatusStopped");
-        break;
-    }
-
-    m_currentFrame = WTFMove(newFrame);
-}
-
-Optional<CaptureDevice> ScreenDisplayCaptureSourceMac::screenCaptureDeviceWithPersistentID(const String& deviceID)
-{
-    bool ok;
-    auto displayID = deviceID.toUIntStrict(&ok);
-    if (!ok) {
-        RELEASE_LOG(Media, "ScreenDisplayCaptureSourceMac::screenCaptureDeviceWithPersistentID: display ID does not convert to 32-bit integer");
-        return WTF::nullopt;
-    }
-
-    auto actualDisplayID = updateDisplayID(displayID);
-    if (!actualDisplayID)
-        return WTF::nullopt;
-
-    auto device = CaptureDevice(String::number(actualDisplayID.value()), CaptureDevice::DeviceType::Screen, "ScreenCaptureDevice"_s);
-    device.setEnabled(true);
-
-    return device;
-}
-
-void ScreenDisplayCaptureSourceMac::screenCaptureDevices(Vector<CaptureDevice>& displays)
-{
-    auto screenID = displayID([NSScreen mainScreen]);
-    if (CGDisplayIDToOpenGLDisplayMask(screenID)) {
-        CaptureDevice displayDevice(String::number(screenID), CaptureDevice::DeviceType::Screen, makeString("Screen 0"));
-        displayDevice.setEnabled(true);
-        displays.append(WTFMove(displayDevice));
-        return;
-    }
-
-    uint32_t displayCount = 0;
-    auto err = CGGetActiveDisplayList(0, nullptr, &displayCount);
-    if (err) {
-        RELEASE_LOG(Media, "CGGetActiveDisplayList() returned error %d when trying to get display count", (int)err);
-        return;
-    }
-
-    if (!displayCount) {
-        RELEASE_LOG(Media, "CGGetActiveDisplayList() returned a display count of 0");
-        return;
-    }
-
-    Vector<CGDirectDisplayID> activeDisplays(displayCount);
-    err = CGGetActiveDisplayList(displayCount, activeDisplays.data(), &displayCount);
-    if (err) {
-        RELEASE_LOG(Media, "CGGetActiveDisplayList() returned error %d when trying to get the active display list", (int)err);
-        return;
-    }
-
-    int count = 0;
-    for (auto displayID : activeDisplays) {
-        CaptureDevice displayDevice(String::number(displayID), CaptureDevice::DeviceType::Screen, makeString("Screen ", String::number(count++)));
-        displayDevice.setEnabled(CGDisplayIDToOpenGLDisplayMask(displayID));
-        displays.append(WTFMove(displayDevice));
-    }
-}
-
-} // namespace WebCore
-
-#endif // ENABLE(MEDIA_STREAM) && PLATFORM(MAC)

Copied: trunk/Source/WebCore/platform/mediastream/mac/ScreenDisplayCapturerMac.h (from rev 260560, trunk/Source/WebCore/platform/mediastream/mac/ScreenDisplayCaptureSourceMac.h) (0 => 260561)


--- trunk/Source/WebCore/platform/mediastream/mac/ScreenDisplayCapturerMac.h	                        (rev 0)
+++ trunk/Source/WebCore/platform/mediastream/mac/ScreenDisplayCapturerMac.h	2020-04-23 08:59:31 UTC (rev 260561)
@@ -0,0 +1,115 @@
+/*
+ * Copyright (C) 2017-2019 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#if ENABLE(MEDIA_STREAM) && PLATFORM(MAC)
+
+#include "DisplayCaptureSourceCocoa.h"
+#include "IOSurface.h"
+#include <CoreGraphics/CGDisplayConfiguration.h>
+#include <CoreGraphics/CGDisplayStream.h>
+#include <wtf/Lock.h>
+#include <wtf/OSObjectPtr.h>
+
+typedef struct __CVBuffer *CVPixelBufferRef;
+typedef struct opaqueCMSampleBuffer *CMSampleBufferRef;
+
+namespace WebCore {
+
+class ScreenDisplayCapturerMac final : public DisplayCaptureSourceCocoa::Capturer, public CanMakeWeakPtr<ScreenDisplayCapturerMac> {
+public:
+    static Expected<UniqueRef<DisplayCaptureSourceCocoa::Capturer>, String> create(const String&);
+
+    explicit ScreenDisplayCapturerMac(uint32_t);
+    ~ScreenDisplayCapturerMac();
+
+    static Optional<CaptureDevice> screenCaptureDeviceWithPersistentID(const String&);
+    static void screenCaptureDevices(Vector<CaptureDevice>&);
+
+private:
+    static void displayReconfigurationCallBack(CGDirectDisplayID, CGDisplayChangeSummaryFlags, void*);
+
+    // DisplayCaptureSourceCocoa::Capturer
+    bool start(float frameRate) final;
+    void stop() final;
+    DisplayCaptureSourceCocoa::DisplayFrameType generateFrame() final;
+    RealtimeMediaSourceSettings::DisplaySurfaceType surfaceType() const final { return RealtimeMediaSourceSettings::DisplaySurfaceType::Monitor; }
+    void commitConfiguration(float frameRate) final;
+    CaptureDevice::DeviceType deviceType() const final { return CaptureDevice::DeviceType::Screen; }
+#if !RELEASE_LOG_DISABLED
+    const char* logClassName() const final { return "ScreenDisplayCapturerMac"; }
+#endif
+
+    void displayWasReconfigured(CGDirectDisplayID, CGDisplayChangeSummaryFlags);
+    bool createDisplayStream(float frameRate);
+    bool startDisplayStream(float frameRate);
+
+    class DisplaySurface {
+    public:
+        DisplaySurface() = default;
+        explicit DisplaySurface(IOSurfaceRef surface)
+            : m_surface(surface)
+        {
+            if (m_surface)
+                IOSurfaceIncrementUseCount(m_surface.get());
+        }
+
+        ~DisplaySurface()
+        {
+            if (m_surface)
+                IOSurfaceDecrementUseCount(m_surface.get());
+        }
+
+        DisplaySurface& operator=(IOSurfaceRef surface)
+        {
+            if (m_surface)
+                IOSurfaceDecrementUseCount(m_surface.get());
+            if (surface)
+                IOSurfaceIncrementUseCount(surface);
+            m_surface = surface;
+            return *this;
+        }
+
+        IOSurfaceRef ioSurface() const { return m_surface.get(); }
+
+    private:
+        RetainPtr<IOSurfaceRef> m_surface;
+    };
+
+    void newFrame(CGDisplayStreamFrameStatus, DisplaySurface&&);
+
+    DisplaySurface m_currentFrame;
+    RetainPtr<CGDisplayStreamRef> m_displayStream;
+    OSObjectPtr<dispatch_queue_t> m_captureQueue;
+
+    uint32_t m_displayID { 0 };
+    bool m_isRunning { false };
+    bool m_observingDisplayChanges { false };
+};
+
+} // namespace WebCore
+
+#endif // ENABLE(MEDIA_STREAM) && PLATFORM(MAC)

Copied: trunk/Source/WebCore/platform/mediastream/mac/ScreenDisplayCapturerMac.mm (from rev 260560, trunk/Source/WebCore/platform/mediastream/mac/ScreenDisplayCaptureSourceMac.mm) (0 => 260561)


--- trunk/Source/WebCore/platform/mediastream/mac/ScreenDisplayCapturerMac.mm	                        (rev 0)
+++ trunk/Source/WebCore/platform/mediastream/mac/ScreenDisplayCapturerMac.mm	2020-04-23 08:59:31 UTC (rev 260561)
@@ -0,0 +1,326 @@
+/*
+ * Copyright (C) 2017-2019 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "ScreenDisplayCapturerMac.h"
+
+#if ENABLE(MEDIA_STREAM) && PLATFORM(MAC)
+
+#import "GraphicsContextCG.h"
+#import "ImageBuffer.h"
+#import "Logging.h"
+#import "MediaConstraints.h"
+#import "MediaSampleAVFObjC.h"
+#import "NotImplemented.h"
+#import "PlatformLayer.h"
+#import "PlatformScreen.h"
+#import "RealtimeMediaSourceSettings.h"
+#import "RealtimeVideoUtilities.h"
+
+#import "CoreVideoSoftLink.h"
+
+extern "C" {
+size_t CGDisplayModeGetPixelsWide(CGDisplayModeRef);
+size_t CGDisplayModeGetPixelsHigh(CGDisplayModeRef);
+}
+
+namespace WebCore {
+
+static Optional<CGDirectDisplayID> updateDisplayID(CGDirectDisplayID displayID)
+{
+    uint32_t displayCount = 0;
+    auto err = CGGetActiveDisplayList(0, nullptr, &displayCount);
+    if (err) {
+        RELEASE_LOG(WebRTC, "CGGetActiveDisplayList() returned error %d when trying to get display count", static_cast<int>(err));
+        return WTF::nullopt;
+    }
+
+    if (!displayCount) {
+        RELEASE_LOG(WebRTC, "CGGetActiveDisplayList() returned a display count of 0");
+        return WTF::nullopt;
+    }
+
+    Vector<CGDirectDisplayID> activeDisplays(displayCount);
+    err = CGGetActiveDisplayList(displayCount, activeDisplays.data(), &displayCount);
+    if (err) {
+        RELEASE_LOG(WebRTC, "CGGetActiveDisplayList() returned error %d when trying to get the active display list", static_cast<int>(err));
+        return WTF::nullopt;
+    }
+
+    auto displayMask = CGDisplayIDToOpenGLDisplayMask(displayID);
+    for (auto display : activeDisplays) {
+        if (displayMask == CGDisplayIDToOpenGLDisplayMask(display))
+            return display;
+    }
+
+    return WTF::nullopt;
+}
+
+Expected<UniqueRef<DisplayCaptureSourceCocoa::Capturer>, String> ScreenDisplayCapturerMac::create(const String& deviceID)
+{
+    bool ok;
+    auto displayID = deviceID.toUIntStrict(&ok);
+    if (!ok)
+        return makeUnexpected("Invalid display device ID"_s);
+
+    auto actualDisplayID = updateDisplayID(displayID);
+    if (!actualDisplayID)
+        return makeUnexpected("Invalid display ID"_s);
+
+    return UniqueRef<DisplayCaptureSourceCocoa::Capturer>(makeUniqueRef<ScreenDisplayCapturerMac>(actualDisplayID.value()));
+}
+
+ScreenDisplayCapturerMac::ScreenDisplayCapturerMac(uint32_t displayID)
+    : m_displayID(displayID)
+{
+}
+
+ScreenDisplayCapturerMac::~ScreenDisplayCapturerMac()
+{
+    if (m_observingDisplayChanges)
+        CGDisplayRemoveReconfigurationCallback(displayReconfigurationCallBack, this);
+
+    m_currentFrame = nullptr;
+}
+
+bool ScreenDisplayCapturerMac::createDisplayStream(float frameRate)
+{
+    static const int screenQueueMaximumLength = 6;
+
+    ALWAYS_LOG_IF(loggerPtr(), LOGIDENTIFIER);
+
+    auto actualDisplayID = updateDisplayID(m_displayID);
+    if (!actualDisplayID) {
+        ERROR_LOG_IF(loggerPtr(), LOGIDENTIFIER, "invalid display ID: ", m_displayID);
+        return false;
+    }
+
+    if (m_displayID != actualDisplayID.value()) {
+        m_displayID = actualDisplayID.value();
+        ALWAYS_LOG_IF(loggerPtr(), LOGIDENTIFIER, "display ID changed to ", static_cast<int>(m_displayID));
+        m_displayStream = nullptr;
+    }
+
+    if (!m_displayStream) {
+        auto displayMode = adoptCF(CGDisplayCopyDisplayMode(m_displayID));
+        auto screenWidth = CGDisplayModeGetPixelsWide(displayMode.get());
+        auto screenHeight = CGDisplayModeGetPixelsHigh(displayMode.get());
+        if (!screenWidth || !screenHeight) {
+            ERROR_LOG_IF(loggerPtr(), LOGIDENTIFIER, "unable to get screen width/height");
+            return false;
+        }
+
+        if (!m_captureQueue)
+            m_captureQueue = adoptOSObject(dispatch_queue_create("ScreenDisplayCapturerMac Capture Queue", DISPATCH_QUEUE_SERIAL));
+
+        NSDictionary* streamOptions = @{
+            (__bridge NSString *)kCGDisplayStreamMinimumFrameTime : @(1 / frameRate),
+            (__bridge NSString *)kCGDisplayStreamQueueDepth : @(screenQueueMaximumLength),
+            (__bridge NSString *)kCGDisplayStreamColorSpace : (__bridge id)sRGBColorSpaceRef(),
+            (__bridge NSString *)kCGDisplayStreamShowCursor : @YES,
+        };
+
+        auto weakThis = makeWeakPtr(*this);
+        auto frameAvailableBlock = ^(CGDisplayStreamFrameStatus status, uint64_t displayTime, IOSurfaceRef frameSurface, CGDisplayStreamUpdateRef updateRef) {
+
+            if (!frameSurface || !displayTime)
+                return;
+
+            size_t count;
+            auto* rects = CGDisplayStreamUpdateGetRects(updateRef, kCGDisplayStreamUpdateDirtyRects, &count);
+            if (!rects || !count)
+                return;
+
+            RunLoop::main().dispatch([weakThis, status, frame = DisplaySurface { frameSurface }]() mutable {
+                if (!weakThis)
+                    return;
+                weakThis->newFrame(status, WTFMove(frame));
+            });
+        };
+
+        m_displayStream = adoptCF(CGDisplayStreamCreateWithDispatchQueue(m_displayID, screenWidth, screenHeight, preferedPixelBufferFormat(), (__bridge CFDictionaryRef)streamOptions, m_captureQueue.get(), frameAvailableBlock));
+        if (!m_displayStream) {
+            ERROR_LOG_IF(loggerPtr(), LOGIDENTIFIER, "CGDisplayStreamCreate failed");
+            return false;
+        }
+    }
+
+    if (!m_observingDisplayChanges) {
+        CGDisplayRegisterReconfigurationCallback(displayReconfigurationCallBack, this);
+        m_observingDisplayChanges = true;
+    }
+
+    return true;
+}
+
+bool ScreenDisplayCapturerMac::start(float frameRate)
+{
+    ALWAYS_LOG_IF(loggerPtr(), LOGIDENTIFIER);
+
+    if (m_isRunning)
+        return true;
+
+    return startDisplayStream(frameRate);
+}
+
+void ScreenDisplayCapturerMac::stop()
+{
+    ALWAYS_LOG_IF(loggerPtr(), LOGIDENTIFIER);
+
+    if (!m_isRunning)
+        return;
+
+    if (m_displayStream)
+        CGDisplayStreamStop(m_displayStream.get());
+
+    m_isRunning = false;
+}
+
+DisplayCaptureSourceCocoa::DisplayFrameType ScreenDisplayCapturerMac::generateFrame()
+{
+    return DisplayCaptureSourceCocoa::DisplayFrameType { RetainPtr<IOSurfaceRef> { m_currentFrame.ioSurface() } };
+}
+
+bool ScreenDisplayCapturerMac::startDisplayStream(float frameRate)
+{
+    auto actualDisplayID = updateDisplayID(m_displayID);
+    if (!actualDisplayID)
+        return false;
+
+    if (m_displayID != actualDisplayID.value()) {
+        m_displayID = actualDisplayID.value();
+        ALWAYS_LOG_IF(loggerPtr(), LOGIDENTIFIER, "display ID changed to ", static_cast<int>(m_displayID));
+    }
+
+    if (!m_displayStream && !createDisplayStream(frameRate))
+        return false;
+
+    auto err = CGDisplayStreamStart(m_displayStream.get());
+    if (err) {
+        ERROR_LOG_IF(loggerPtr(), LOGIDENTIFIER, "CGDisplayStreamStart failed with error ", static_cast<int>(err));
+        return false;
+    }
+
+    m_isRunning = true;
+    return true;
+}
+
+void ScreenDisplayCapturerMac::commitConfiguration(float frameRate)
+{
+    if (m_isRunning && !m_displayStream)
+        startDisplayStream(frameRate);
+}
+
+void ScreenDisplayCapturerMac::displayWasReconfigured(CGDirectDisplayID, CGDisplayChangeSummaryFlags)
+{
+    // FIXME: implement!
+}
+
+void ScreenDisplayCapturerMac::displayReconfigurationCallBack(CGDirectDisplayID display, CGDisplayChangeSummaryFlags flags, void *userInfo)
+{
+    if (userInfo)
+        reinterpret_cast<ScreenDisplayCapturerMac *>(userInfo)->displayWasReconfigured(display, flags);
+}
+
+void ScreenDisplayCapturerMac::newFrame(CGDisplayStreamFrameStatus status, DisplaySurface&& newFrame)
+{
+    switch (status) {
+    case kCGDisplayStreamFrameStatusFrameComplete:
+        break;
+
+    case kCGDisplayStreamFrameStatusFrameIdle:
+        break;
+
+    case kCGDisplayStreamFrameStatusFrameBlank:
+        RELEASE_LOG(WebRTC, "ScreenDisplayCapturerMac::frameAvailable: kCGDisplayStreamFrameStatusFrameBlank");
+        break;
+
+    case kCGDisplayStreamFrameStatusStopped:
+        RELEASE_LOG(WebRTC, "ScreenDisplayCapturerMac::frameAvailable: kCGDisplayStreamFrameStatusStopped");
+        break;
+    }
+
+    m_currentFrame = WTFMove(newFrame);
+}
+
+Optional<CaptureDevice> ScreenDisplayCapturerMac::screenCaptureDeviceWithPersistentID(const String& deviceID)
+{
+    bool ok;
+    auto displayID = deviceID.toUIntStrict(&ok);
+    if (!ok) {
+        RELEASE_LOG(WebRTC, "ScreenDisplayCapturerMac::screenCaptureDeviceWithPersistentID: display ID does not convert to 32-bit integer");
+        return WTF::nullopt;
+    }
+
+    auto actualDisplayID = updateDisplayID(displayID);
+    if (!actualDisplayID)
+        return WTF::nullopt;
+
+    auto device = CaptureDevice(String::number(actualDisplayID.value()), CaptureDevice::DeviceType::Screen, "ScreenCaptureDevice"_s);
+    device.setEnabled(true);
+
+    return device;
+}
+
+void ScreenDisplayCapturerMac::screenCaptureDevices(Vector<CaptureDevice>& displays)
+{
+    auto screenID = displayID([NSScreen mainScreen]);
+    if (CGDisplayIDToOpenGLDisplayMask(screenID)) {
+        CaptureDevice displayDevice(String::number(screenID), CaptureDevice::DeviceType::Screen, makeString("Screen 0"));
+        displayDevice.setEnabled(true);
+        displays.append(WTFMove(displayDevice));
+        return;
+    }
+
+    uint32_t displayCount = 0;
+    auto err = CGGetActiveDisplayList(0, nullptr, &displayCount);
+    if (err) {
+        RELEASE_LOG(WebRTC, "CGGetActiveDisplayList() returned error %d when trying to get display count", (int)err);
+        return;
+    }
+
+    if (!displayCount) {
+        RELEASE_LOG(WebRTC, "CGGetActiveDisplayList() returned a display count of 0");
+        return;
+    }
+
+    Vector<CGDirectDisplayID> activeDisplays(displayCount);
+    err = CGGetActiveDisplayList(displayCount, activeDisplays.data(), &displayCount);
+    if (err) {
+        RELEASE_LOG(WebRTC, "CGGetActiveDisplayList() returned error %d when trying to get the active display list", (int)err);
+        return;
+    }
+
+    int count = 0;
+    for (auto displayID : activeDisplays) {
+        CaptureDevice displayDevice(String::number(displayID), CaptureDevice::DeviceType::Screen, makeString("Screen ", String::number(count++)));
+        displayDevice.setEnabled(CGDisplayIDToOpenGLDisplayMask(displayID));
+        displays.append(WTFMove(displayDevice));
+    }
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(MEDIA_STREAM) && PLATFORM(MAC)

Deleted: trunk/Source/WebCore/platform/mediastream/mac/WindowDisplayCaptureSourceMac.h (260560 => 260561)


--- trunk/Source/WebCore/platform/mediastream/mac/WindowDisplayCaptureSourceMac.h	2020-04-23 08:47:37 UTC (rev 260560)
+++ trunk/Source/WebCore/platform/mediastream/mac/WindowDisplayCaptureSourceMac.h	2020-04-23 08:59:31 UTC (rev 260561)
@@ -1,68 +0,0 @@
-/*
- * Copyright (C) 2018 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#pragma once
-
-#if ENABLE(MEDIA_STREAM) && PLATFORM(MAC)
-
-#include "DisplayCaptureSourceCocoa.h"
-
-typedef struct __CVBuffer *CVBufferRef;
-typedef CVBufferRef CVImageBufferRef;
-typedef CVImageBufferRef CVPixelBufferRef;
-typedef struct __CVPixelBufferPool *CVPixelBufferPoolRef;
-
-namespace WebCore {
-
-class PixelBufferConformerCV;
-
-class WindowDisplayCaptureSourceMac : public DisplayCaptureSourceCocoa {
-public:
-    static CaptureSourceOrError create(String&&, const MediaConstraints*);
-
-    static Optional<CaptureDevice> windowCaptureDeviceWithPersistentID(const String&);
-    static void windowCaptureDevices(Vector<CaptureDevice>&);
-
-private:
-    WindowDisplayCaptureSourceMac(uint32_t, String&&);
-    virtual ~WindowDisplayCaptureSourceMac() = default;
-
-    DisplayCaptureSourceCocoa::DisplayFrameType generateFrame() final;
-    RealtimeMediaSourceSettings::DisplaySurfaceType surfaceType() const final { return RealtimeMediaSourceSettings::DisplaySurfaceType::Window; }
-    CaptureDevice::DeviceType deviceType() const final { return CaptureDevice::DeviceType::Window; }
-
-    RetainPtr<CGImageRef> windowImage();
-
-    IntSize m_windowSize;
-    CGWindowID m_windowID { 0 };
-    RetainPtr<CVPixelBufferPoolRef> m_bufferPool;
-    std::unique_ptr<PixelBufferConformerCV> m_pixelBufferConformer;
-    RetainPtr<CGImageRef> m_lastImage;
-    RetainPtr<CVPixelBufferRef> m_lastPixelBuffer;
-};
-
-} // namespace WebCore
-
-#endif // ENABLE(MEDIA_STREAM) && PLATFORM(MAC)

Deleted: trunk/Source/WebCore/platform/mediastream/mac/WindowDisplayCaptureSourceMac.mm (260560 => 260561)


--- trunk/Source/WebCore/platform/mediastream/mac/WindowDisplayCaptureSourceMac.mm	2020-04-23 08:47:37 UTC (rev 260560)
+++ trunk/Source/WebCore/platform/mediastream/mac/WindowDisplayCaptureSourceMac.mm	2020-04-23 08:59:31 UTC (rev 260561)
@@ -1,187 +0,0 @@
-/*
- * Copyright (C) 2018 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#import "config.h"
-#import "WindowDisplayCaptureSourceMac.h"
-
-#if ENABLE(MEDIA_STREAM) && PLATFORM(MAC)
-
-#import "GraphicsContextCG.h"
-#import "ImageBuffer.h"
-#import "Logging.h"
-#import "MediaConstraints.h"
-#import "MediaSampleAVFObjC.h"
-#import "NotImplemented.h"
-#import "PixelBufferConformerCV.h"
-#import "PlatformLayer.h"
-#import "RealtimeMediaSourceSettings.h"
-#import <pal/cf/CoreMediaSoftLink.h>
-#import <pal/spi/cg/CoreGraphicsSPI.h>
-#import <wtf/cf/TypeCastsCF.h>
-
-#import "CoreVideoSoftLink.h"
-
-WTF_DECLARE_CF_TYPE_TRAIT(CGImage);
-
-namespace WebCore {
-using namespace PAL;
-
-static bool anyOfCGWindow(const Function<bool(CFDictionaryRef info, unsigned id, const String& title)>& predicate)
-{
-    auto windows = adoptCF(CGWindowListCopyWindowInfo(kCGWindowListOptionOnScreenOnly | kCGWindowListExcludeDesktopElements, kCGNullWindowID));
-    if (!windows) {
-        RELEASE_LOG(Media, "CGWindowListCopyWindowInfo returned NULL");
-        return false;
-    }
-
-    auto windowCount = CFArrayGetCount(windows.get());
-    for (auto i = 0; i < windowCount; i++) {
-        auto windowInfo = checked_cf_cast<CFDictionaryRef>(CFArrayGetValueAtIndex(windows.get(), i));
-        if (!windowInfo)
-            continue;
-
-        // Menus, the dock, etc have layers greater than 0, skip them.
-        auto windowLayerRef = checked_cf_cast<CFNumberRef>(CFDictionaryGetValue(windowInfo, kCGWindowLayer));
-        if (!windowLayerRef)
-            continue;
-        unsigned windowLayer;
-        CFNumberGetValue(windowLayerRef, kCFNumberIntType, &windowLayer);
-        if (windowLayer)
-            continue;
-
-        auto _onScreen_ = checked_cf_cast<CFBooleanRef>(CFDictionaryGetValue(windowInfo, kCGWindowIsOnscreen));
-        if (!CFBooleanGetValue(onScreen))
-            continue;
-
-        auto windowIDRef = checked_cf_cast<CFNumberRef>(CFDictionaryGetValue(windowInfo, kCGWindowNumber));
-        if (!windowIDRef)
-            continue;
-        unsigned windowID;
-        CFNumberGetValue(windowIDRef, kCFNumberIntType, &windowID);
-        if (!windowID)
-            continue;
-
-        auto windowTitle = checked_cf_cast<CFStringRef>(CFDictionaryGetValue(windowInfo, kCGWindowName));
-
-        if (predicate(windowInfo, windowID, windowTitle))
-            return true;
-    }
-
-    return false;
-}
-
-static RetainPtr<CFDictionaryRef> windowDescription(CGWindowID id)
-{
-    auto ids = adoptCF(CFArrayCreate(nullptr, reinterpret_cast<const void**>(&id), 1, nullptr));
-    auto windows = adoptCF(CGWindowListCreateDescriptionFromArray(ids.get()));
-    if (!windows)
-        return nullptr;
-
-    return checked_cf_cast<CFDictionaryRef>(CFArrayGetValueAtIndex(windows.get(), 0));
-}
-
-CaptureSourceOrError WindowDisplayCaptureSourceMac::create(String&& windowID, const MediaConstraints* constraints)
-{
-    bool ok;
-    auto actualID = windowID.toUIntStrict(&ok);
-    if (!ok) {
-        RELEASE_LOG(Media, "WindowDisplayCaptureSourceMac::create: window ID does not convert to 32-bit integer");
-        return { };
-    }
-
-    auto windowInfo = windowDescription(actualID);
-    if (!windowInfo) {
-        RELEASE_LOG(Media, "WindowDisplayCaptureSourceMac::create: invalid window ID");
-        return { };
-    }
-
-    auto source = adoptRef(*new WindowDisplayCaptureSourceMac(actualID, checked_cf_cast<CFStringRef>(CFDictionaryGetValue(windowInfo.get(), kCGWindowName))));
-    if (constraints && source->applyConstraints(*constraints))
-        return { };
-
-    return CaptureSourceOrError(WTFMove(source));
-}
-
-WindowDisplayCaptureSourceMac::WindowDisplayCaptureSourceMac(uint32_t windowID, String&& title)
-    : DisplayCaptureSourceCocoa(WTFMove(title))
-    , m_windowID(windowID)
-{
-}
-
-RetainPtr<CGImageRef> WindowDisplayCaptureSourceMac::windowImage()
-{
-    auto image = adoptCF(CGWindowListCreateImage(CGRectNull, kCGWindowListOptionIncludingWindow, m_windowID, kCGWindowImageBoundsIgnoreFraming | kCGWindowImageShouldBeOpaque));
-    if (!image)
-        RELEASE_LOG(Media, "WindowDisplayCaptureSourceMac::windowImage: failed to capture window image");
-
-    return image;
-}
-
-DisplayCaptureSourceCocoa::DisplayFrameType WindowDisplayCaptureSourceMac::generateFrame()
-{
-    return DisplayCaptureSourceCocoa::DisplayFrameType { RetainPtr<CGImageRef> { windowImage() } };
-}
-
-Optional<CaptureDevice> WindowDisplayCaptureSourceMac::windowCaptureDeviceWithPersistentID(const String& idString)
-{
-    bool ok;
-    auto windowID = idString.toUIntStrict(&ok);
-    if (!ok) {
-        RELEASE_LOG(Media, "WindowDisplayCaptureSourceMac::windowCaptureDeviceWithPersistentID: window ID does not convert to 32-bit integer");
-        return WTF::nullopt;
-    }
-
-    String windowTitle;
-    if (!anyOfCGWindow([&windowTitle, windowID] (CFDictionaryRef, CGWindowID id, const String& title) {
-        if (windowID != id)
-            return false;
-
-        windowTitle = title;
-        return true;
-
-    })) {
-        RELEASE_LOG(Media, "WindowDisplayCaptureSourceMac::windowCaptureDeviceWithPersistentID: window ID is not valid");
-        return WTF::nullopt;
-    }
-
-    auto device = CaptureDevice(String::number(windowID), CaptureDevice::DeviceType::Window, windowTitle);
-    device.setEnabled(true);
-
-    return device;
-}
-
-void WindowDisplayCaptureSourceMac::windowCaptureDevices(Vector<CaptureDevice>& windows)
-{
-    anyOfCGWindow([&] (CFDictionaryRef, int id, const String& title) mutable {
-        CaptureDevice device(String::number(id), CaptureDevice::DeviceType::Window, title);
-        device.setEnabled(true);
-        windows.append(WTFMove(device));
-        return false;
-    });
-}
-
-} // namespace WebCore
-
-#endif // ENABLE(MEDIA_STREAM) && PLATFORM(MAC)

Copied: trunk/Source/WebCore/platform/mediastream/mac/WindowDisplayCapturerMac.h (from rev 260560, trunk/Source/WebCore/platform/mediastream/mac/WindowDisplayCaptureSourceMac.h) (0 => 260561)


--- trunk/Source/WebCore/platform/mediastream/mac/WindowDisplayCapturerMac.h	                        (rev 0)
+++ trunk/Source/WebCore/platform/mediastream/mac/WindowDisplayCapturerMac.h	2020-04-23 08:59:31 UTC (rev 260561)
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2018 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#if ENABLE(MEDIA_STREAM) && PLATFORM(MAC)
+
+#include "DisplayCaptureSourceCocoa.h"
+
+typedef struct __CVBuffer *CVBufferRef;
+typedef CVBufferRef CVImageBufferRef;
+typedef CVImageBufferRef CVPixelBufferRef;
+typedef struct __CVPixelBufferPool *CVPixelBufferPoolRef;
+
+namespace WebCore {
+
+class PixelBufferConformerCV;
+
+class WindowDisplayCapturerMac final : public DisplayCaptureSourceCocoa::Capturer {
+public:
+    static Expected<UniqueRef<DisplayCaptureSourceCocoa::Capturer>, String> create(const String&);
+
+    explicit WindowDisplayCapturerMac(uint32_t);
+    virtual ~WindowDisplayCapturerMac() = default;
+
+    static Optional<CaptureDevice> windowCaptureDeviceWithPersistentID(const String&);
+    static void windowCaptureDevices(Vector<CaptureDevice>&);
+
+private:
+    // DisplayCaptureSourceCocoa::Capturer
+    bool start(float) final { return true; }
+    void stop() final { }
+    DisplayCaptureSourceCocoa::DisplayFrameType generateFrame() final;
+    RealtimeMediaSourceSettings::DisplaySurfaceType surfaceType() const final { return RealtimeMediaSourceSettings::DisplaySurfaceType::Window; }
+    CaptureDevice::DeviceType deviceType() const final { return CaptureDevice::DeviceType::Window; }
+    void commitConfiguration(float) final { }
+#if !RELEASE_LOG_DISABLED
+    const char* logClassName() const final { return "WindowDisplayCapturerMac"; }
+#endif
+
+    RetainPtr<CGImageRef> windowImage();
+
+    IntSize m_windowSize;
+    CGWindowID m_windowID { 0 };
+    RetainPtr<CVPixelBufferPoolRef> m_bufferPool;
+    std::unique_ptr<PixelBufferConformerCV> m_pixelBufferConformer;
+    RetainPtr<CGImageRef> m_lastImage;
+    RetainPtr<CVPixelBufferRef> m_lastPixelBuffer;
+};
+
+} // namespace WebCore
+
+#endif // ENABLE(MEDIA_STREAM) && PLATFORM(MAC)

Copied: trunk/Source/WebCore/platform/mediastream/mac/WindowDisplayCapturerMac.mm (from rev 260560, trunk/Source/WebCore/platform/mediastream/mac/WindowDisplayCaptureSourceMac.mm) (0 => 260561)


--- trunk/Source/WebCore/platform/mediastream/mac/WindowDisplayCapturerMac.mm	                        (rev 0)
+++ trunk/Source/WebCore/platform/mediastream/mac/WindowDisplayCapturerMac.mm	2020-04-23 08:59:31 UTC (rev 260561)
@@ -0,0 +1,178 @@
+/*
+ * Copyright (C) 2018 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#import "config.h"
+#import "WindowDisplayCapturerMac.h"
+
+#if ENABLE(MEDIA_STREAM) && PLATFORM(MAC)
+
+#import "GraphicsContextCG.h"
+#import "ImageBuffer.h"
+#import "Logging.h"
+#import "MediaConstraints.h"
+#import "MediaSampleAVFObjC.h"
+#import "NotImplemented.h"
+#import "PixelBufferConformerCV.h"
+#import "PlatformLayer.h"
+#import "RealtimeMediaSourceSettings.h"
+#import <pal/spi/cg/CoreGraphicsSPI.h>
+#import <wtf/cf/TypeCastsCF.h>
+
+#import <pal/cf/CoreMediaSoftLink.h>
+#import "CoreVideoSoftLink.h"
+
+WTF_DECLARE_CF_TYPE_TRAIT(CGImage);
+
+namespace WebCore {
+using namespace PAL;
+
+static bool anyOfCGWindow(const Function<bool(CFDictionaryRef info, unsigned id, const String& title)>& predicate)
+{
+    auto windows = adoptCF(CGWindowListCopyWindowInfo(kCGWindowListOptionOnScreenOnly | kCGWindowListExcludeDesktopElements, kCGNullWindowID));
+    if (!windows) {
+        RELEASE_LOG(WebRTC, "CGWindowListCopyWindowInfo returned NULL");
+        return false;
+    }
+
+    auto windowCount = CFArrayGetCount(windows.get());
+    for (auto i = 0; i < windowCount; i++) {
+        auto windowInfo = checked_cf_cast<CFDictionaryRef>(CFArrayGetValueAtIndex(windows.get(), i));
+        if (!windowInfo)
+            continue;
+
+        // Menus, the dock, etc have layers greater than 0, skip them.
+        auto windowLayerRef = checked_cf_cast<CFNumberRef>(CFDictionaryGetValue(windowInfo, kCGWindowLayer));
+        if (!windowLayerRef)
+            continue;
+        unsigned windowLayer;
+        CFNumberGetValue(windowLayerRef, kCFNumberIntType, &windowLayer);
+        if (windowLayer)
+            continue;
+
+        auto _onScreen_ = checked_cf_cast<CFBooleanRef>(CFDictionaryGetValue(windowInfo, kCGWindowIsOnscreen));
+        if (!CFBooleanGetValue(onScreen))
+            continue;
+
+        auto windowIDRef = checked_cf_cast<CFNumberRef>(CFDictionaryGetValue(windowInfo, kCGWindowNumber));
+        if (!windowIDRef)
+            continue;
+        unsigned windowID;
+        CFNumberGetValue(windowIDRef, kCFNumberIntType, &windowID);
+        if (!windowID)
+            continue;
+
+        auto windowTitle = checked_cf_cast<CFStringRef>(CFDictionaryGetValue(windowInfo, kCGWindowName));
+
+        if (predicate(windowInfo, windowID, windowTitle))
+            return true;
+    }
+
+    return false;
+}
+
+static RetainPtr<CFDictionaryRef> windowDescription(CGWindowID id)
+{
+    auto ids = adoptCF(CFArrayCreate(nullptr, reinterpret_cast<const void**>(&id), 1, nullptr));
+    auto windows = adoptCF(CGWindowListCreateDescriptionFromArray(ids.get()));
+    if (!windows)
+        return nullptr;
+
+    return checked_cf_cast<CFDictionaryRef>(CFArrayGetValueAtIndex(windows.get(), 0));
+}
+
+Expected<UniqueRef<DisplayCaptureSourceCocoa::Capturer>, String> WindowDisplayCapturerMac::create(const String& deviceID)
+{
+    bool ok;
+    auto displayID = deviceID.toUIntStrict(&ok);
+    if (!ok)
+        return makeUnexpected("Invalid window device ID"_s);
+
+    auto windowInfo = windowDescription(displayID);
+    if (!windowInfo)
+        return makeUnexpected("Invalid window ID"_s);
+
+    return UniqueRef<DisplayCaptureSourceCocoa::Capturer>(makeUniqueRef<WindowDisplayCapturerMac>(displayID));
+}
+
+WindowDisplayCapturerMac::WindowDisplayCapturerMac(uint32_t windowID)
+    : m_windowID(windowID)
+{
+}
+
+RetainPtr<CGImageRef> WindowDisplayCapturerMac::windowImage()
+{
+    auto image = adoptCF(CGWindowListCreateImage(CGRectNull, kCGWindowListOptionIncludingWindow, m_windowID, kCGWindowImageBoundsIgnoreFraming | kCGWindowImageShouldBeOpaque));
+    if (!image)
+        RELEASE_LOG(WebRTC, "WindowDisplayCapturerMac::windowImage: failed to capture window image");
+
+    return image;
+}
+
+DisplayCaptureSourceCocoa::DisplayFrameType WindowDisplayCapturerMac::generateFrame()
+{
+    return DisplayCaptureSourceCocoa::DisplayFrameType { RetainPtr<CGImageRef> { windowImage() } };
+}
+
+Optional<CaptureDevice> WindowDisplayCapturerMac::windowCaptureDeviceWithPersistentID(const String& idString)
+{
+    bool ok;
+    auto windowID = idString.toUIntStrict(&ok);
+    if (!ok) {
+        RELEASE_LOG(WebRTC, "WindowDisplayCapturerMac::windowCaptureDeviceWithPersistentID: window ID does not convert to 32-bit integer");
+        return WTF::nullopt;
+    }
+
+    String windowTitle;
+    if (!anyOfCGWindow([&windowTitle, windowID] (CFDictionaryRef, CGWindowID id, const String& title) {
+        if (windowID != id)
+            return false;
+
+        windowTitle = title;
+        return true;
+
+    })) {
+        RELEASE_LOG(WebRTC, "WindowDisplayCapturerMac::windowCaptureDeviceWithPersistentID: window ID is not valid");
+        return WTF::nullopt;
+    }
+
+    auto device = CaptureDevice(String::number(windowID), CaptureDevice::DeviceType::Window, windowTitle);
+    device.setEnabled(true);
+
+    return device;
+}
+
+void WindowDisplayCapturerMac::windowCaptureDevices(Vector<CaptureDevice>& windows)
+{
+    anyOfCGWindow([&] (CFDictionaryRef, int id, const String& title) mutable {
+        CaptureDevice device(String::number(id), CaptureDevice::DeviceType::Window, title);
+        device.setEnabled(true);
+        windows.append(WTFMove(device));
+        return false;
+    });
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(MEDIA_STREAM) && PLATFORM(MAC)

Modified: trunk/Source/WebCore/platform/mock/MockRealtimeMediaSourceCenter.cpp (260560 => 260561)


--- trunk/Source/WebCore/platform/mock/MockRealtimeMediaSourceCenter.cpp	2020-04-23 08:47:37 UTC (rev 260560)
+++ trunk/Source/WebCore/platform/mock/MockRealtimeMediaSourceCenter.cpp	2020-04-23 08:59:31 UTC (rev 260561)
@@ -43,6 +43,8 @@
 
 #if PLATFORM(COCOA)
 #include "CoreAudioCaptureSource.h"
+#include "DisplayCaptureSourceCocoa.h"
+#include "MockRealtimeVideoSourceMac.h"
 #endif
 
 namespace WebCore {
@@ -110,17 +112,59 @@
     CaptureDeviceManager& videoCaptureDeviceManager() final { return MockRealtimeMediaSourceCenter::singleton().videoCaptureDeviceManager(); }
 };
 
+#if PLATFORM(MAC)
+class MockDisplayCapturer final : public DisplayCaptureSourceCocoa::Capturer {
+public:
+    explicit MockDisplayCapturer(const CaptureDevice&);
+
+private:
+    bool start(float) final;
+    void stop() final  { m_source->stop(); }
+    DisplayCaptureSourceCocoa::DisplayFrameType generateFrame() final;
+    RealtimeMediaSourceSettings::DisplaySurfaceType surfaceType() const final { return RealtimeMediaSourceSettings::DisplaySurfaceType::Monitor; }
+    void commitConfiguration(float) final { }
+    CaptureDevice::DeviceType deviceType() const final { return CaptureDevice::DeviceType::Screen; }
+#if !RELEASE_LOG_DISABLED
+    const char* logClassName() const final { return "MockDisplayCapturer"; }
+#endif
+    
+    Ref<MockRealtimeVideoSource> m_source;
+};
+
+MockDisplayCapturer::MockDisplayCapturer(const CaptureDevice& device)
+    : m_source(MockRealtimeVideoSourceMac::createForMockDisplayCapturer(String { device.persistentId() }, String { device.label() }, String { }))
+{
+}
+
+bool MockDisplayCapturer::start(float)
+{
+    m_source->start();
+    return true;
+}
+
+DisplayCaptureSourceCocoa::DisplayFrameType MockDisplayCapturer::generateFrame()
+{
+    if (auto* imageBuffer = m_source->imageBuffer())
+        return imageBuffer->copyNativeImage();
+    return { };
+}
+#endif
+
 class MockRealtimeDisplaySourceFactory : public DisplayCaptureFactory {
 public:
     CaptureSourceOrError createDisplayCaptureSource(const CaptureDevice& device, const MediaConstraints* constraints) final
     {
         if (!MockRealtimeMediaSourceCenter::captureDeviceWithPersistentID(device.type(), device.persistentId()))
-            return { "Unable to find mock  display device with given persistentID"_s };
+            return { "Unable to find mock display device with given persistentID"_s };
 
         switch (device.type()) {
         case CaptureDevice::DeviceType::Screen:
         case CaptureDevice::DeviceType::Window:
+#if PLATFORM(MAC)
+            return DisplayCaptureSourceCocoa::create(UniqueRef<DisplayCaptureSourceCocoa::Capturer>(makeUniqueRef<MockDisplayCapturer>(device)), device, constraints);
+#else
             return MockRealtimeVideoSource::create(String { device.persistentId() }, String { device.label() }, String { }, constraints);
+#endif
             break;
         case CaptureDevice::DeviceType::Microphone:
         case CaptureDevice::DeviceType::Camera:

Modified: trunk/Source/WebCore/platform/mock/MockRealtimeVideoSource.h (260560 => 260561)


--- trunk/Source/WebCore/platform/mock/MockRealtimeVideoSource.h	2020-04-23 08:47:37 UTC (rev 260560)
+++ trunk/Source/WebCore/platform/mock/MockRealtimeVideoSource.h	2020-04-23 08:59:31 UTC (rev 260561)
@@ -48,9 +48,10 @@
 
 class MockRealtimeVideoSource : public RealtimeVideoCaptureSource, private OrientationNotifier::Observer {
 public:
-
     static CaptureSourceOrError create(String&& deviceID, String&& name, String&& hashSalt, const MediaConstraints*);
 
+    ImageBuffer* imageBuffer() const;
+
 protected:
     MockRealtimeVideoSource(String&& deviceID, String&& name, String&& hashSalt);
 
@@ -57,7 +58,6 @@
     virtual void updateSampleBuffer() = 0;
 
     void setCurrentFrame(MediaSample&);
-    ImageBuffer* imageBuffer() const;
 
     Seconds elapsedTime();
     void settingsDidChange(OptionSet<RealtimeMediaSourceSettings::Flag>) override;
@@ -125,6 +125,10 @@
 
 } // namespace WebCore
 
+SPECIALIZE_TYPE_TRAITS_BEGIN(WebCore::MockRealtimeVideoSource)
+    static bool isType(const WebCore::RealtimeMediaSource& source) { return source.isCaptureSource() && source.isMockSource() && (source.deviceType() == WebCore::CaptureDevice::DeviceType::Camera || source.deviceType() == WebCore::CaptureDevice::DeviceType::Screen || source.deviceType() == WebCore::CaptureDevice::DeviceType::Window); }
+SPECIALIZE_TYPE_TRAITS_END()
+
 #endif // ENABLE(MEDIA_STREAM)
 
 #endif // MockRealtimeVideoSource_h
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to