Title: [277361] trunk/Source/WebCore
Revision
277361
Author
[email protected]
Date
2021-05-12 01:05:19 -0700 (Wed, 12 May 2021)

Log Message

Enumerate AVCaptureDevice list in a background thread
https://bugs.webkit.org/show_bug.cgi?id=225643
<rdar://problem/77820002>

Reviewed by Eric Carlson.

Enumerate AVCaptureDevice in a background queue asynchronously.
Delay getUserMedia and enumerateDevices until this is completed.

Update RealtimeMediaSourceCenter accordingly and introduce RealtimeMediaSourceCenter::enumerateDevices for that purpose.
Replace getCaptureDevices by computeCaptureDevices to do the async computation.
Continue using captureDevices() getters.

Manually tested.

* platform/mediastream/CaptureDevice.h:
(WebCore::CaptureDevice::CaptureDevice):
(WebCore::CaptureDevice::isolatedCopy):
* platform/mediastream/CaptureDeviceManager.h:
* platform/mediastream/RealtimeMediaSourceCenter.cpp:
(WebCore::RealtimeMediaSourceCenter::getMediaStreamDevices):
(WebCore::RealtimeMediaSourceCenter::enumerateDevices):
(WebCore::RealtimeMediaSourceCenter::validateRequestConstraints):
(WebCore::RealtimeMediaSourceCenter::validateRequestConstraintsAfterEnumeration):
* platform/mediastream/RealtimeMediaSourceCenter.h:
* platform/mediastream/RealtimeMediaSourceFactory.h:
(WebCore::AudioCaptureFactory::computeSpeakerDevices const):
* platform/mediastream/ios/AVAudioSessionCaptureDevice.mm:
(WebCore::AVAudioSessionCaptureDevice::AVAudioSessionCaptureDevice):
* platform/mediastream/ios/AVAudioSessionCaptureDeviceManager.h:
* platform/mediastream/ios/AVAudioSessionCaptureDeviceManager.mm:
(WebCore::AVAudioSessionCaptureDeviceManager::scheduleUpdateCaptureDevices):
(WebCore::AVAudioSessionCaptureDeviceManager::computeCaptureDevices):
* platform/mediastream/mac/AVCaptureDeviceManager.h:
* platform/mediastream/mac/AVCaptureDeviceManager.mm:
(WebCore::AVCaptureDeviceManager::computeCaptureDevices):
(WebCore::AVCaptureDeviceManager::captureDevices):
(WebCore::AVCaptureDeviceManager::updateCachedAVCaptureDevices):
(WebCore::AVCaptureDeviceManager::retrieveCaptureDevices):
(WebCore::AVCaptureDeviceManager::refreshCaptureDevices):
(WebCore::AVCaptureDeviceManager::AVCaptureDeviceManager):

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (277360 => 277361)


--- trunk/Source/WebCore/ChangeLog	2021-05-12 07:56:39 UTC (rev 277360)
+++ trunk/Source/WebCore/ChangeLog	2021-05-12 08:05:19 UTC (rev 277361)
@@ -1,3 +1,47 @@
+2021-05-12  Youenn Fablet  <[email protected]>
+
+        Enumerate AVCaptureDevice list in a background thread
+        https://bugs.webkit.org/show_bug.cgi?id=225643
+        <rdar://problem/77820002>
+
+        Reviewed by Eric Carlson.
+
+        Enumerate AVCaptureDevice in a background queue asynchronously.
+        Delay getUserMedia and enumerateDevices until this is completed.
+
+        Update RealtimeMediaSourceCenter accordingly and introduce RealtimeMediaSourceCenter::enumerateDevices for that purpose.
+        Replace getCaptureDevices by computeCaptureDevices to do the async computation.
+        Continue using captureDevices() getters.
+
+        Manually tested.
+
+        * platform/mediastream/CaptureDevice.h:
+        (WebCore::CaptureDevice::CaptureDevice):
+        (WebCore::CaptureDevice::isolatedCopy):
+        * platform/mediastream/CaptureDeviceManager.h:
+        * platform/mediastream/RealtimeMediaSourceCenter.cpp:
+        (WebCore::RealtimeMediaSourceCenter::getMediaStreamDevices):
+        (WebCore::RealtimeMediaSourceCenter::enumerateDevices):
+        (WebCore::RealtimeMediaSourceCenter::validateRequestConstraints):
+        (WebCore::RealtimeMediaSourceCenter::validateRequestConstraintsAfterEnumeration):
+        * platform/mediastream/RealtimeMediaSourceCenter.h:
+        * platform/mediastream/RealtimeMediaSourceFactory.h:
+        (WebCore::AudioCaptureFactory::computeSpeakerDevices const):
+        * platform/mediastream/ios/AVAudioSessionCaptureDevice.mm:
+        (WebCore::AVAudioSessionCaptureDevice::AVAudioSessionCaptureDevice):
+        * platform/mediastream/ios/AVAudioSessionCaptureDeviceManager.h:
+        * platform/mediastream/ios/AVAudioSessionCaptureDeviceManager.mm:
+        (WebCore::AVAudioSessionCaptureDeviceManager::scheduleUpdateCaptureDevices):
+        (WebCore::AVAudioSessionCaptureDeviceManager::computeCaptureDevices):
+        * platform/mediastream/mac/AVCaptureDeviceManager.h:
+        * platform/mediastream/mac/AVCaptureDeviceManager.mm:
+        (WebCore::AVCaptureDeviceManager::computeCaptureDevices):
+        (WebCore::AVCaptureDeviceManager::captureDevices):
+        (WebCore::AVCaptureDeviceManager::updateCachedAVCaptureDevices):
+        (WebCore::AVCaptureDeviceManager::retrieveCaptureDevices):
+        (WebCore::AVCaptureDeviceManager::refreshCaptureDevices):
+        (WebCore::AVCaptureDeviceManager::AVCaptureDeviceManager):
+
 2021-05-11  Cameron McCormack  <[email protected]>
 
         Include reasons for compositing in showLayerTree output

Modified: trunk/Source/WebCore/platform/mediastream/CaptureDevice.h (277360 => 277361)


--- trunk/Source/WebCore/platform/mediastream/CaptureDevice.h	2021-05-12 07:56:39 UTC (rev 277360)
+++ trunk/Source/WebCore/platform/mediastream/CaptureDevice.h	2021-05-12 08:05:19 UTC (rev 277361)
@@ -33,11 +33,14 @@
 public:
     enum class DeviceType { Unknown, Microphone, Speaker, Camera, Screen, Window };
 
-    CaptureDevice(const String& persistentId, DeviceType type, const String& label, const String& groupId = emptyString())
+    CaptureDevice(const String& persistentId, DeviceType type, const String& label, const String& groupId = emptyString(), bool isEnabled = false, bool isDefault = false, bool isMock = false)
         : m_persistentId(persistentId)
         , m_type(type)
         , m_label(label)
         , m_groupId(groupId)
+        , m_enabled(isEnabled)
+        , m_default(isDefault)
+        , m_isMockDevice(isMock)
     {
     }
 
@@ -71,6 +74,8 @@
 
     explicit operator bool() const { return m_type != DeviceType::Unknown; }
 
+    CaptureDevice isolatedCopy() &&;
+
 #if ENABLE(MEDIA_STREAM)
     template<class Encoder>
     void encode(Encoder& encoder) const
@@ -160,6 +165,19 @@
     return false;
 }
 
+inline CaptureDevice CaptureDevice::isolatedCopy() &&
+{
+    return {
+        WTFMove(m_persistentId).isolatedCopy(),
+        m_type,
+        WTFMove(m_label).isolatedCopy(),
+        WTFMove(m_groupId).isolatedCopy(),
+        m_enabled,
+        m_default,
+        m_isMockDevice
+    };
+}
+
 } // namespace WebCore
 
 #if ENABLE(MEDIA_STREAM)

Modified: trunk/Source/WebCore/platform/mediastream/CaptureDeviceManager.h (277360 => 277361)


--- trunk/Source/WebCore/platform/mediastream/CaptureDeviceManager.h	2021-05-12 07:56:39 UTC (rev 277360)
+++ trunk/Source/WebCore/platform/mediastream/CaptureDeviceManager.h	2021-05-12 08:05:19 UTC (rev 277361)
@@ -35,7 +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 void computeCaptureDevices(CompletionHandler<void()>&& callback) { callback(); }
     virtual Optional<CaptureDevice> captureDeviceWithPersistentID(CaptureDevice::DeviceType, const String&) { return WTF::nullopt; }
 
 protected:

Modified: trunk/Source/WebCore/platform/mediastream/RealtimeMediaSourceCenter.cpp (277360 => 277361)


--- trunk/Source/WebCore/platform/mediastream/RealtimeMediaSourceCenter.cpp	2021-05-12 07:56:39 UTC (rev 277360)
+++ trunk/Source/WebCore/platform/mediastream/RealtimeMediaSourceCenter.cpp	2021-05-12 08:05:19 UTC (rev 277361)
@@ -38,6 +38,7 @@
 #include "CaptureDeviceManager.h"
 #include "Logging.h"
 #include "MediaStreamPrivate.h"
+#include <wtf/CallbackAggregator.h>
 #include <wtf/SHA1.h>
 
 namespace WebCore {
@@ -119,46 +120,16 @@
 
 void RealtimeMediaSourceCenter::getMediaStreamDevices(CompletionHandler<void(Vector<CaptureDevice>&&)>&& completion)
 {
-    class CaptureDeviceAccumulator : public RefCounted<CaptureDeviceAccumulator> {
-    public:
-        static Ref<CaptureDeviceAccumulator> create(CompletionHandler<void(Vector<CaptureDevice>&&)>&& completion)
-        {
-            return adoptRef(*new CaptureDeviceAccumulator(WTFMove(completion)));
-        }
+    enumerateDevices(true, true, true, true, [this, completion = WTFMove(completion)]() mutable {
+        Vector<CaptureDevice> results;
 
-        ~CaptureDeviceAccumulator()
-        {
-            m_completionHandler(WTFMove(m_results));
-        }
+        results.appendVector(audioCaptureFactory().audioCaptureDeviceManager().captureDevices());
+        results.appendVector(videoCaptureFactory().videoCaptureDeviceManager().captureDevices());
+        results.appendVector(displayCaptureFactory().displayCaptureDeviceManager().captureDevices());
+        results.appendVector(audioCaptureFactory().speakerDevices());
 
-        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));
+        completion(WTFMove(results));
     });
-
-    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)
@@ -274,8 +245,32 @@
     }
 }
 
+void RealtimeMediaSourceCenter::enumerateDevices(bool shouldEnumerateCamera, bool shouldEnumerateDisplay, bool shouldEnumerateMicrophone, bool shouldEnumerateSpeakers, CompletionHandler<void()>&& callback)
+{
+    auto callbackAggregator = CallbackAggregator::create(WTFMove(callback));
+    if (shouldEnumerateCamera)
+        videoCaptureFactory().videoCaptureDeviceManager().computeCaptureDevices([callbackAggregator] { });
+    if (shouldEnumerateDisplay)
+        displayCaptureFactory().displayCaptureDeviceManager().computeCaptureDevices([callbackAggregator] { });
+    if (shouldEnumerateMicrophone)
+        audioCaptureFactory().audioCaptureDeviceManager().computeCaptureDevices([callbackAggregator] { });
+    if (shouldEnumerateSpeakers)
+        audioCaptureFactory().computeSpeakerDevices([callbackAggregator] { });
+}
+
 void RealtimeMediaSourceCenter::validateRequestConstraints(ValidConstraintsHandler&& validHandler, InvalidConstraintsHandler&& invalidHandler, const MediaStreamRequest& request, String&& deviceIdentifierHashSalt)
 {
+    bool shouldEnumerateCamera = request.videoConstraints.isValid;
+    bool shouldEnumerateDisplay = request.type == MediaStreamRequest::Type::DisplayMedia;
+    bool shouldEnumerateMicrophone = request.audioConstraints.isValid;
+    bool shouldEnumerateSpeakers = false;
+    enumerateDevices(shouldEnumerateCamera, shouldEnumerateDisplay, shouldEnumerateMicrophone, shouldEnumerateSpeakers, [this, validHandler = WTFMove(validHandler), invalidHandler = WTFMove(invalidHandler), request, deviceIdentifierHashSalt = WTFMove(deviceIdentifierHashSalt)]() mutable {
+        validateRequestConstraintsAfterEnumeration(WTFMove(validHandler), WTFMove(invalidHandler), request, WTFMove(deviceIdentifierHashSalt));
+    });
+}
+
+void RealtimeMediaSourceCenter::validateRequestConstraintsAfterEnumeration(ValidConstraintsHandler&& validHandler, InvalidConstraintsHandler&& invalidHandler, const MediaStreamRequest& request, String&& deviceIdentifierHashSalt)
+{
     struct {
         bool operator()(const DeviceInfo& a, const DeviceInfo& b)
         {

Modified: trunk/Source/WebCore/platform/mediastream/RealtimeMediaSourceCenter.h (277360 => 277361)


--- trunk/Source/WebCore/platform/mediastream/RealtimeMediaSourceCenter.h	2021-05-12 07:56:39 UTC (rev 277360)
+++ trunk/Source/WebCore/platform/mediastream/RealtimeMediaSourceCenter.h	2021-05-12 08:05:19 UTC (rev 277361)
@@ -115,6 +115,8 @@
 
     void getDisplayMediaDevices(const MediaStreamRequest&, Vector<DeviceInfo>&, String&);
     void getUserMediaDevices(const MediaStreamRequest&, String&&, Vector<DeviceInfo>& audioDevices, Vector<DeviceInfo>& videoDevices, String&);
+    void validateRequestConstraintsAfterEnumeration(ValidConstraintsHandler&&, InvalidConstraintsHandler&&, const MediaStreamRequest&, String&&);
+    void enumerateDevices(bool shouldEnumerateCamera, bool shouldEnumerateDisplay, bool shouldEnumerateMicrophone, bool shouldEnumerateSpeakers, CompletionHandler<void()>&&);
 
     RealtimeMediaSourceSupportedConstraints m_supportedConstraints;
 

Modified: trunk/Source/WebCore/platform/mediastream/RealtimeMediaSourceFactory.h (277360 => 277361)


--- trunk/Source/WebCore/platform/mediastream/RealtimeMediaSourceFactory.h	2021-05-12 07:56:39 UTC (rev 277360)
+++ trunk/Source/WebCore/platform/mediastream/RealtimeMediaSourceFactory.h	2021-05-12 08:05:19 UTC (rev 277361)
@@ -63,7 +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())); }
+    virtual void computeSpeakerDevices(CompletionHandler<void()>&& callback) const { callback(); }
 
     class ExtensiveObserver : public CanMakeWeakPtr<ExtensiveObserver> { };
     virtual void addExtensiveObserver(ExtensiveObserver&) { };

Modified: trunk/Source/WebCore/platform/mediastream/ios/AVAudioSessionCaptureDevice.mm (277360 => 277361)


--- trunk/Source/WebCore/platform/mediastream/ios/AVAudioSessionCaptureDevice.mm	2021-05-12 07:56:39 UTC (rev 277360)
+++ trunk/Source/WebCore/platform/mediastream/ios/AVAudioSessionCaptureDevice.mm	2021-05-12 08:05:19 UTC (rev 277361)
@@ -45,11 +45,8 @@
 }
 
 AVAudioSessionCaptureDevice::AVAudioSessionCaptureDevice(const String& persistentId, DeviceType type, const String& label, const String& groupId, bool isEnabled, bool isDefault, bool isMock)
-    : CaptureDevice(persistentId, type, label, groupId)
+    : CaptureDevice(persistentId, type, label, groupId, isEnabled, isDefault, isMock)
 {
-    setEnabled(isEnabled);
-    setIsDefault(isDefault);
-    setIsMockDevice(isMock);
 }
 
 AVAudioSessionCaptureDevice AVAudioSessionCaptureDevice::isolatedCopy() &&

Modified: trunk/Source/WebCore/platform/mediastream/ios/AVAudioSessionCaptureDeviceManager.h (277360 => 277361)


--- trunk/Source/WebCore/platform/mediastream/ios/AVAudioSessionCaptureDeviceManager.h	2021-05-12 07:56:39 UTC (rev 277360)
+++ trunk/Source/WebCore/platform/mediastream/ios/AVAudioSessionCaptureDeviceManager.h	2021-05-12 08:05:19 UTC (rev 277361)
@@ -47,7 +47,7 @@
     static AVAudioSessionCaptureDeviceManager& singleton();
 
     const Vector<CaptureDevice>& captureDevices() final;
-    void getCaptureDevices(CompletionHandler<void(Vector<CaptureDevice>&&)>&&) final;
+    void computeCaptureDevices(CompletionHandler<void()>&&) final;
     const Vector<CaptureDevice>& speakerDevices() const { return m_speakerDevices; }
     Optional<CaptureDevice> captureDeviceWithPersistentID(CaptureDevice::DeviceType, const String&);
 

Modified: trunk/Source/WebCore/platform/mediastream/ios/AVAudioSessionCaptureDeviceManager.mm (277360 => 277361)


--- trunk/Source/WebCore/platform/mediastream/ios/AVAudioSessionCaptureDeviceManager.mm	2021-05-12 07:56:39 UTC (rev 277360)
+++ trunk/Source/WebCore/platform/mediastream/ios/AVAudioSessionCaptureDeviceManager.mm	2021-05-12 08:05:19 UTC (rev 277361)
@@ -146,7 +146,7 @@
 
 void AVAudioSessionCaptureDeviceManager::scheduleUpdateCaptureDevices()
 {
-    getCaptureDevices([] (auto) { });
+    computeCaptureDevices([] { });
 }
 
 void AVAudioSessionCaptureDeviceManager::refreshAudioCaptureDevices()
@@ -166,7 +166,7 @@
     setAudioCaptureDevices(WTFMove(newAudioDevices).isolatedCopy());
 }
 
-void AVAudioSessionCaptureDeviceManager::getCaptureDevices(CompletionHandler<void(Vector<CaptureDevice>&&)>&& completion)
+void AVAudioSessionCaptureDeviceManager::computeCaptureDevices(CompletionHandler<void()>&& completion)
 {
     if (m_audioSessionState == AudioSessionState::Inactive) {
         m_audioSessionState = AudioSessionState::Active;
@@ -180,7 +180,7 @@
         auto newAudioDevices = retrieveAudioSessionCaptureDevices();
         callOnWebThreadOrDispatchAsyncOnMainThread(makeBlockPtr([this, completion = WTFMove(completion), newAudioDevices = WTFMove(newAudioDevices).isolatedCopy()] () mutable {
             setAudioCaptureDevices(WTFMove(newAudioDevices));
-            completion(copyToVector(*m_devices));
+            completion();
         }).get());
     });
 }

Modified: trunk/Source/WebCore/platform/mediastream/mac/AVCaptureDeviceManager.h (277360 => 277361)


--- trunk/Source/WebCore/platform/mediastream/mac/AVCaptureDeviceManager.h	2021-05-12 07:56:39 UTC (rev 277360)
+++ trunk/Source/WebCore/platform/mediastream/mac/AVCaptureDeviceManager.h	2021-05-12 08:05:19 UTC (rev 277361)
@@ -33,6 +33,7 @@
 #include "RealtimeMediaSourceSupportedConstraints.h"
 #include <wtf/NeverDestroyed.h>
 #include <wtf/RetainPtr.h>
+#include <wtf/WorkQueue.h>
 #include <wtf/text/WTFString.h>
 
 OBJC_CLASS AVCaptureDevice;
@@ -47,11 +48,9 @@
 class AVCaptureDeviceManager final : public CaptureDeviceManager {
     friend class NeverDestroyed<AVCaptureDeviceManager>;
 public:
-    const Vector<CaptureDevice>& captureDevices() final;
-
     static AVCaptureDeviceManager& singleton();
 
-    void refreshCaptureDevices();
+    void refreshCaptureDevices(CompletionHandler<void()>&& = [] { });
 
 private:
     static bool isAvailable();
@@ -59,15 +58,19 @@
     AVCaptureDeviceManager();
     ~AVCaptureDeviceManager() final;
 
+    void computeCaptureDevices(CompletionHandler<void()>&&) final;
+    const Vector<CaptureDevice>& captureDevices() final;
+
     void registerForDeviceNotifications();
-    Vector<CaptureDevice>& captureDevicesInternal();
     void updateCachedAVCaptureDevices();
-    bool isMatchingExistingCaptureDevice(AVCaptureDevice*);
+    Vector<CaptureDevice> retrieveCaptureDevices();
 
     RetainPtr<WebCoreAVCaptureDeviceManagerObserver> m_objcObserver;
     Vector<CaptureDevice> m_devices;
     RetainPtr<NSMutableArray> m_avCaptureDevices;
-    bool m_notifyWhenDeviceListChanges { false };
+    bool m_isInitialized { false };
+
+    Ref<WorkQueue> m_dispatchQueue;
 };
 
 } // namespace WebCore

Modified: trunk/Source/WebCore/platform/mediastream/mac/AVCaptureDeviceManager.mm (277360 => 277361)


--- trunk/Source/WebCore/platform/mediastream/mac/AVCaptureDeviceManager.mm	2021-05-12 07:56:39 UTC (rev 277360)
+++ trunk/Source/WebCore/platform/mediastream/mac/AVCaptureDeviceManager.mm	2021-05-12 08:05:19 UTC (rev 277361)
@@ -59,25 +59,23 @@
 
 namespace WebCore {
 
-
-Vector<CaptureDevice>& AVCaptureDeviceManager::captureDevicesInternal()
+void AVCaptureDeviceManager::computeCaptureDevices(CompletionHandler<void()>&& callback)
 {
-    if (!isAvailable())
-        return m_devices;
-
-    static bool firstTime = true;
-    if (firstTime) {
-        firstTime = false;
-        refreshCaptureDevices();
-        m_notifyWhenDeviceListChanges = true;
+    if (!m_isInitialized) {
+        refreshCaptureDevices([this, callback = WTFMove(callback)]() mutable {
+            m_isInitialized = true;
+            callback();
+        });
+        return;
     }
-
-    return m_devices;
+    callback();
 }
 
 const Vector<CaptureDevice>& AVCaptureDeviceManager::captureDevices()
 {
-    return captureDevicesInternal();
+    ASSERT(m_isInitialized);
+    RELEASE_LOG_ERROR_IF(!m_isInitialized, WebRTC, "Retrieving AVCaptureDeviceManager list before initialization");
+    return m_devices;
 }
 
 inline static bool deviceIsAvailable(AVCaptureDevice *device)
@@ -95,6 +93,7 @@
 
 void AVCaptureDeviceManager::updateCachedAVCaptureDevices()
 {
+    ASSERT(!isMainThread());
     auto* currentDevices = [PAL::getAVCaptureDeviceClass() devices];
     auto changedDevices = adoptNS([[NSMutableArray alloc] init]);
     for (AVCaptureDevice *cachedDevice in m_avCaptureDevices.get()) {
@@ -129,29 +128,17 @@
     return captureDevice;
 }
 
-bool AVCaptureDeviceManager::isMatchingExistingCaptureDevice(AVCaptureDevice *device)
-{
-    auto existingCaptureDevice = captureDeviceFromPersistentID(device.uniqueID);
-    if (!existingCaptureDevice)
-        return false;
-
-    return deviceIsAvailable(device) == existingCaptureDevice.enabled();
-}
-
-static inline bool isDefaultVideoCaptureDeviceFirst(const Vector<CaptureDevice>& devices, const String& defaultDeviceID)
-{
-    if (devices.isEmpty())
-        return false;
-    return devices[0].persistentId() == defaultDeviceID;
-}
-
 static inline bool isVideoDevice(AVCaptureDevice *device)
 {
     return [device hasMediaType:AVMediaTypeVideo] || [device hasMediaType:AVMediaTypeMuxed];
 }
 
-void AVCaptureDeviceManager::refreshCaptureDevices()
+Vector<CaptureDevice> AVCaptureDeviceManager::retrieveCaptureDevices()
 {
+    ASSERT(!isMainThread());
+    if (!isAvailable())
+        return { };
+
     if (!m_avCaptureDevices) {
         m_avCaptureDevices = adoptNS([[NSMutableArray alloc] init]);
         registerForDeviceNotifications();
@@ -178,31 +165,40 @@
     }
 #endif
 
-    bool deviceHasChanged = false;
     if (defaultVideoDevice) {
-        deviceList.append(toCaptureDevice(defaultVideoDevice));
-        deviceHasChanged = !isDefaultVideoCaptureDeviceFirst(captureDevices(), defaultVideoDevice.uniqueID);
+        auto device = toCaptureDevice(defaultVideoDevice);
+        device.setIsDefault(true);
+        deviceList.append(WTFMove(device));
     }
     for (AVCaptureDevice *platformDevice in currentDevices) {
-        if (!isVideoDevice(platformDevice))
-            continue;
-
-        if (!deviceHasChanged && !isMatchingExistingCaptureDevice(platformDevice))
-            deviceHasChanged = true;
-
-        if (platformDevice.uniqueID == defaultVideoDevice.uniqueID)
-            continue;
-
-        deviceList.append(toCaptureDevice(platformDevice));
+        if (isVideoDevice(platformDevice) && platformDevice.uniqueID != defaultVideoDevice.uniqueID)
+            deviceList.append(toCaptureDevice(platformDevice));
     }
+    return deviceList;
+}
 
-    if (deviceHasChanged || m_devices.size() != deviceList.size()) {
-        deviceHasChanged = true;
-        m_devices = WTFMove(deviceList);
-    }
+void AVCaptureDeviceManager::refreshCaptureDevices(CompletionHandler<void()>&& callback)
+{
+    m_dispatchQueue->dispatch([this, callback = WTFMove(callback)]() mutable {
+        RunLoop::main().dispatch([this, callback = WTFMove(callback), deviceList = retrieveCaptureDevices().isolatedCopy()]() mutable {            
+            bool deviceHasChanged = m_devices.size() != deviceList.size();
+            if (!deviceHasChanged) {
+                for (size_t cptr = 0; cptr < deviceList.size(); ++cptr) {
+                    if (m_devices[cptr].persistentId() != deviceList[cptr].persistentId() || m_devices[cptr].enabled() != deviceList[cptr].enabled()) {
+                        deviceHasChanged = true;
+                        break;
+                    }
+                }
+            }
 
-    if (m_notifyWhenDeviceListChanges && deviceHasChanged)
-        deviceChanged();
+            if (deviceHasChanged) {
+                m_devices = WTFMove(deviceList);
+                if (m_isInitialized)
+                    deviceChanged();
+            }
+            callback();
+        });
+    });
 }
 
 bool AVCaptureDeviceManager::isAvailable()
@@ -218,6 +214,7 @@
 
 AVCaptureDeviceManager::AVCaptureDeviceManager()
     : m_objcObserver(adoptNS([[WebCoreAVCaptureDeviceManagerObserver alloc] initWithCallback: this]))
+    , m_dispatchQueue(WorkQueue::create("com.apple.WebKit.AVCaptureDeviceManager"))
 {
 }
 
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to