Title: [271841] branches/safari-611-branch
Revision
271841
Author
[email protected]
Date
2021-01-25 14:12:26 -0800 (Mon, 25 Jan 2021)

Log Message

Cherry-pick r271471. rdar://problem/73477068

    Source/WebCore:
    [HANG] 496ms to 1360ms in WebCore::AVAudioSessionCaptureDeviceManager::refreshAudioCaptureDevices()
    https://bugs.webkit.org/show_bug.cgi?id=220471

    Reviewed by Youenn Fablet.

    Refactor RealtimeMediaSourceCenter::getMediaStreamDevices() to take a completion handler, rather than
    synchronously return a Vector of CaptureDevices. This also requires all CaptureDeviceManager subclasses
    to support taking a completion handler themselves. By default, all CaptureDeviceManagers will support
    the CompletionHandler path by just synchronously calling the completion handler with the existing
    synchronous method. But for AVAudioSessionCaptureDeviceManager, override that default implementation by
    activating the AVAudioSession on a background thread, and querying that session's inputs on a background
    thread as well.

    * platform/mediastream/CaptureDeviceManager.h:
    * platform/mediastream/RealtimeMediaSourceCenter.cpp:
    (WebCore::RealtimeMediaSourceCenter::getMediaStreamDevices):
    * platform/mediastream/RealtimeMediaSourceCenter.h:
    * platform/mediastream/RealtimeMediaSourceFactory.h:
    (WebCore::AudioCaptureFactory::getSpeakerDevices const):
    * platform/mediastream/ios/AVAudioSessionCaptureDeviceManager.h:
    * platform/mediastream/ios/AVAudioSessionCaptureDeviceManager.mm:
    (WebCore::AVAudioSessionCaptureDeviceManager::audioSessionDeviceWithUID):
    (WebCore::AVAudioSessionCaptureDeviceManager::scheduleUpdateCaptureDevices):
    (WebCore::AVAudioSessionCaptureDeviceManager::refreshAudioCaptureDevices):
    (WebCore::AVAudioSessionCaptureDeviceManager::getCaptureDevices):
    (WebCore::AVAudioSessionCaptureDeviceManager::activateAudioSession):
    (WebCore::AVAudioSessionCaptureDeviceManager::retrieveAudioSessionCaptureDevices const):
    (WebCore::AVAudioSessionCaptureDeviceManager::setAudioCaptureDevices):
    (WebCore::AVAudioSessionCaptureDeviceManager::audioSessionCaptureDevices): Deleted.

    Source/WebKit:
    [HANG] 496ms to 1360ms in WebCore::AVAudioSessionCaptureDeviceManager::refreshAudioCaptureDevices()
    https://bugs.webkit.org/show_bug.cgi?id=220471

    Reviewed by Youenn Fablet.

    Use the completion-handler version of RealtimeMediaSourceCenter::getMediaStreamDevices().

    * UIProcess/UserMediaPermissionRequestManagerProxy.cpp:
    (WebKit::UserMediaPermissionRequestManagerProxy::computeFilteredDeviceList):
    (WebKit::UserMediaPermissionRequestManagerProxy::enumerateMediaDevicesForFrame):
    * UIProcess/UserMediaPermissionRequestManagerProxy.h:
    * UIProcess/UserMediaProcessManager.cpp:
    (WebKit::UserMediaProcessManager::updateCaptureDevices):
    (WebKit::UserMediaProcessManager::beginMonitoringCaptureDevices):
    * UIProcess/UserMediaProcessManager.h:

    LayoutTests:
    [Cocoa] Support key rotation with HLS-backed encrypted media streams
    https://bugs.webkit.org/show_bug.cgi?id=220493
    <rdar://68227709>

    Reviewed by Youenn Fablet.

    Fix a broken layout test; the test enumerates devices, then uses the deviceIds returned to generate
    constraints for a call to getUserMedia(). However, it assumes all devices will either be of kind
    'audioinput' or 'videoinput'. If an 'audiooutput' device is returned (as the MockRealtimeMediaSourceCenter
    does), then the test turns that into a video capture constraint, which fails.

    * fast/mediastream/get-user-media-device-id.html:

    git-svn-id: https://svn.webkit.org/repository/webkit/trunk@271471 268f45cc-cd09-0410-ab3c-d52691b4dbfc

Modified Paths

Diff

Modified: branches/safari-611-branch/LayoutTests/ChangeLog (271840 => 271841)


--- branches/safari-611-branch/LayoutTests/ChangeLog	2021-01-25 22:12:20 UTC (rev 271840)
+++ branches/safari-611-branch/LayoutTests/ChangeLog	2021-01-25 22:12:26 UTC (rev 271841)
@@ -1,5 +1,89 @@
 2021-01-25  Alan Coon  <[email protected]>
 
+        Cherry-pick r271471. rdar://problem/73477068
+
+    Source/WebCore:
+    [HANG] 496ms to 1360ms in WebCore::AVAudioSessionCaptureDeviceManager::refreshAudioCaptureDevices()
+    https://bugs.webkit.org/show_bug.cgi?id=220471
+    
+    Reviewed by Youenn Fablet.
+    
+    Refactor RealtimeMediaSourceCenter::getMediaStreamDevices() to take a completion handler, rather than
+    synchronously return a Vector of CaptureDevices. This also requires all CaptureDeviceManager subclasses
+    to support taking a completion handler themselves. By default, all CaptureDeviceManagers will support
+    the CompletionHandler path by just synchronously calling the completion handler with the existing
+    synchronous method. But for AVAudioSessionCaptureDeviceManager, override that default implementation by
+    activating the AVAudioSession on a background thread, and querying that session's inputs on a background
+    thread as well.
+    
+    * platform/mediastream/CaptureDeviceManager.h:
+    * platform/mediastream/RealtimeMediaSourceCenter.cpp:
+    (WebCore::RealtimeMediaSourceCenter::getMediaStreamDevices):
+    * platform/mediastream/RealtimeMediaSourceCenter.h:
+    * platform/mediastream/RealtimeMediaSourceFactory.h:
+    (WebCore::AudioCaptureFactory::getSpeakerDevices const):
+    * platform/mediastream/ios/AVAudioSessionCaptureDeviceManager.h:
+    * platform/mediastream/ios/AVAudioSessionCaptureDeviceManager.mm:
+    (WebCore::AVAudioSessionCaptureDeviceManager::audioSessionDeviceWithUID):
+    (WebCore::AVAudioSessionCaptureDeviceManager::scheduleUpdateCaptureDevices):
+    (WebCore::AVAudioSessionCaptureDeviceManager::refreshAudioCaptureDevices):
+    (WebCore::AVAudioSessionCaptureDeviceManager::getCaptureDevices):
+    (WebCore::AVAudioSessionCaptureDeviceManager::activateAudioSession):
+    (WebCore::AVAudioSessionCaptureDeviceManager::retrieveAudioSessionCaptureDevices const):
+    (WebCore::AVAudioSessionCaptureDeviceManager::setAudioCaptureDevices):
+    (WebCore::AVAudioSessionCaptureDeviceManager::audioSessionCaptureDevices): Deleted.
+    
+    Source/WebKit:
+    [HANG] 496ms to 1360ms in WebCore::AVAudioSessionCaptureDeviceManager::refreshAudioCaptureDevices()
+    https://bugs.webkit.org/show_bug.cgi?id=220471
+    
+    Reviewed by Youenn Fablet.
+    
+    Use the completion-handler version of RealtimeMediaSourceCenter::getMediaStreamDevices().
+    
+    * UIProcess/UserMediaPermissionRequestManagerProxy.cpp:
+    (WebKit::UserMediaPermissionRequestManagerProxy::computeFilteredDeviceList):
+    (WebKit::UserMediaPermissionRequestManagerProxy::enumerateMediaDevicesForFrame):
+    * UIProcess/UserMediaPermissionRequestManagerProxy.h:
+    * UIProcess/UserMediaProcessManager.cpp:
+    (WebKit::UserMediaProcessManager::updateCaptureDevices):
+    (WebKit::UserMediaProcessManager::beginMonitoringCaptureDevices):
+    * UIProcess/UserMediaProcessManager.h:
+    
+    LayoutTests:
+    [Cocoa] Support key rotation with HLS-backed encrypted media streams
+    https://bugs.webkit.org/show_bug.cgi?id=220493
+    <rdar://68227709>
+    
+    Reviewed by Youenn Fablet.
+    
+    Fix a broken layout test; the test enumerates devices, then uses the deviceIds returned to generate
+    constraints for a call to getUserMedia(). However, it assumes all devices will either be of kind
+    'audioinput' or 'videoinput'. If an 'audiooutput' device is returned (as the MockRealtimeMediaSourceCenter
+    does), then the test turns that into a video capture constraint, which fails.
+    
+    * fast/mediastream/get-user-media-device-id.html:
+    
+    
+    git-svn-id: https://svn.webkit.org/repository/webkit/trunk@271471 268f45cc-cd09-0410-ab3c-d52691b4dbfc
+
+    2021-01-13  Jer Noble  <[email protected]>
+
+            [Cocoa] Support key rotation with HLS-backed encrypted media streams
+            https://bugs.webkit.org/show_bug.cgi?id=220493
+            <rdar://68227709>
+
+            Reviewed by Youenn Fablet.
+
+            Fix a broken layout test; the test enumerates devices, then uses the deviceIds returned to generate
+            constraints for a call to getUserMedia(). However, it assumes all devices will either be of kind
+            'audioinput' or 'videoinput'. If an 'audiooutput' device is returned (as the MockRealtimeMediaSourceCenter
+            does), then the test turns that into a video capture constraint, which fails.
+
+            * fast/mediastream/get-user-media-device-id.html:
+
+2021-01-25  Alan Coon  <[email protected]>
+
         Cherry-pick r271453. rdar://problem/73477471
 
     Fix for LayoutTests/accessibility/mac/details-summary.html in isolated tree mode.

Modified: branches/safari-611-branch/LayoutTests/fast/mediastream/get-user-media-device-id.html (271840 => 271841)


--- branches/safari-611-branch/LayoutTests/fast/mediastream/get-user-media-device-id.html	2021-01-25 22:12:20 UTC (rev 271840)
+++ branches/safari-611-branch/LayoutTests/fast/mediastream/get-user-media-device-id.html	2021-01-25 22:12:26 UTC (rev 271841)
@@ -25,6 +25,8 @@
                 return navigator.mediaDevices.enumerateDevices();
             }).then(devices => {
                 devices.forEach((device) => {
+                    if (device.kind == "audiooutput")
+                        return;
                     let kind = device.kind == "audioinput" ? "audio" : "video";
                     deviceIds.push({ type: kind, id : device.deviceId});
                 });

Modified: branches/safari-611-branch/Source/WebCore/ChangeLog (271840 => 271841)


--- branches/safari-611-branch/Source/WebCore/ChangeLog	2021-01-25 22:12:20 UTC (rev 271840)
+++ branches/safari-611-branch/Source/WebCore/ChangeLog	2021-01-25 22:12:26 UTC (rev 271841)
@@ -1,5 +1,106 @@
 2021-01-25  Alan Coon  <[email protected]>
 
+        Cherry-pick r271471. rdar://problem/73477068
+
+    Source/WebCore:
+    [HANG] 496ms to 1360ms in WebCore::AVAudioSessionCaptureDeviceManager::refreshAudioCaptureDevices()
+    https://bugs.webkit.org/show_bug.cgi?id=220471
+    
+    Reviewed by Youenn Fablet.
+    
+    Refactor RealtimeMediaSourceCenter::getMediaStreamDevices() to take a completion handler, rather than
+    synchronously return a Vector of CaptureDevices. This also requires all CaptureDeviceManager subclasses
+    to support taking a completion handler themselves. By default, all CaptureDeviceManagers will support
+    the CompletionHandler path by just synchronously calling the completion handler with the existing
+    synchronous method. But for AVAudioSessionCaptureDeviceManager, override that default implementation by
+    activating the AVAudioSession on a background thread, and querying that session's inputs on a background
+    thread as well.
+    
+    * platform/mediastream/CaptureDeviceManager.h:
+    * platform/mediastream/RealtimeMediaSourceCenter.cpp:
+    (WebCore::RealtimeMediaSourceCenter::getMediaStreamDevices):
+    * platform/mediastream/RealtimeMediaSourceCenter.h:
+    * platform/mediastream/RealtimeMediaSourceFactory.h:
+    (WebCore::AudioCaptureFactory::getSpeakerDevices const):
+    * platform/mediastream/ios/AVAudioSessionCaptureDeviceManager.h:
+    * platform/mediastream/ios/AVAudioSessionCaptureDeviceManager.mm:
+    (WebCore::AVAudioSessionCaptureDeviceManager::audioSessionDeviceWithUID):
+    (WebCore::AVAudioSessionCaptureDeviceManager::scheduleUpdateCaptureDevices):
+    (WebCore::AVAudioSessionCaptureDeviceManager::refreshAudioCaptureDevices):
+    (WebCore::AVAudioSessionCaptureDeviceManager::getCaptureDevices):
+    (WebCore::AVAudioSessionCaptureDeviceManager::activateAudioSession):
+    (WebCore::AVAudioSessionCaptureDeviceManager::retrieveAudioSessionCaptureDevices const):
+    (WebCore::AVAudioSessionCaptureDeviceManager::setAudioCaptureDevices):
+    (WebCore::AVAudioSessionCaptureDeviceManager::audioSessionCaptureDevices): Deleted.
+    
+    Source/WebKit:
+    [HANG] 496ms to 1360ms in WebCore::AVAudioSessionCaptureDeviceManager::refreshAudioCaptureDevices()
+    https://bugs.webkit.org/show_bug.cgi?id=220471
+    
+    Reviewed by Youenn Fablet.
+    
+    Use the completion-handler version of RealtimeMediaSourceCenter::getMediaStreamDevices().
+    
+    * UIProcess/UserMediaPermissionRequestManagerProxy.cpp:
+    (WebKit::UserMediaPermissionRequestManagerProxy::computeFilteredDeviceList):
+    (WebKit::UserMediaPermissionRequestManagerProxy::enumerateMediaDevicesForFrame):
+    * UIProcess/UserMediaPermissionRequestManagerProxy.h:
+    * UIProcess/UserMediaProcessManager.cpp:
+    (WebKit::UserMediaProcessManager::updateCaptureDevices):
+    (WebKit::UserMediaProcessManager::beginMonitoringCaptureDevices):
+    * UIProcess/UserMediaProcessManager.h:
+    
+    LayoutTests:
+    [Cocoa] Support key rotation with HLS-backed encrypted media streams
+    https://bugs.webkit.org/show_bug.cgi?id=220493
+    <rdar://68227709>
+    
+    Reviewed by Youenn Fablet.
+    
+    Fix a broken layout test; the test enumerates devices, then uses the deviceIds returned to generate
+    constraints for a call to getUserMedia(). However, it assumes all devices will either be of kind
+    'audioinput' or 'videoinput'. If an 'audiooutput' device is returned (as the MockRealtimeMediaSourceCenter
+    does), then the test turns that into a video capture constraint, which fails.
+    
+    * fast/mediastream/get-user-media-device-id.html:
+    
+    
+    git-svn-id: https://svn.webkit.org/repository/webkit/trunk@271471 268f45cc-cd09-0410-ab3c-d52691b4dbfc
+
+    2021-01-13  Jer Noble  <[email protected]>
+
+            [HANG] 496ms to 1360ms in WebCore::AVAudioSessionCaptureDeviceManager::refreshAudioCaptureDevices()
+            https://bugs.webkit.org/show_bug.cgi?id=220471
+
+            Reviewed by Youenn Fablet.
+
+            Refactor RealtimeMediaSourceCenter::getMediaStreamDevices() to take a completion handler, rather than
+            synchronously return a Vector of CaptureDevices. This also requires all CaptureDeviceManager subclasses
+            to support taking a completion handler themselves. By default, all CaptureDeviceManagers will support
+            the CompletionHandler path by just synchronously calling the completion handler with the existing
+            synchronous method. But for AVAudioSessionCaptureDeviceManager, override that default implementation by
+            activating the AVAudioSession on a background thread, and querying that session's inputs on a background
+            thread as well.
+
+            * platform/mediastream/CaptureDeviceManager.h:
+            * platform/mediastream/RealtimeMediaSourceCenter.cpp:
+            (WebCore::RealtimeMediaSourceCenter::getMediaStreamDevices):
+            * platform/mediastream/RealtimeMediaSourceCenter.h:
+            * platform/mediastream/RealtimeMediaSourceFactory.h:
+            (WebCore::AudioCaptureFactory::getSpeakerDevices const):
+            * platform/mediastream/ios/AVAudioSessionCaptureDeviceManager.h:
+            * platform/mediastream/ios/AVAudioSessionCaptureDeviceManager.mm:
+            (WebCore::AVAudioSessionCaptureDeviceManager::audioSessionDeviceWithUID):
+            (WebCore::AVAudioSessionCaptureDeviceManager::scheduleUpdateCaptureDevices):
+            (WebCore::AVAudioSessionCaptureDeviceManager::refreshAudioCaptureDevices):
+            (WebCore::AVAudioSessionCaptureDeviceManager::getCaptureDevices):
+            (WebCore::AVAudioSessionCaptureDeviceManager::activateAudioSession):
+            (WebCore::AVAudioSessionCaptureDeviceManager::retrieveAudioSessionCaptureDevices const):
+            (WebCore::AVAudioSessionCaptureDeviceManager::setAudioCaptureDevices):
+            (WebCore::AVAudioSessionCaptureDeviceManager::audioSessionCaptureDevices): Deleted.
+
+2021-01-25  Alan Coon  <[email protected]>
+
         Cherry-pick r271436. rdar://problem/73477448
 
     REGRESSION(r268666) Incorrect vertical position inside grid items with padding

Modified: branches/safari-611-branch/Source/WebCore/platform/mediastream/CaptureDeviceManager.h (271840 => 271841)


--- branches/safari-611-branch/Source/WebCore/platform/mediastream/CaptureDeviceManager.h	2021-01-25 22:12:20 UTC (rev 271840)
+++ branches/safari-611-branch/Source/WebCore/platform/mediastream/CaptureDeviceManager.h	2021-01-25 22:12:26 UTC (rev 271841)
@@ -35,6 +35,7 @@
 class WEBCORE_EXPORT CaptureDeviceManager {
 public:
     virtual const Vector<CaptureDevice>& captureDevices() = 0;
+    virtual void getCaptureDevices(CompletionHandler<void(Vector<CaptureDevice>&&)>&& callback) { callback(copyToVector(captureDevices())); };
     virtual Optional<CaptureDevice> captureDeviceWithPersistentID(CaptureDevice::DeviceType, const String&) { return WTF::nullopt; }
 
 protected:

Modified: branches/safari-611-branch/Source/WebCore/platform/mediastream/RealtimeMediaSourceCenter.cpp (271840 => 271841)


--- branches/safari-611-branch/Source/WebCore/platform/mediastream/RealtimeMediaSourceCenter.cpp	2021-01-25 22:12:20 UTC (rev 271840)
+++ branches/safari-611-branch/Source/WebCore/platform/mediastream/RealtimeMediaSourceCenter.cpp	2021-01-25 22:12:26 UTC (rev 271841)
@@ -112,27 +112,48 @@
     audioSource->whenReady(WTFMove(whenAudioSourceReady));
 }
 
-Vector<CaptureDevice> RealtimeMediaSourceCenter::getMediaStreamDevices()
+void RealtimeMediaSourceCenter::getMediaStreamDevices(CompletionHandler<void(Vector<CaptureDevice>&&)>&& completion)
 {
-    Vector<CaptureDevice> result;
-    for (auto& device : audioCaptureFactory().audioCaptureDeviceManager().captureDevices()) {
-        if (device.enabled())
-            result.append(device);
-    }
-    for (auto& device : audioCaptureFactory().speakerDevices()) {
-        if (device.enabled())
-            result.append(device);
-    }
-    for (auto& device : videoCaptureFactory().videoCaptureDeviceManager().captureDevices()) {
-        if (device.enabled())
-            result.append(device);
-    }
-    for (auto& device : displayCaptureFactory().displayCaptureDeviceManager().captureDevices()) {
-        if (device.enabled())
-            result.append(device);
-    }
+    class CaptureDeviceAccumulator : public RefCounted<CaptureDeviceAccumulator> {
+    public:
+        static Ref<CaptureDeviceAccumulator> create(CompletionHandler<void(Vector<CaptureDevice>&&)>&& completion)
+        {
+            return adoptRef(*new CaptureDeviceAccumulator(WTFMove(completion)));
+        }
 
-    return result;
+        ~CaptureDeviceAccumulator()
+        {
+            m_completionHandler(WTFMove(m_results));
+        }
+
+        CompletionHandler<void(Vector<CaptureDevice>&&)> accumulate()
+        {
+            return [this, protectedThis = makeRef(*this)] (Vector<CaptureDevice>&& result) {
+                m_results.appendVector(WTFMove(result));
+            };
+        }
+
+    private:
+        explicit CaptureDeviceAccumulator(CompletionHandler<void(Vector<CaptureDevice>&&)>&& completion)
+            : m_completionHandler(WTFMove(completion))
+        {
+        }
+
+        CompletionHandler<void(Vector<CaptureDevice>&&)> m_completionHandler;
+        Vector<CaptureDevice> m_results;
+    };
+
+    auto accumulator = CaptureDeviceAccumulator::create([completion = WTFMove(completion)] (auto&& devices) mutable {
+        devices.removeAllMatching([] (auto& captureDevice) {
+            return !captureDevice.enabled();
+        });
+        completion(WTFMove(devices));
+    });
+
+    audioCaptureFactory().audioCaptureDeviceManager().getCaptureDevices(accumulator->accumulate());
+    videoCaptureFactory().videoCaptureDeviceManager().getCaptureDevices(accumulator->accumulate());
+    displayCaptureFactory().displayCaptureDeviceManager().getCaptureDevices(accumulator->accumulate());
+    audioCaptureFactory().getSpeakerDevices(accumulator->accumulate());
 }
 
 static void addStringToSHA1(SHA1& sha1, const String& string)

Modified: branches/safari-611-branch/Source/WebCore/platform/mediastream/RealtimeMediaSourceCenter.h (271840 => 271841)


--- branches/safari-611-branch/Source/WebCore/platform/mediastream/RealtimeMediaSourceCenter.h	2021-01-25 22:12:20 UTC (rev 271840)
+++ branches/safari-611-branch/Source/WebCore/platform/mediastream/RealtimeMediaSourceCenter.h	2021-01-25 22:12:26 UTC (rev 271841)
@@ -66,7 +66,7 @@
     using NewMediaStreamHandler = Function<void(Expected<Ref<MediaStreamPrivate>, String>&&)>;
     void createMediaStream(Ref<const Logger>&&, NewMediaStreamHandler&&, String&&, CaptureDevice&& audioDevice, CaptureDevice&& videoDevice, const MediaStreamRequest&);
 
-    WEBCORE_EXPORT Vector<CaptureDevice> getMediaStreamDevices();
+    WEBCORE_EXPORT void getMediaStreamDevices(CompletionHandler<void(Vector<CaptureDevice>&&)>&&);
 
     const RealtimeMediaSourceSupportedConstraints& supportedConstraints() { return m_supportedConstraints; }
 

Modified: branches/safari-611-branch/Source/WebCore/platform/mediastream/RealtimeMediaSourceFactory.h (271840 => 271841)


--- branches/safari-611-branch/Source/WebCore/platform/mediastream/RealtimeMediaSourceFactory.h	2021-01-25 22:12:20 UTC (rev 271840)
+++ branches/safari-611-branch/Source/WebCore/platform/mediastream/RealtimeMediaSourceFactory.h	2021-01-25 22:12:26 UTC (rev 271841)
@@ -27,6 +27,7 @@
 
 #if ENABLE(MEDIA_STREAM)
 
+#include <wtf/CompletionHandler.h>
 #include <wtf/WeakPtr.h>
 #include <wtf/text/WTFString.h>
 
@@ -62,6 +63,7 @@
     virtual CaptureSourceOrError createAudioCaptureSource(const CaptureDevice&, String&&, const MediaConstraints*) = 0;
     virtual CaptureDeviceManager& audioCaptureDeviceManager() = 0;
     virtual const Vector<CaptureDevice>& speakerDevices() const = 0;
+    virtual void getSpeakerDevices(CompletionHandler<void(Vector<CaptureDevice>&&)>&& completion) const { completion(copyToVector(speakerDevices())); }
 
     class ExtensiveObserver : public CanMakeWeakPtr<ExtensiveObserver> { };
     virtual void addExtensiveObserver(ExtensiveObserver&) { };

Modified: branches/safari-611-branch/Source/WebCore/platform/mediastream/ios/AVAudioSessionCaptureDeviceManager.h (271840 => 271841)


--- branches/safari-611-branch/Source/WebCore/platform/mediastream/ios/AVAudioSessionCaptureDeviceManager.h	2021-01-25 22:12:20 UTC (rev 271840)
+++ branches/safari-611-branch/Source/WebCore/platform/mediastream/ios/AVAudioSessionCaptureDeviceManager.h	2021-01-25 22:12:26 UTC (rev 271841)
@@ -48,6 +48,7 @@
     static AVAudioSessionCaptureDeviceManager& singleton();
 
     const Vector<CaptureDevice>& captureDevices() final;
+    void getCaptureDevices(CompletionHandler<void(Vector<CaptureDevice>&&)>&&) final;
     const Vector<CaptureDevice>& speakerDevices() const { return m_speakerDevices; }
     Optional<CaptureDevice> captureDeviceWithPersistentID(CaptureDevice::DeviceType, const String&);
 
@@ -63,8 +64,10 @@
     ~AVAudioSessionCaptureDeviceManager();
 
     void createAudioSession();
+    void activateAudioSession();
     void refreshAudioCaptureDevices();
-    Vector<AVAudioSessionCaptureDevice>& audioSessionCaptureDevices();
+    Vector<AVAudioSessionCaptureDevice> retrieveAudioSessionCaptureDevices() const;
+    void setAudioCaptureDevices(Vector<AVAudioSessionCaptureDevice>&&);
 
     enum class AudioSessionState { NotNeeded, Inactive, Active };
 

Modified: branches/safari-611-branch/Source/WebCore/platform/mediastream/ios/AVAudioSessionCaptureDeviceManager.mm (271840 => 271841)


--- branches/safari-611-branch/Source/WebCore/platform/mediastream/ios/AVAudioSessionCaptureDeviceManager.mm	2021-01-25 22:12:20 UTC (rev 271840)
+++ branches/safari-611-branch/Source/WebCore/platform/mediastream/ios/AVAudioSessionCaptureDeviceManager.mm	2021-01-25 22:12:26 UTC (rev 271841)
@@ -136,16 +136,12 @@
     return WTF::nullopt;
 }
 
-Vector<AVAudioSessionCaptureDevice>& AVAudioSessionCaptureDeviceManager::audioSessionCaptureDevices()
+Optional<AVAudioSessionCaptureDevice> AVAudioSessionCaptureDeviceManager::audioSessionDeviceWithUID(const String& deviceID)
 {
     if (!m_audioSessionCaptureDevices)
         refreshAudioCaptureDevices();
-    return m_audioSessionCaptureDevices.value();
-}
 
-Optional<AVAudioSessionCaptureDevice> AVAudioSessionCaptureDeviceManager::audioSessionDeviceWithUID(const String& deviceID)
-{
-    for (auto& device : audioSessionCaptureDevices()) {
+    for (auto& device : *m_audioSessionCaptureDevices) {
         if (device.persistentId() == deviceID)
             return device;
     }
@@ -154,42 +150,71 @@
 
 void AVAudioSessionCaptureDeviceManager::scheduleUpdateCaptureDevices()
 {
-    if (m_updateDeviceStateQueue.hasPendingTasks())
-        return;
-
-    m_updateDeviceStateQueue.enqueueTask([this] {
-        refreshAudioCaptureDevices();
-    });
+    getCaptureDevices([] (auto) { });
 }
 
 void AVAudioSessionCaptureDeviceManager::refreshAudioCaptureDevices()
 {
-    {
-        // Make sure we have created the audio session.
-        auto locker = holdLock(m_lock);
+    if (m_audioSessionState == AudioSessionState::Inactive) {
+        m_audioSessionState = AudioSessionState::Active;
+
+        dispatch_sync(m_dispatchQueue, makeBlockPtr([this] {
+            activateAudioSession();
+        }).get());
     }
-    bool firstTime = !m_devices;
+
+    Vector<AVAudioSessionCaptureDevice> newAudioDevices;
+    dispatch_sync(m_dispatchQueue, makeBlockPtr([&] {
+        newAudioDevices = retrieveAudioSessionCaptureDevices();
+    }).get());
+    setAudioCaptureDevices(WTFMove(newAudioDevices));
+}
+
+void AVAudioSessionCaptureDeviceManager::getCaptureDevices(CompletionHandler<void(Vector<CaptureDevice>&&)>&& completion)
+{
     if (m_audioSessionState == AudioSessionState::Inactive) {
         m_audioSessionState = AudioSessionState::Active;
 
-        if (!m_listener)
-            m_listener = adoptNS([[WebAVAudioSessionAvailableInputsListener alloc] initWithCallback:this audioSession:m_audioSession.get()]);
-
-        NSError *error = nil;
-        [m_audioSession setActive:YES withOptions:0 error:&error];
-        if (error)
-            RELEASE_LOG_ERROR(WebRTC, "Failed to activate audio session with error: %@.", error.localizedDescription);
+        dispatch_async(m_dispatchQueue, makeBlockPtr([this] {
+            activateAudioSession();
+        }).get());
     }
 
+    dispatch_async(m_dispatchQueue, makeBlockPtr([this, completion = WTFMove(completion)] () mutable {
+        auto newAudioDevices = retrieveAudioSessionCaptureDevices();
+        callOnWebThreadOrDispatchAsyncOnMainThread(makeBlockPtr([this, completion = WTFMove(completion), newAudioDevices = WTFMove(newAudioDevices)] () mutable {
+            setAudioCaptureDevices(WTFMove(newAudioDevices));
+            completion(copyToVector(*m_devices));
+        }).get());
+    }).get());
+}
+
+void AVAudioSessionCaptureDeviceManager::activateAudioSession()
+{
+    if (!m_listener)
+        m_listener = adoptNS([[WebAVAudioSessionAvailableInputsListener alloc] initWithCallback:this audioSession:m_audioSession.get()]);
+
+    NSError *error = nil;
+    [m_audioSession setActive:YES withOptions:0 error:&error];
+    if (error)
+        RELEASE_LOG_ERROR(WebRTC, "Failed to activate audio session with error: %@.", error.localizedDescription);
+}
+
+Vector<AVAudioSessionCaptureDevice> AVAudioSessionCaptureDeviceManager::retrieveAudioSessionCaptureDevices() const
+{
     Vector<AVAudioSessionCaptureDevice> newAudioDevices;
-    Vector<CaptureDevice> newDevices;
     auto *defaultInput = [m_audioSession currentRoute].inputs.firstObject;
-    for (AVAudioSessionPortDescription *portDescription in [m_audioSession availableInputs]) {
-        auto audioDevice = AVAudioSessionCaptureDevice::create(portDescription, defaultInput);
-        newDevices.append(audioDevice);
-        newAudioDevices.append(WTFMove(audioDevice));
-    }
+    newAudioDevices.reserveInitialCapacity([m_audioSession availableInputs].count);
 
+    for (AVAudioSessionPortDescription *portDescription in [m_audioSession availableInputs])
+        newAudioDevices.uncheckedAppend(AVAudioSessionCaptureDevice::create(portDescription, defaultInput));
+
+    return newAudioDevices;
+}
+
+void AVAudioSessionCaptureDeviceManager::setAudioCaptureDevices(Vector<AVAudioSessionCaptureDevice>&& newAudioDevices)
+{
+    bool firstTime = !m_devices;
     bool haveDeviceChanges = !m_devices || newAudioDevices.size() != m_devices->size();
     if (!haveDeviceChanges) {
         for (size_t i = 0; i < newAudioDevices.size(); ++i) {
@@ -203,6 +228,7 @@
     if (!haveDeviceChanges && !firstTime)
         return;
 
+    auto newDevices = copyToVectorOf<CaptureDevice>(newAudioDevices);
     m_audioSessionCaptureDevices = WTFMove(newAudioDevices);
     std::sort(newDevices.begin(), newDevices.end(), [] (auto& first, auto& second) -> bool {
         return first.isDefault() && !second.isDefault();

Modified: branches/safari-611-branch/Source/WebKit/ChangeLog (271840 => 271841)


--- branches/safari-611-branch/Source/WebKit/ChangeLog	2021-01-25 22:12:20 UTC (rev 271840)
+++ branches/safari-611-branch/Source/WebKit/ChangeLog	2021-01-25 22:12:26 UTC (rev 271841)
@@ -1,5 +1,92 @@
 2021-01-25  Alan Coon  <[email protected]>
 
+        Cherry-pick r271471. rdar://problem/73477068
+
+    Source/WebCore:
+    [HANG] 496ms to 1360ms in WebCore::AVAudioSessionCaptureDeviceManager::refreshAudioCaptureDevices()
+    https://bugs.webkit.org/show_bug.cgi?id=220471
+    
+    Reviewed by Youenn Fablet.
+    
+    Refactor RealtimeMediaSourceCenter::getMediaStreamDevices() to take a completion handler, rather than
+    synchronously return a Vector of CaptureDevices. This also requires all CaptureDeviceManager subclasses
+    to support taking a completion handler themselves. By default, all CaptureDeviceManagers will support
+    the CompletionHandler path by just synchronously calling the completion handler with the existing
+    synchronous method. But for AVAudioSessionCaptureDeviceManager, override that default implementation by
+    activating the AVAudioSession on a background thread, and querying that session's inputs on a background
+    thread as well.
+    
+    * platform/mediastream/CaptureDeviceManager.h:
+    * platform/mediastream/RealtimeMediaSourceCenter.cpp:
+    (WebCore::RealtimeMediaSourceCenter::getMediaStreamDevices):
+    * platform/mediastream/RealtimeMediaSourceCenter.h:
+    * platform/mediastream/RealtimeMediaSourceFactory.h:
+    (WebCore::AudioCaptureFactory::getSpeakerDevices const):
+    * platform/mediastream/ios/AVAudioSessionCaptureDeviceManager.h:
+    * platform/mediastream/ios/AVAudioSessionCaptureDeviceManager.mm:
+    (WebCore::AVAudioSessionCaptureDeviceManager::audioSessionDeviceWithUID):
+    (WebCore::AVAudioSessionCaptureDeviceManager::scheduleUpdateCaptureDevices):
+    (WebCore::AVAudioSessionCaptureDeviceManager::refreshAudioCaptureDevices):
+    (WebCore::AVAudioSessionCaptureDeviceManager::getCaptureDevices):
+    (WebCore::AVAudioSessionCaptureDeviceManager::activateAudioSession):
+    (WebCore::AVAudioSessionCaptureDeviceManager::retrieveAudioSessionCaptureDevices const):
+    (WebCore::AVAudioSessionCaptureDeviceManager::setAudioCaptureDevices):
+    (WebCore::AVAudioSessionCaptureDeviceManager::audioSessionCaptureDevices): Deleted.
+    
+    Source/WebKit:
+    [HANG] 496ms to 1360ms in WebCore::AVAudioSessionCaptureDeviceManager::refreshAudioCaptureDevices()
+    https://bugs.webkit.org/show_bug.cgi?id=220471
+    
+    Reviewed by Youenn Fablet.
+    
+    Use the completion-handler version of RealtimeMediaSourceCenter::getMediaStreamDevices().
+    
+    * UIProcess/UserMediaPermissionRequestManagerProxy.cpp:
+    (WebKit::UserMediaPermissionRequestManagerProxy::computeFilteredDeviceList):
+    (WebKit::UserMediaPermissionRequestManagerProxy::enumerateMediaDevicesForFrame):
+    * UIProcess/UserMediaPermissionRequestManagerProxy.h:
+    * UIProcess/UserMediaProcessManager.cpp:
+    (WebKit::UserMediaProcessManager::updateCaptureDevices):
+    (WebKit::UserMediaProcessManager::beginMonitoringCaptureDevices):
+    * UIProcess/UserMediaProcessManager.h:
+    
+    LayoutTests:
+    [Cocoa] Support key rotation with HLS-backed encrypted media streams
+    https://bugs.webkit.org/show_bug.cgi?id=220493
+    <rdar://68227709>
+    
+    Reviewed by Youenn Fablet.
+    
+    Fix a broken layout test; the test enumerates devices, then uses the deviceIds returned to generate
+    constraints for a call to getUserMedia(). However, it assumes all devices will either be of kind
+    'audioinput' or 'videoinput'. If an 'audiooutput' device is returned (as the MockRealtimeMediaSourceCenter
+    does), then the test turns that into a video capture constraint, which fails.
+    
+    * fast/mediastream/get-user-media-device-id.html:
+    
+    
+    git-svn-id: https://svn.webkit.org/repository/webkit/trunk@271471 268f45cc-cd09-0410-ab3c-d52691b4dbfc
+
+    2021-01-13  Jer Noble  <[email protected]>
+
+            [HANG] 496ms to 1360ms in WebCore::AVAudioSessionCaptureDeviceManager::refreshAudioCaptureDevices()
+            https://bugs.webkit.org/show_bug.cgi?id=220471
+
+            Reviewed by Youenn Fablet.
+
+            Use the completion-handler version of RealtimeMediaSourceCenter::getMediaStreamDevices().
+
+            * UIProcess/UserMediaPermissionRequestManagerProxy.cpp:
+            (WebKit::UserMediaPermissionRequestManagerProxy::computeFilteredDeviceList):
+            (WebKit::UserMediaPermissionRequestManagerProxy::enumerateMediaDevicesForFrame):
+            * UIProcess/UserMediaPermissionRequestManagerProxy.h:
+            * UIProcess/UserMediaProcessManager.cpp:
+            (WebKit::UserMediaProcessManager::updateCaptureDevices):
+            (WebKit::UserMediaProcessManager::beginMonitoringCaptureDevices):
+            * UIProcess/UserMediaProcessManager.h:
+
+2021-01-25  Alan Coon  <[email protected]>
+
         Cherry-pick r271467. rdar://problem/73477045
 
     Crash at SOAuthorizationSession::dismissViewController

Modified: branches/safari-611-branch/Source/WebKit/UIProcess/UserMediaPermissionRequestManagerProxy.cpp (271840 => 271841)


--- branches/safari-611-branch/Source/WebKit/UIProcess/UserMediaPermissionRequestManagerProxy.cpp	2021-01-25 22:12:20 UTC (rev 271840)
+++ branches/safari-611-branch/Source/WebKit/UIProcess/UserMediaPermissionRequestManagerProxy.cpp	2021-01-25 22:12:26 UTC (rev 271841)
@@ -654,40 +654,42 @@
     });
 }
 
-Vector<CaptureDevice> UserMediaPermissionRequestManagerProxy::computeFilteredDeviceList(bool revealIdsAndLabels)
+void UserMediaPermissionRequestManagerProxy::computeFilteredDeviceList(bool revealIdsAndLabels, CompletionHandler<void(Vector<CaptureDevice>&&)>&& completion)
 {
-    static const int defaultMaximumCameraCount = 1;
-    static const int defaultMaximumMicrophoneCount = 1;
+    static const unsigned defaultMaximumCameraCount = 1;
+    static const unsigned defaultMaximumMicrophoneCount = 1;
 
-    auto devices = RealtimeMediaSourceCenter::singleton().getMediaStreamDevices();
-    int cameraCount = 0;
-    int microphoneCount = 0;
+    RealtimeMediaSourceCenter::singleton().getMediaStreamDevices([this, weakThis = makeWeakPtr(this), revealIdsAndLabels, completion = WTFMove(completion)] (auto&& devices) mutable {
+        unsigned cameraCount = 0;
+        unsigned microphoneCount = 0;
 
-    Vector<CaptureDevice> filteredDevices;
-    for (const auto& device : devices) {
-        if (!device.enabled() || (device.type() != WebCore::CaptureDevice::DeviceType::Camera && device.type() != WebCore::CaptureDevice::DeviceType::Microphone && device.type() != WebCore::CaptureDevice::DeviceType::Speaker))
-            continue;
+        Vector<CaptureDevice> filteredDevices;
+        for (const auto& device : devices) {
+            if (!device.enabled() || (device.type() != WebCore::CaptureDevice::DeviceType::Camera && device.type() != WebCore::CaptureDevice::DeviceType::Microphone && device.type() != WebCore::CaptureDevice::DeviceType::Speaker))
+                continue;
 
-        if (!revealIdsAndLabels) {
-            if (device.type() == WebCore::CaptureDevice::DeviceType::Camera && ++cameraCount > defaultMaximumCameraCount)
-                continue;
-            if (device.type() == WebCore::CaptureDevice::DeviceType::Microphone && ++microphoneCount > defaultMaximumMicrophoneCount)
-                continue;
-            if (device.type() != WebCore::CaptureDevice::DeviceType::Camera && device.type() != WebCore::CaptureDevice::DeviceType::Microphone)
-                continue;
-        } else {
-            // We only expose speakers tied to a microphone for the moment.
-            if (device.type() == WebCore::CaptureDevice::DeviceType::Speaker && !haveMicrophoneDevice(devices, device.groupId()))
-                continue;
+            if (!revealIdsAndLabels) {
+                if (device.type() == WebCore::CaptureDevice::DeviceType::Camera && ++cameraCount > defaultMaximumCameraCount)
+                    continue;
+                if (device.type() == WebCore::CaptureDevice::DeviceType::Microphone && ++microphoneCount > defaultMaximumMicrophoneCount)
+                    continue;
+                if (device.type() != WebCore::CaptureDevice::DeviceType::Camera && device.type() != WebCore::CaptureDevice::DeviceType::Microphone)
+                    continue;
+            } else {
+                // We only expose speakers tied to a microphone for the moment.
+                if (device.type() == WebCore::CaptureDevice::DeviceType::Speaker && !haveMicrophoneDevice(devices, device.groupId()))
+                    continue;
+            }
+
+            filteredDevices.append(revealIdsAndLabels ? device : CaptureDevice({ }, device.type(), { }, { }));
         }
 
-        filteredDevices.append(revealIdsAndLabels ? device : CaptureDevice({ }, device.type(), { }, { }));
-    }
+        if (weakThis)
+            m_hasFilteredDeviceList = !revealIdsAndLabels;
 
-    m_hasFilteredDeviceList = !revealIdsAndLabels;
-
-    ALWAYS_LOG(LOGIDENTIFIER, filteredDevices.size(), " devices revealed");
-    return filteredDevices;
+        ALWAYS_LOG(LOGIDENTIFIER, filteredDevices.size(), " devices revealed");
+        completion(WTFMove(filteredDevices));
+    });
 }
 #endif
 
@@ -739,7 +741,9 @@
             bool revealIdsAndLabels = originHasPersistentAccess || wasGrantedVideoOrAudioAccess(frameID, userMediaDocumentOrigin.get(), topLevelDocumentOrigin.get());
 
             callCompletionHandler.release();
-            completionHandler(computeFilteredDeviceList(revealIdsAndLabels), deviceIDHashSalt);
+            computeFilteredDeviceList(revealIdsAndLabels, [completionHandler = WTFMove(completionHandler), deviceIDHashSalt = WTFMove(deviceIDHashSalt)] (auto&& devices) mutable {
+                completionHandler(devices, deviceIDHashSalt);
+            });
         });
     };
 

Modified: branches/safari-611-branch/Source/WebKit/UIProcess/UserMediaPermissionRequestManagerProxy.h (271840 => 271841)


--- branches/safari-611-branch/Source/WebKit/UIProcess/UserMediaPermissionRequestManagerProxy.h	2021-01-25 22:12:20 UTC (rev 271840)
+++ branches/safari-611-branch/Source/WebKit/UIProcess/UserMediaPermissionRequestManagerProxy.h	2021-01-25 22:12:26 UTC (rev 271841)
@@ -119,7 +119,7 @@
 
     bool wasGrantedVideoOrAudioAccess(WebCore::FrameIdentifier, const WebCore::SecurityOrigin& userMediaDocumentOrigin, const WebCore::SecurityOrigin& topLevelDocumentOrigin);
 
-    Vector<WebCore::CaptureDevice> computeFilteredDeviceList(bool revealIdsAndLabels);
+    void computeFilteredDeviceList(bool revealIdsAndLabels, CompletionHandler<void(Vector<WebCore::CaptureDevice>&&)>&&);
 
     void processUserMediaPermissionRequest();
     void processUserMediaPermissionInvalidRequest(const String& invalidConstraint);

Modified: branches/safari-611-branch/Source/WebKit/UIProcess/UserMediaProcessManager.cpp (271840 => 271841)


--- branches/safari-611-branch/Source/WebKit/UIProcess/UserMediaProcessManager.cpp	2021-01-25 22:12:20 UTC (rev 271840)
+++ branches/safari-611-branch/Source/WebKit/UIProcess/UserMediaProcessManager.cpp	2021-01-25 22:12:26 UTC (rev 271841)
@@ -217,41 +217,51 @@
     });
 }
 
-void UserMediaProcessManager::beginMonitoringCaptureDevices()
+void UserMediaProcessManager::updateCaptureDevices(ShouldNotify shouldNotify)
 {
-    static std::once_flag onceFlag;
+    WebCore::RealtimeMediaSourceCenter::singleton().getMediaStreamDevices([this, shouldNotify] (auto&& newDevices) mutable {
+        auto oldDevices = WTFMove(m_captureDevices);
+        m_captureDevices = WTFMove(newDevices);
 
-    std::call_once(onceFlag, [this] {
-        m_captureDevices = WebCore::RealtimeMediaSourceCenter::singleton().getMediaStreamDevices();
+        if (shouldNotify == ShouldNotify::No)
+            return;
 
-        WebCore::RealtimeMediaSourceCenter::singleton().setDevicesChangedObserver([this]() {
-            auto oldDevices = WTFMove(m_captureDevices);
-            m_captureDevices = WebCore::RealtimeMediaSourceCenter::singleton().getMediaStreamDevices();
+        if (m_captureDevices.size() == oldDevices.size()) {
+            bool haveChanges = false;
+            for (auto &newDevice : m_captureDevices) {
+                if (newDevice.type() != WebCore::CaptureDevice::DeviceType::Camera && newDevice.type() != WebCore::CaptureDevice::DeviceType::Microphone)
+                    continue;
 
-            if (m_captureDevices.size() == oldDevices.size()) {
-                bool haveChanges = false;
-                for (auto &newDevice : m_captureDevices) {
-                    if (newDevice.type() != WebCore::CaptureDevice::DeviceType::Camera && newDevice.type() != WebCore::CaptureDevice::DeviceType::Microphone)
-                        continue;
+                auto index = oldDevices.findMatching([&newDevice] (auto& oldDevice) {
+                    return newDevice.persistentId() == oldDevice.persistentId() && newDevice.enabled() != oldDevice.enabled();
+                });
 
-                    auto index = oldDevices.findMatching([&newDevice] (auto& oldDevice) {
-                        return newDevice.persistentId() == oldDevice.persistentId() && newDevice.enabled() != oldDevice.enabled();
-                    });
-
-                    if (index == notFound) {
-                        haveChanges = true;
-                        break;
-                    }
+                if (index == notFound) {
+                    haveChanges = true;
+                    break;
                 }
-
-                if (!haveChanges)
-                    return;
             }
 
-            // When a device with camera and microphone is attached or detached, the CaptureDevice notification for
-            // the different devices won't arrive at the same time so delay a bit so we can coalesce the callbacks.
-            if (!m_debounceTimer.isActive())
-                m_debounceTimer.startOneShot(deviceChangeDebounceTimerInterval);
+            if (!haveChanges)
+                return;
+        }
+
+        // When a device with camera and microphone is attached or detached, the CaptureDevice notification for
+        // the different devices won't arrive at the same time so delay a bit so we can coalesce the callbacks.
+        if (!m_debounceTimer.isActive())
+            m_debounceTimer.startOneShot(deviceChangeDebounceTimerInterval);
+    });
+}
+
+void UserMediaProcessManager::beginMonitoringCaptureDevices()
+{
+    static std::once_flag onceFlag;
+
+    std::call_once(onceFlag, [this] {
+        updateCaptureDevices(ShouldNotify::No);
+
+        WebCore::RealtimeMediaSourceCenter::singleton().setDevicesChangedObserver([this]() {
+            updateCaptureDevices(ShouldNotify::Yes);
         });
     });
 }

Modified: branches/safari-611-branch/Source/WebKit/UIProcess/UserMediaProcessManager.h (271840 => 271841)


--- branches/safari-611-branch/Source/WebKit/UIProcess/UserMediaProcessManager.h	2021-01-25 22:12:20 UTC (rev 271840)
+++ branches/safari-611-branch/Source/WebKit/UIProcess/UserMediaProcessManager.h	2021-01-25 22:12:26 UTC (rev 271841)
@@ -48,6 +48,8 @@
     void beginMonitoringCaptureDevices();
 
 private:
+    enum class ShouldNotify { Yes, No };
+    void updateCaptureDevices(ShouldNotify);
     void captureDevicesChanged();
 
     Vector<WebCore::CaptureDevice> m_captureDevices;
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to