Changeset 277361 in webkit
- Timestamp:
- May 12, 2021, 1:05:19 AM (5 years ago)
- Location:
- trunk/Source/WebCore
- Files:
-
- 11 edited
-
ChangeLog (modified) (1 diff)
-
platform/mediastream/CaptureDevice.h (modified) (3 diffs)
-
platform/mediastream/CaptureDeviceManager.h (modified) (1 diff)
-
platform/mediastream/RealtimeMediaSourceCenter.cpp (modified) (3 diffs)
-
platform/mediastream/RealtimeMediaSourceCenter.h (modified) (1 diff)
-
platform/mediastream/RealtimeMediaSourceFactory.h (modified) (1 diff)
-
platform/mediastream/ios/AVAudioSessionCaptureDevice.mm (modified) (1 diff)
-
platform/mediastream/ios/AVAudioSessionCaptureDeviceManager.h (modified) (1 diff)
-
platform/mediastream/ios/AVAudioSessionCaptureDeviceManager.mm (modified) (3 diffs)
-
platform/mediastream/mac/AVCaptureDeviceManager.h (modified) (3 diffs)
-
platform/mediastream/mac/AVCaptureDeviceManager.mm (modified) (6 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebCore/ChangeLog
r277358 r277361 1 2021-05-12 Youenn Fablet <youenn@apple.com> 2 3 Enumerate AVCaptureDevice list in a background thread 4 https://bugs.webkit.org/show_bug.cgi?id=225643 5 <rdar://problem/77820002> 6 7 Reviewed by Eric Carlson. 8 9 Enumerate AVCaptureDevice in a background queue asynchronously. 10 Delay getUserMedia and enumerateDevices until this is completed. 11 12 Update RealtimeMediaSourceCenter accordingly and introduce RealtimeMediaSourceCenter::enumerateDevices for that purpose. 13 Replace getCaptureDevices by computeCaptureDevices to do the async computation. 14 Continue using captureDevices() getters. 15 16 Manually tested. 17 18 * platform/mediastream/CaptureDevice.h: 19 (WebCore::CaptureDevice::CaptureDevice): 20 (WebCore::CaptureDevice::isolatedCopy): 21 * platform/mediastream/CaptureDeviceManager.h: 22 * platform/mediastream/RealtimeMediaSourceCenter.cpp: 23 (WebCore::RealtimeMediaSourceCenter::getMediaStreamDevices): 24 (WebCore::RealtimeMediaSourceCenter::enumerateDevices): 25 (WebCore::RealtimeMediaSourceCenter::validateRequestConstraints): 26 (WebCore::RealtimeMediaSourceCenter::validateRequestConstraintsAfterEnumeration): 27 * platform/mediastream/RealtimeMediaSourceCenter.h: 28 * platform/mediastream/RealtimeMediaSourceFactory.h: 29 (WebCore::AudioCaptureFactory::computeSpeakerDevices const): 30 * platform/mediastream/ios/AVAudioSessionCaptureDevice.mm: 31 (WebCore::AVAudioSessionCaptureDevice::AVAudioSessionCaptureDevice): 32 * platform/mediastream/ios/AVAudioSessionCaptureDeviceManager.h: 33 * platform/mediastream/ios/AVAudioSessionCaptureDeviceManager.mm: 34 (WebCore::AVAudioSessionCaptureDeviceManager::scheduleUpdateCaptureDevices): 35 (WebCore::AVAudioSessionCaptureDeviceManager::computeCaptureDevices): 36 * platform/mediastream/mac/AVCaptureDeviceManager.h: 37 * platform/mediastream/mac/AVCaptureDeviceManager.mm: 38 (WebCore::AVCaptureDeviceManager::computeCaptureDevices): 39 (WebCore::AVCaptureDeviceManager::captureDevices): 40 (WebCore::AVCaptureDeviceManager::updateCachedAVCaptureDevices): 41 (WebCore::AVCaptureDeviceManager::retrieveCaptureDevices): 42 (WebCore::AVCaptureDeviceManager::refreshCaptureDevices): 43 (WebCore::AVCaptureDeviceManager::AVCaptureDeviceManager): 44 1 45 2021-05-11 Cameron McCormack <heycam@apple.com> 2 46 -
trunk/Source/WebCore/platform/mediastream/CaptureDevice.h
r275871 r277361 34 34 enum class DeviceType { Unknown, Microphone, Speaker, Camera, Screen, Window }; 35 35 36 CaptureDevice(const String& persistentId, DeviceType type, const String& label, const String& groupId = emptyString() )36 CaptureDevice(const String& persistentId, DeviceType type, const String& label, const String& groupId = emptyString(), bool isEnabled = false, bool isDefault = false, bool isMock = false) 37 37 : m_persistentId(persistentId) 38 38 , m_type(type) 39 39 , m_label(label) 40 40 , m_groupId(groupId) 41 , m_enabled(isEnabled) 42 , m_default(isDefault) 43 , m_isMockDevice(isMock) 41 44 { 42 45 } … … 71 74 72 75 explicit operator bool() const { return m_type != DeviceType::Unknown; } 76 77 CaptureDevice isolatedCopy() &&; 73 78 74 79 #if ENABLE(MEDIA_STREAM) … … 159 164 160 165 return false; 166 } 167 168 inline CaptureDevice CaptureDevice::isolatedCopy() && 169 { 170 return { 171 WTFMove(m_persistentId).isolatedCopy(), 172 m_type, 173 WTFMove(m_label).isolatedCopy(), 174 WTFMove(m_groupId).isolatedCopy(), 175 m_enabled, 176 m_default, 177 m_isMockDevice 178 }; 161 179 } 162 180 -
trunk/Source/WebCore/platform/mediastream/CaptureDeviceManager.h
r271471 r277361 36 36 public: 37 37 virtual const Vector<CaptureDevice>& captureDevices() = 0; 38 virtual void getCaptureDevices(CompletionHandler<void(Vector<CaptureDevice>&&)>&& callback) { callback(copyToVector(captureDevices())); };38 virtual void computeCaptureDevices(CompletionHandler<void()>&& callback) { callback(); } 39 39 virtual Optional<CaptureDevice> captureDeviceWithPersistentID(CaptureDevice::DeviceType, const String&) { return WTF::nullopt; } 40 40 -
trunk/Source/WebCore/platform/mediastream/RealtimeMediaSourceCenter.cpp
r275871 r277361 39 39 #include "Logging.h" 40 40 #include "MediaStreamPrivate.h" 41 #include <wtf/CallbackAggregator.h> 41 42 #include <wtf/SHA1.h> 42 43 … … 120 121 void RealtimeMediaSourceCenter::getMediaStreamDevices(CompletionHandler<void(Vector<CaptureDevice>&&)>&& completion) 121 122 { 122 class CaptureDeviceAccumulator : public RefCounted<CaptureDeviceAccumulator> { 123 public: 124 static Ref<CaptureDeviceAccumulator> create(CompletionHandler<void(Vector<CaptureDevice>&&)>&& completion) 125 { 126 return adoptRef(*new CaptureDeviceAccumulator(WTFMove(completion))); 127 } 128 129 ~CaptureDeviceAccumulator() 130 { 131 m_completionHandler(WTFMove(m_results)); 132 } 133 134 CompletionHandler<void(Vector<CaptureDevice>&&)> accumulate() 135 { 136 return [this, protectedThis = makeRef(*this)] (Vector<CaptureDevice>&& result) { 137 m_results.appendVector(WTFMove(result)); 138 }; 139 } 140 141 private: 142 explicit CaptureDeviceAccumulator(CompletionHandler<void(Vector<CaptureDevice>&&)>&& completion) 143 : m_completionHandler(WTFMove(completion)) 144 { 145 } 146 147 CompletionHandler<void(Vector<CaptureDevice>&&)> m_completionHandler; 148 Vector<CaptureDevice> m_results; 149 }; 150 151 auto accumulator = CaptureDeviceAccumulator::create([completion = WTFMove(completion)] (auto&& devices) mutable { 152 devices.removeAllMatching([] (auto& captureDevice) { 153 return !captureDevice.enabled(); 154 }); 155 completion(WTFMove(devices)); 123 enumerateDevices(true, true, true, true, [this, completion = WTFMove(completion)]() mutable { 124 Vector<CaptureDevice> results; 125 126 results.appendVector(audioCaptureFactory().audioCaptureDeviceManager().captureDevices()); 127 results.appendVector(videoCaptureFactory().videoCaptureDeviceManager().captureDevices()); 128 results.appendVector(displayCaptureFactory().displayCaptureDeviceManager().captureDevices()); 129 results.appendVector(audioCaptureFactory().speakerDevices()); 130 131 completion(WTFMove(results)); 156 132 }); 157 158 audioCaptureFactory().audioCaptureDeviceManager().getCaptureDevices(accumulator->accumulate());159 videoCaptureFactory().videoCaptureDeviceManager().getCaptureDevices(accumulator->accumulate());160 displayCaptureFactory().displayCaptureDeviceManager().getCaptureDevices(accumulator->accumulate());161 audioCaptureFactory().getSpeakerDevices(accumulator->accumulate());162 133 } 163 134 … … 275 246 } 276 247 248 void RealtimeMediaSourceCenter::enumerateDevices(bool shouldEnumerateCamera, bool shouldEnumerateDisplay, bool shouldEnumerateMicrophone, bool shouldEnumerateSpeakers, CompletionHandler<void()>&& callback) 249 { 250 auto callbackAggregator = CallbackAggregator::create(WTFMove(callback)); 251 if (shouldEnumerateCamera) 252 videoCaptureFactory().videoCaptureDeviceManager().computeCaptureDevices([callbackAggregator] { }); 253 if (shouldEnumerateDisplay) 254 displayCaptureFactory().displayCaptureDeviceManager().computeCaptureDevices([callbackAggregator] { }); 255 if (shouldEnumerateMicrophone) 256 audioCaptureFactory().audioCaptureDeviceManager().computeCaptureDevices([callbackAggregator] { }); 257 if (shouldEnumerateSpeakers) 258 audioCaptureFactory().computeSpeakerDevices([callbackAggregator] { }); 259 } 260 277 261 void RealtimeMediaSourceCenter::validateRequestConstraints(ValidConstraintsHandler&& validHandler, InvalidConstraintsHandler&& invalidHandler, const MediaStreamRequest& request, String&& deviceIdentifierHashSalt) 262 { 263 bool shouldEnumerateCamera = request.videoConstraints.isValid; 264 bool shouldEnumerateDisplay = request.type == MediaStreamRequest::Type::DisplayMedia; 265 bool shouldEnumerateMicrophone = request.audioConstraints.isValid; 266 bool shouldEnumerateSpeakers = false; 267 enumerateDevices(shouldEnumerateCamera, shouldEnumerateDisplay, shouldEnumerateMicrophone, shouldEnumerateSpeakers, [this, validHandler = WTFMove(validHandler), invalidHandler = WTFMove(invalidHandler), request, deviceIdentifierHashSalt = WTFMove(deviceIdentifierHashSalt)]() mutable { 268 validateRequestConstraintsAfterEnumeration(WTFMove(validHandler), WTFMove(invalidHandler), request, WTFMove(deviceIdentifierHashSalt)); 269 }); 270 } 271 272 void RealtimeMediaSourceCenter::validateRequestConstraintsAfterEnumeration(ValidConstraintsHandler&& validHandler, InvalidConstraintsHandler&& invalidHandler, const MediaStreamRequest& request, String&& deviceIdentifierHashSalt) 278 273 { 279 274 struct { -
trunk/Source/WebCore/platform/mediastream/RealtimeMediaSourceCenter.h
r275871 r277361 116 116 void getDisplayMediaDevices(const MediaStreamRequest&, Vector<DeviceInfo>&, String&); 117 117 void getUserMediaDevices(const MediaStreamRequest&, String&&, Vector<DeviceInfo>& audioDevices, Vector<DeviceInfo>& videoDevices, String&); 118 void validateRequestConstraintsAfterEnumeration(ValidConstraintsHandler&&, InvalidConstraintsHandler&&, const MediaStreamRequest&, String&&); 119 void enumerateDevices(bool shouldEnumerateCamera, bool shouldEnumerateDisplay, bool shouldEnumerateMicrophone, bool shouldEnumerateSpeakers, CompletionHandler<void()>&&); 118 120 119 121 RealtimeMediaSourceSupportedConstraints m_supportedConstraints; -
trunk/Source/WebCore/platform/mediastream/RealtimeMediaSourceFactory.h
r271471 r277361 64 64 virtual CaptureDeviceManager& audioCaptureDeviceManager() = 0; 65 65 virtual const Vector<CaptureDevice>& speakerDevices() const = 0; 66 virtual void getSpeakerDevices(CompletionHandler<void(Vector<CaptureDevice>&&)>&& completion) const { completion(copyToVector(speakerDevices())); }66 virtual void computeSpeakerDevices(CompletionHandler<void()>&& callback) const { callback(); } 67 67 68 68 class ExtensiveObserver : public CanMakeWeakPtr<ExtensiveObserver> { }; -
trunk/Source/WebCore/platform/mediastream/ios/AVAudioSessionCaptureDevice.mm
r274819 r277361 46 46 47 47 AVAudioSessionCaptureDevice::AVAudioSessionCaptureDevice(const String& persistentId, DeviceType type, const String& label, const String& groupId, bool isEnabled, bool isDefault, bool isMock) 48 : CaptureDevice(persistentId, type, label, groupId )48 : CaptureDevice(persistentId, type, label, groupId, isEnabled, isDefault, isMock) 49 49 { 50 setEnabled(isEnabled);51 setIsDefault(isDefault);52 setIsMockDevice(isMock);53 50 } 54 51 -
trunk/Source/WebCore/platform/mediastream/ios/AVAudioSessionCaptureDeviceManager.h
r276880 r277361 48 48 49 49 const Vector<CaptureDevice>& captureDevices() final; 50 void getCaptureDevices(CompletionHandler<void(Vector<CaptureDevice>&&)>&&) final;50 void computeCaptureDevices(CompletionHandler<void()>&&) final; 51 51 const Vector<CaptureDevice>& speakerDevices() const { return m_speakerDevices; } 52 52 Optional<CaptureDevice> captureDeviceWithPersistentID(CaptureDevice::DeviceType, const String&); -
trunk/Source/WebCore/platform/mediastream/ios/AVAudioSessionCaptureDeviceManager.mm
r274819 r277361 147 147 void AVAudioSessionCaptureDeviceManager::scheduleUpdateCaptureDevices() 148 148 { 149 getCaptureDevices([] (auto){ });149 computeCaptureDevices([] { }); 150 150 } 151 151 … … 167 167 } 168 168 169 void AVAudioSessionCaptureDeviceManager:: getCaptureDevices(CompletionHandler<void(Vector<CaptureDevice>&&)>&& completion)169 void AVAudioSessionCaptureDeviceManager::computeCaptureDevices(CompletionHandler<void()>&& completion) 170 170 { 171 171 if (m_audioSessionState == AudioSessionState::Inactive) { … … 181 181 callOnWebThreadOrDispatchAsyncOnMainThread(makeBlockPtr([this, completion = WTFMove(completion), newAudioDevices = WTFMove(newAudioDevices).isolatedCopy()] () mutable { 182 182 setAudioCaptureDevices(WTFMove(newAudioDevices)); 183 completion( copyToVector(*m_devices));183 completion(); 184 184 }).get()); 185 185 }); -
trunk/Source/WebCore/platform/mediastream/mac/AVCaptureDeviceManager.h
r260415 r277361 34 34 #include <wtf/NeverDestroyed.h> 35 35 #include <wtf/RetainPtr.h> 36 #include <wtf/WorkQueue.h> 36 37 #include <wtf/text/WTFString.h> 37 38 … … 48 49 friend class NeverDestroyed<AVCaptureDeviceManager>; 49 50 public: 50 const Vector<CaptureDevice>& captureDevices() final;51 52 51 static AVCaptureDeviceManager& singleton(); 53 52 54 void refreshCaptureDevices( );53 void refreshCaptureDevices(CompletionHandler<void()>&& = [] { }); 55 54 56 55 private: … … 60 59 ~AVCaptureDeviceManager() final; 61 60 61 void computeCaptureDevices(CompletionHandler<void()>&&) final; 62 const Vector<CaptureDevice>& captureDevices() final; 63 62 64 void registerForDeviceNotifications(); 63 Vector<CaptureDevice>& captureDevicesInternal();64 65 void updateCachedAVCaptureDevices(); 65 bool isMatchingExistingCaptureDevice(AVCaptureDevice*);66 Vector<CaptureDevice> retrieveCaptureDevices(); 66 67 67 68 RetainPtr<WebCoreAVCaptureDeviceManagerObserver> m_objcObserver; 68 69 Vector<CaptureDevice> m_devices; 69 70 RetainPtr<NSMutableArray> m_avCaptureDevices; 70 bool m_notifyWhenDeviceListChanges { false }; 71 bool m_isInitialized { false }; 72 73 Ref<WorkQueue> m_dispatchQueue; 71 74 }; 72 75 -
trunk/Source/WebCore/platform/mediastream/mac/AVCaptureDeviceManager.mm
r271493 r277361 60 60 namespace WebCore { 61 61 62 63 Vector<CaptureDevice>& AVCaptureDeviceManager::captureDevicesInternal() 64 { 65 if (!isAvailable()) 66 return m_devices; 67 68 static bool firstTime = true; 69 if (firstTime) { 70 firstTime = false; 71 refreshCaptureDevices(); 72 m_notifyWhenDeviceListChanges = true; 73 } 74 62 void AVCaptureDeviceManager::computeCaptureDevices(CompletionHandler<void()>&& callback) 63 { 64 if (!m_isInitialized) { 65 refreshCaptureDevices([this, callback = WTFMove(callback)]() mutable { 66 m_isInitialized = true; 67 callback(); 68 }); 69 return; 70 } 71 callback(); 72 } 73 74 const Vector<CaptureDevice>& AVCaptureDeviceManager::captureDevices() 75 { 76 ASSERT(m_isInitialized); 77 RELEASE_LOG_ERROR_IF(!m_isInitialized, WebRTC, "Retrieving AVCaptureDeviceManager list before initialization"); 75 78 return m_devices; 76 }77 78 const Vector<CaptureDevice>& AVCaptureDeviceManager::captureDevices()79 {80 return captureDevicesInternal();81 79 } 82 80 … … 96 94 void AVCaptureDeviceManager::updateCachedAVCaptureDevices() 97 95 { 96 ASSERT(!isMainThread()); 98 97 auto* currentDevices = [PAL::getAVCaptureDeviceClass() devices]; 99 98 auto changedDevices = adoptNS([[NSMutableArray alloc] init]); … … 130 129 } 131 130 132 bool AVCaptureDeviceManager::isMatchingExistingCaptureDevice(AVCaptureDevice *device)133 {134 auto existingCaptureDevice = captureDeviceFromPersistentID(device.uniqueID);135 if (!existingCaptureDevice)136 return false;137 138 return deviceIsAvailable(device) == existingCaptureDevice.enabled();139 }140 141 static inline bool isDefaultVideoCaptureDeviceFirst(const Vector<CaptureDevice>& devices, const String& defaultDeviceID)142 {143 if (devices.isEmpty())144 return false;145 return devices[0].persistentId() == defaultDeviceID;146 }147 148 131 static inline bool isVideoDevice(AVCaptureDevice *device) 149 132 { … … 151 134 } 152 135 153 void AVCaptureDeviceManager::refreshCaptureDevices() 154 { 136 Vector<CaptureDevice> AVCaptureDeviceManager::retrieveCaptureDevices() 137 { 138 ASSERT(!isMainThread()); 139 if (!isAvailable()) 140 return { }; 141 155 142 if (!m_avCaptureDevices) { 156 143 m_avCaptureDevices = adoptNS([[NSMutableArray alloc] init]); … … 179 166 #endif 180 167 181 bool deviceHasChanged = false;182 168 if (defaultVideoDevice) { 183 deviceList.append(toCaptureDevice(defaultVideoDevice)); 184 deviceHasChanged = !isDefaultVideoCaptureDeviceFirst(captureDevices(), defaultVideoDevice.uniqueID); 169 auto device = toCaptureDevice(defaultVideoDevice); 170 device.setIsDefault(true); 171 deviceList.append(WTFMove(device)); 185 172 } 186 173 for (AVCaptureDevice *platformDevice in currentDevices) { 187 if (!isVideoDevice(platformDevice)) 188 continue; 189 190 if (!deviceHasChanged && !isMatchingExistingCaptureDevice(platformDevice)) 191 deviceHasChanged = true; 192 193 if (platformDevice.uniqueID == defaultVideoDevice.uniqueID) 194 continue; 195 196 deviceList.append(toCaptureDevice(platformDevice)); 197 } 198 199 if (deviceHasChanged || m_devices.size() != deviceList.size()) { 200 deviceHasChanged = true; 201 m_devices = WTFMove(deviceList); 202 } 203 204 if (m_notifyWhenDeviceListChanges && deviceHasChanged) 205 deviceChanged(); 174 if (isVideoDevice(platformDevice) && platformDevice.uniqueID != defaultVideoDevice.uniqueID) 175 deviceList.append(toCaptureDevice(platformDevice)); 176 } 177 return deviceList; 178 } 179 180 void AVCaptureDeviceManager::refreshCaptureDevices(CompletionHandler<void()>&& callback) 181 { 182 m_dispatchQueue->dispatch([this, callback = WTFMove(callback)]() mutable { 183 RunLoop::main().dispatch([this, callback = WTFMove(callback), deviceList = retrieveCaptureDevices().isolatedCopy()]() mutable { 184 bool deviceHasChanged = m_devices.size() != deviceList.size(); 185 if (!deviceHasChanged) { 186 for (size_t cptr = 0; cptr < deviceList.size(); ++cptr) { 187 if (m_devices[cptr].persistentId() != deviceList[cptr].persistentId() || m_devices[cptr].enabled() != deviceList[cptr].enabled()) { 188 deviceHasChanged = true; 189 break; 190 } 191 } 192 } 193 194 if (deviceHasChanged) { 195 m_devices = WTFMove(deviceList); 196 if (m_isInitialized) 197 deviceChanged(); 198 } 199 callback(); 200 }); 201 }); 206 202 } 207 203 … … 219 215 AVCaptureDeviceManager::AVCaptureDeviceManager() 220 216 : m_objcObserver(adoptNS([[WebCoreAVCaptureDeviceManagerObserver alloc] initWithCallback: this])) 217 , m_dispatchQueue(WorkQueue::create("com.apple.WebKit.AVCaptureDeviceManager")) 221 218 { 222 219 }
Note:
See TracChangeset
for help on using the changeset viewer.