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"))
{
}