Refactor: Allow WebKit2 to override the creation of RealtimeMediaSources
authorjer.noble@apple.com <jer.noble@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 14 Mar 2017 21:41:48 +0000 (21:41 +0000)
committerjer.noble@apple.com <jer.noble@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 14 Mar 2017 21:41:48 +0000 (21:41 +0000)
https://bugs.webkit.org/show_bug.cgi?id=169227

Reviewed by Eric Carlson.

Source/WebCore:

Allow clients of RealtimeMediaSourceCenter to specify a factory for creating
RealtimeMediaSources, to be used by subclasess of RealtimeMediaSourceCenter. Add virtual
methods to retrieve the "default" factories for the RealtimeMediaSourceCenter subclass. The
requires moving the creation of sources up from CaptureDeviceManager into
RealtimeMediaSourceCenterMac, and the addition of factory methods to AVAudioCaptureSource
and AVVideoCaptureSource.

* platform/mediastream/CaptureDeviceManager.cpp:
(CaptureDeviceManager::deviceWithUID):
(CaptureDeviceManager::bestSourcesForTypeAndConstraints): Deleted.
(CaptureDeviceManager::sourceWithUID): Deleted.
* platform/mediastream/CaptureDeviceManager.h:
* platform/mediastream/RealtimeMediaSource.h:
* platform/mediastream/RealtimeMediaSourceCenter.cpp:
(WebCore::RealtimeMediaSourceCenter::setAudioFactory):
(WebCore::RealtimeMediaSourceCenter::unsetAudioFactory):
(WebCore::RealtimeMediaSourceCenter::setVideoFactory):
(WebCore::RealtimeMediaSourceCenter::unsetVideoFactory):
* platform/mediastream/RealtimeMediaSourceCenter.h:
(WebCore::RealtimeMediaSourceCenter::audioFactory):
(WebCore::RealtimeMediaSourceCenter::videoFactory):
* platform/mediastream/mac/AVAudioCaptureSource.h:
* platform/mediastream/mac/AVAudioCaptureSource.mm:
(WebCore::AVAudioCaptureSource::factory):
* platform/mediastream/mac/AVCaptureDeviceManager.h:
* platform/mediastream/mac/AVCaptureDeviceManager.mm:
(WebCore::AVCaptureDeviceManager::createMediaSourceForCaptureDeviceWithConstraints): Deleted.
* platform/mediastream/mac/AVMediaCaptureSource.h:
* platform/mediastream/mac/AVVideoCaptureSource.h:
* platform/mediastream/mac/AVVideoCaptureSource.mm:
(WebCore::AVVideoCaptureSource::factory):
* platform/mediastream/mac/RealtimeMediaSourceCenterMac.cpp:
(WebCore::RealtimeMediaSourceCenterMac::RealtimeMediaSourceCenterMac):
(WebCore::RealtimeMediaSourceCenterMac::validateRequestConstraints):
(WebCore::RealtimeMediaSourceCenterMac::createMediaStream):
(WebCore::RealtimeMediaSourceCenterMac::bestSourcesForTypeAndConstraints):
(WebCore::RealtimeMediaSourceCenterMac::defaultAudioFactory):
(WebCore::RealtimeMediaSourceCenterMac::defaultVideoFactory):
* platform/mediastream/mac/RealtimeMediaSourceCenterMac.h:
* platform/mock/MockRealtimeAudioSource.cpp:
(WebCore::MockRealtimeAudioSource::factory):
* platform/mock/MockRealtimeAudioSource.h:
* platform/mock/MockRealtimeMediaSourceCenter.cpp:
(WebCore::MockRealtimeMediaSourceCenter::defaultAudioFactory):
(WebCore::MockRealtimeMediaSourceCenter::defaultVideoFactory):
* platform/mock/MockRealtimeMediaSourceCenter.h:
* platform/mock/MockRealtimeVideoSource.cpp:
(WebCore::MockRealtimeVideoSource::factory):
* platform/mock/MockRealtimeVideoSource.h:

Source/WebKit2:

* WebKit2.xcodeproj/project.pbxproj:
* WebProcess/WebCoreSupport/WebUserMediaClient.cpp:
(WebKit::WebUserMediaClient::WebUserMediaClient):
(WebKit::WebUserMediaClient::initializeFactories): Add empty non-Cocoa implementation.
* WebProcess/WebCoreSupport/WebUserMediaClient.h:
* WebProcess/WebCoreSupport/cocoa/WebUserMediaClientMac.mm: Added.
(WebKit::WebUserMediaClient::initializeFactories): Initialize a (for now) pass-through factory.

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

26 files changed:
Source/WebCore/ChangeLog
Source/WebCore/platform/mediastream/CaptureDeviceManager.cpp
Source/WebCore/platform/mediastream/CaptureDeviceManager.h
Source/WebCore/platform/mediastream/RealtimeMediaSource.h
Source/WebCore/platform/mediastream/RealtimeMediaSourceCenter.cpp
Source/WebCore/platform/mediastream/RealtimeMediaSourceCenter.h
Source/WebCore/platform/mediastream/mac/AVAudioCaptureSource.h
Source/WebCore/platform/mediastream/mac/AVAudioCaptureSource.mm
Source/WebCore/platform/mediastream/mac/AVCaptureDeviceManager.h
Source/WebCore/platform/mediastream/mac/AVCaptureDeviceManager.mm
Source/WebCore/platform/mediastream/mac/AVMediaCaptureSource.h
Source/WebCore/platform/mediastream/mac/AVVideoCaptureSource.h
Source/WebCore/platform/mediastream/mac/AVVideoCaptureSource.mm
Source/WebCore/platform/mediastream/mac/RealtimeMediaSourceCenterMac.cpp
Source/WebCore/platform/mediastream/mac/RealtimeMediaSourceCenterMac.h
Source/WebCore/platform/mock/MockRealtimeAudioSource.cpp
Source/WebCore/platform/mock/MockRealtimeAudioSource.h
Source/WebCore/platform/mock/MockRealtimeMediaSourceCenter.cpp
Source/WebCore/platform/mock/MockRealtimeMediaSourceCenter.h
Source/WebCore/platform/mock/MockRealtimeVideoSource.cpp
Source/WebCore/platform/mock/MockRealtimeVideoSource.h
Source/WebKit2/ChangeLog
Source/WebKit2/WebKit2.xcodeproj/project.pbxproj
Source/WebKit2/WebProcess/WebCoreSupport/WebUserMediaClient.cpp
Source/WebKit2/WebProcess/WebCoreSupport/WebUserMediaClient.h
Source/WebKit2/WebProcess/WebCoreSupport/cocoa/WebUserMediaClientMac.mm [new file with mode: 0644]

index f04a9e6..504687c 100644 (file)
@@ -1,3 +1,60 @@
+2017-03-06  Jer Noble  <jer.noble@apple.com>
+
+        Refactor: Allow WebKit2 to override the creation of RealtimeMediaSources
+        https://bugs.webkit.org/show_bug.cgi?id=169227
+
+        Reviewed by Eric Carlson.
+
+        Allow clients of RealtimeMediaSourceCenter to specify a factory for creating
+        RealtimeMediaSources, to be used by subclasess of RealtimeMediaSourceCenter. Add virtual
+        methods to retrieve the "default" factories for the RealtimeMediaSourceCenter subclass. The
+        requires moving the creation of sources up from CaptureDeviceManager into
+        RealtimeMediaSourceCenterMac, and the addition of factory methods to AVAudioCaptureSource
+        and AVVideoCaptureSource.
+
+        * platform/mediastream/CaptureDeviceManager.cpp:
+        (CaptureDeviceManager::deviceWithUID):
+        (CaptureDeviceManager::bestSourcesForTypeAndConstraints): Deleted.
+        (CaptureDeviceManager::sourceWithUID): Deleted.
+        * platform/mediastream/CaptureDeviceManager.h:
+        * platform/mediastream/RealtimeMediaSource.h:
+        * platform/mediastream/RealtimeMediaSourceCenter.cpp:
+        (WebCore::RealtimeMediaSourceCenter::setAudioFactory):
+        (WebCore::RealtimeMediaSourceCenter::unsetAudioFactory):
+        (WebCore::RealtimeMediaSourceCenter::setVideoFactory):
+        (WebCore::RealtimeMediaSourceCenter::unsetVideoFactory):
+        * platform/mediastream/RealtimeMediaSourceCenter.h:
+        (WebCore::RealtimeMediaSourceCenter::audioFactory):
+        (WebCore::RealtimeMediaSourceCenter::videoFactory):
+        * platform/mediastream/mac/AVAudioCaptureSource.h:
+        * platform/mediastream/mac/AVAudioCaptureSource.mm:
+        (WebCore::AVAudioCaptureSource::factory):
+        * platform/mediastream/mac/AVCaptureDeviceManager.h:
+        * platform/mediastream/mac/AVCaptureDeviceManager.mm:
+        (WebCore::AVCaptureDeviceManager::createMediaSourceForCaptureDeviceWithConstraints): Deleted.
+        * platform/mediastream/mac/AVMediaCaptureSource.h:
+        * platform/mediastream/mac/AVVideoCaptureSource.h:
+        * platform/mediastream/mac/AVVideoCaptureSource.mm:
+        (WebCore::AVVideoCaptureSource::factory):
+        * platform/mediastream/mac/RealtimeMediaSourceCenterMac.cpp:
+        (WebCore::RealtimeMediaSourceCenterMac::RealtimeMediaSourceCenterMac):
+        (WebCore::RealtimeMediaSourceCenterMac::validateRequestConstraints):
+        (WebCore::RealtimeMediaSourceCenterMac::createMediaStream):
+        (WebCore::RealtimeMediaSourceCenterMac::bestSourcesForTypeAndConstraints):
+        (WebCore::RealtimeMediaSourceCenterMac::defaultAudioFactory):
+        (WebCore::RealtimeMediaSourceCenterMac::defaultVideoFactory):
+        * platform/mediastream/mac/RealtimeMediaSourceCenterMac.h:
+        * platform/mock/MockRealtimeAudioSource.cpp:
+        (WebCore::MockRealtimeAudioSource::factory):
+        * platform/mock/MockRealtimeAudioSource.h:
+        * platform/mock/MockRealtimeMediaSourceCenter.cpp:
+        (WebCore::MockRealtimeMediaSourceCenter::defaultAudioFactory):
+        (WebCore::MockRealtimeMediaSourceCenter::defaultVideoFactory):
+        * platform/mock/MockRealtimeMediaSourceCenter.h:
+        * platform/mock/MockRealtimeVideoSource.cpp:
+        (WebCore::MockRealtimeVideoSource::factory):
+        * platform/mock/MockRealtimeVideoSource.h:
+
 2017-03-14  Dean Jackson  <dino@apple.com>
 
         Rename LayerTypeWebGLLayer and use it for both WebGL and WebGPU
index 0430fc6..719bb1e 100644 (file)
@@ -69,40 +69,7 @@ bool CaptureDeviceManager::captureDeviceFromDeviceID(const String& captureDevice
     return false;
 }
 
-Vector<String> CaptureDeviceManager::bestSourcesForTypeAndConstraints(RealtimeMediaSource::Type type, const MediaConstraints& constraints, String& invalidConstraint)
-{
-    Vector<RefPtr<RealtimeMediaSource>> bestSources;
-
-    struct {
-        bool operator()(RefPtr<RealtimeMediaSource> a, RefPtr<RealtimeMediaSource> b)
-        {
-            return a->fitnessScore() < b->fitnessScore();
-        }
-    } sortBasedOnFitnessScore;
-
-    ASSERT(type != RealtimeMediaSource::Type::None);
-    CaptureDevice::DeviceType deviceType = type == RealtimeMediaSource::Type::Video ? CaptureDevice::DeviceType::Video : CaptureDevice::DeviceType::Audio;
-    for (auto& captureDevice : captureDevices()) {
-        if (!captureDevice.enabled() || captureDevice.type() != deviceType)
-            continue;
-
-        if (auto captureSource = createMediaSourceForCaptureDeviceWithConstraints(captureDevice, &constraints, invalidConstraint))
-            bestSources.append(captureSource.leakRef());
-    }
-
-    Vector<String> sourceUIDs;
-    if (bestSources.isEmpty())
-        return sourceUIDs;
-
-    sourceUIDs.reserveInitialCapacity(bestSources.size());
-    std::sort(bestSources.begin(), bestSources.end(), sortBasedOnFitnessScore);
-    for (auto& device : bestSources)
-        sourceUIDs.uncheckedAppend(device->persistentID());
-
-    return sourceUIDs;
-}
-
-RefPtr<RealtimeMediaSource> CaptureDeviceManager::sourceWithUID(const String& deviceUID, RealtimeMediaSource::Type type, const MediaConstraints* constraints, String& invalidConstraint)
+std::optional<CaptureDevice> CaptureDeviceManager::deviceWithUID(const String& deviceUID, RealtimeMediaSource::Type type)
 {
     for (auto& captureDevice : captureDevices()) {
         CaptureDevice::DeviceType deviceType;
@@ -124,11 +91,10 @@ RefPtr<RealtimeMediaSource> CaptureDeviceManager::sourceWithUID(const String& de
         if (!captureDevice.enabled())
             continue;
 
-        if (auto mediaSource = createMediaSourceForCaptureDeviceWithConstraints(captureDevice, constraints, invalidConstraint))
-            return mediaSource;
+        return captureDevice;
     }
 
-    return nullptr;
+    return std::nullopt;
 }
 
 #endif // ENABLE(MEDIA_STREAM)
index 5d40099..8cbd456 100644 (file)
@@ -37,13 +37,10 @@ public:
     virtual Vector<CaptureDevice>& captureDevices() = 0;
     virtual void refreshCaptureDevices() { }
     virtual Vector<CaptureDevice> getSourcesInfo();
-    virtual Vector<String> bestSourcesForTypeAndConstraints(RealtimeMediaSource::Type, const MediaConstraints&, String&);
-    virtual RefPtr<RealtimeMediaSource> sourceWithUID(const String&, RealtimeMediaSource::Type, const MediaConstraints*, String&);
+    virtual std::optional<CaptureDevice> deviceWithUID(const String&, RealtimeMediaSource::Type);
 
 protected:
     virtual ~CaptureDeviceManager();
-    virtual RefPtr<RealtimeMediaSource> createMediaSourceForCaptureDeviceWithConstraints(const CaptureDevice&, const MediaConstraints*, String&) = 0;
-
     bool captureDeviceFromDeviceID(const String& captureDeviceID, CaptureDevice& source);
 };
 
index 1a911ad..acacdea 100644 (file)
@@ -54,6 +54,7 @@ class MediaTime;
 namespace WebCore {
 
 class AudioStreamDescription;
+class CaptureDevice;
 class FloatRect;
 class GraphicsContext;
 class MediaStreamPrivate;
@@ -82,6 +83,15 @@ public:
         virtual void audioSamplesAvailable(const MediaTime&, const PlatformAudioData&, const AudioStreamDescription&, size_t /*numberOfFrames*/) { }
     };
 
+    class CaptureFactory {
+    public:
+        virtual ~CaptureFactory() = default;
+        virtual RefPtr<RealtimeMediaSource> createMediaSourceForCaptureDeviceWithConstraints(const CaptureDevice&, const MediaConstraints*, String&) = 0;
+
+    protected:
+        CaptureFactory() = default;
+    };
+
     virtual ~RealtimeMediaSource() { }
 
     const String& id() const { return m_id; }
index 236f656..785d621 100644 (file)
@@ -66,6 +66,28 @@ RealtimeMediaSourceCenter::~RealtimeMediaSourceCenter()
 {
 }
 
+void RealtimeMediaSourceCenter::setAudioFactory(RealtimeMediaSource::CaptureFactory& factory)
+{
+    m_audioFactory = &factory;
+}
+
+void RealtimeMediaSourceCenter::unsetAudioFactory(RealtimeMediaSource::CaptureFactory& factory)
+{
+    if (m_audioFactory == &factory)
+        m_audioFactory = nullptr;
+}
+
+void RealtimeMediaSourceCenter::setVideoFactory(RealtimeMediaSource::CaptureFactory& factory)
+{
+    m_videoFactory = &factory;
+}
+
+void RealtimeMediaSourceCenter::unsetVideoFactory(RealtimeMediaSource::CaptureFactory& factory)
+{
+    if (m_videoFactory == &factory)
+        m_videoFactory = nullptr;
+}
+
 } // namespace WebCore
 
 #endif // ENABLE(MEDIA_STREAM)
index 81e8f43..61b7e9e 100644 (file)
@@ -65,11 +65,25 @@ public:
     
     virtual const RealtimeMediaSourceSupportedConstraints& supportedConstraints() { return m_supportedConstraints; }
 
+    virtual RealtimeMediaSource::CaptureFactory* defaultAudioFactory() { return nullptr; }
+    virtual RealtimeMediaSource::CaptureFactory* defaultVideoFactory() { return nullptr; }
+
+    WEBCORE_EXPORT void setAudioFactory(RealtimeMediaSource::CaptureFactory&);
+    WEBCORE_EXPORT void unsetAudioFactory(RealtimeMediaSource::CaptureFactory&);
+    RealtimeMediaSource::CaptureFactory* audioFactory() const { return m_audioFactory; }
+
+    WEBCORE_EXPORT void setVideoFactory(RealtimeMediaSource::CaptureFactory&);
+    WEBCORE_EXPORT void unsetVideoFactory(RealtimeMediaSource::CaptureFactory&);
+    RealtimeMediaSource::CaptureFactory* videoFactory() const { return m_videoFactory; }
+
 protected:
     RealtimeMediaSourceCenter();
 
     static RealtimeMediaSourceCenter& platformCenter();
     RealtimeMediaSourceSupportedConstraints m_supportedConstraints;
+
+    RealtimeMediaSource::CaptureFactory* m_audioFactory { nullptr };
+    RealtimeMediaSource::CaptureFactory* m_videoFactory { nullptr };
 };
 
 } // namespace WebCore
index 4549abb..6c8362f 100644 (file)
@@ -46,6 +46,8 @@ public:
 
     static RefPtr<AVMediaCaptureSource> create(AVCaptureDevice*, const AtomicString&, const MediaConstraints*, String&);
 
+    WEBCORE_EXPORT static CaptureFactory& factory();
+
 private:
     AVAudioCaptureSource(AVCaptureDevice*, const AtomicString&);
     virtual ~AVAudioCaptureSource();
index 5d7db31..8a7b6da 100644 (file)
@@ -30,6 +30,7 @@
 
 #import "AudioSampleBufferList.h"
 #import "CAAudioStreamDescription.h"
+#import "CaptureDevice.h"
 #import "Logging.h"
 #import "MediaConstraints.h"
 #import "MediaSampleAVFObjC.h"
@@ -41,6 +42,7 @@
 #import <AVFoundation/AVCaptureSession.h>
 #import <CoreAudio/CoreAudioTypes.h>
 #import <wtf/HashSet.h>
+#import <wtf/NeverDestroyed.h>
 
 #import "CoreMediaSoftLink.h"
 
@@ -75,6 +77,15 @@ SOFT_LINK_POINTER(AVFoundation, AVMediaTypeAudio, NSString *)
 
 namespace WebCore {
 
+class AVAudioCaptureSourceFactory : public RealtimeMediaSource::CaptureFactory {
+public:
+    RefPtr<RealtimeMediaSource> createMediaSourceForCaptureDeviceWithConstraints(const CaptureDevice& captureDevice, const MediaConstraints* constraints, String& invalidConstraint) final {
+        AVCaptureDeviceTypedef *device = [getAVCaptureDeviceClass() deviceWithUniqueID:captureDevice.persistentId()];
+        ASSERT(!device || (device && captureDevice.type() == CaptureDevice::DeviceType::Audio));
+        return device ? AVAudioCaptureSource::create(device, emptyString(), constraints, invalidConstraint) : nullptr;
+    }
+};
+
 RefPtr<AVMediaCaptureSource> AVAudioCaptureSource::create(AVCaptureDeviceTypedef* device, const AtomicString& id, const MediaConstraints* constraints, String& invalidConstraint)
 {
     auto source = adoptRef(new AVAudioCaptureSource(device, id));
@@ -89,6 +100,12 @@ RefPtr<AVMediaCaptureSource> AVAudioCaptureSource::create(AVCaptureDeviceTypedef
     return source;
 }
 
+RealtimeMediaSource::CaptureFactory& AVAudioCaptureSource::factory()
+{
+    static NeverDestroyed<AVAudioCaptureSourceFactory> factory;
+    return factory.get();
+}
+
 AVAudioCaptureSource::AVAudioCaptureSource(AVCaptureDeviceTypedef* device, const AtomicString& id)
     : AVMediaCaptureSource(device, id, Type::Audio)
 {
index 3c9b35b..24f73b0 100644 (file)
@@ -60,7 +60,6 @@ protected:
     AVCaptureDeviceManager();
     ~AVCaptureDeviceManager() final;
 
-    RefPtr<RealtimeMediaSource> createMediaSourceForCaptureDeviceWithConstraints(const CaptureDevice&, const MediaConstraints*, String&) final;
     void refreshCaptureDevices() final;
     void registerForDeviceNotifications();
 
index f0dbbbc..3f03683 100644 (file)
@@ -176,18 +176,6 @@ Vector<CaptureDevice> AVCaptureDeviceManager::getSourcesInfo()
     return CaptureDeviceManager::getSourcesInfo();
 }
 
-RefPtr<RealtimeMediaSource> AVCaptureDeviceManager::createMediaSourceForCaptureDeviceWithConstraints(const CaptureDevice& captureDevice, const MediaConstraints* constraints, String& invalidConstraint)
-{
-    AVCaptureDeviceTypedef *device = [getAVCaptureDeviceClass() deviceWithUniqueID:captureDevice.persistentId()];
-    if (!device)
-        return nullptr;
-
-    if (captureDevice.type() == CaptureDevice::DeviceType::Audio)
-        return AVAudioCaptureSource::create(device, emptyString(), constraints, invalidConstraint);
-
-    return AVVideoCaptureSource::create(device, emptyString(), constraints, invalidConstraint);
-}
-
 void AVCaptureDeviceManager::registerForDeviceNotifications()
 {
     [[NSNotificationCenter defaultCenter] addObserver:m_objcObserver.get() selector:@selector(deviceConnected:) name:AVCaptureDeviceWasConnectedNotification object:nil];
index cfe883a..fed9f6c 100644 (file)
@@ -40,6 +40,7 @@ OBJC_CLASS AVCaptureOutput;
 OBJC_CLASS AVCaptureSession;
 OBJC_CLASS AVCaptureVideoDataOutput;
 OBJC_CLASS NSError;
+OBJC_CLASS NSNotification;
 OBJC_CLASS WebCoreAVMediaCaptureSourceObserver;
 
 typedef struct opaqueCMSampleBuffer *CMSampleBufferRef;
index 802c3c1..1d6d6ef 100644 (file)
@@ -47,6 +47,8 @@ class AVVideoCaptureSource : public AVMediaCaptureSource {
 public:
     static RefPtr<AVMediaCaptureSource> create(AVCaptureDevice*, const AtomicString&, const MediaConstraints*, String&);
 
+    WEBCORE_EXPORT static CaptureFactory& factory();
+
     int32_t width() const { return m_width; }
     int32_t height() const { return m_height; }
 
index 8b94e3e..96e216e 100644 (file)
@@ -109,6 +109,15 @@ const OSType videoCaptureFormat = kCVPixelFormatType_420YpCbCr8Planar;
 const OSType videoCaptureFormat = kCVPixelFormatType_420YpCbCr8BiPlanarFullRange;
 #endif
 
+class AVVideoCaptureSourceFactory : public RealtimeMediaSource::CaptureFactory {
+public:
+    RefPtr<RealtimeMediaSource> createMediaSourceForCaptureDeviceWithConstraints(const CaptureDevice& captureDevice, const MediaConstraints* constraints, String& invalidConstraint) final {
+        AVCaptureDeviceTypedef *device = [getAVCaptureDeviceClass() deviceWithUniqueID:captureDevice.persistentId()];
+        ASSERT(!device || (captureDevice.type() == CaptureDevice::DeviceType::Video));
+        return device ? AVVideoCaptureSource::create(device, emptyString(), constraints, invalidConstraint) : nullptr;
+    }
+};
+
 RefPtr<AVMediaCaptureSource> AVVideoCaptureSource::create(AVCaptureDeviceTypedef* device, const AtomicString& id, const MediaConstraints* constraints, String& invalidConstraint)
 {
     auto source = adoptRef(new AVVideoCaptureSource(device, id));
@@ -123,6 +132,12 @@ RefPtr<AVMediaCaptureSource> AVVideoCaptureSource::create(AVCaptureDeviceTypedef
     return source;
 }
 
+RealtimeMediaSource::CaptureFactory& AVVideoCaptureSource::factory()
+{
+    static NeverDestroyed<AVVideoCaptureSourceFactory> factory;
+    return factory.get();
+}
+
 AVVideoCaptureSource::AVVideoCaptureSource(AVCaptureDeviceTypedef* device, const AtomicString& id)
     : AVMediaCaptureSource(device, id, Type::Video)
 {
index 1ec0cc3..ef8adc1 100644 (file)
@@ -33,7 +33,9 @@
 #if ENABLE(MEDIA_STREAM)
 #include "RealtimeMediaSourceCenterMac.h"
 
+#include "AVAudioCaptureSource.h"
 #include "AVCaptureDeviceManager.h"
+#include "AVVideoCaptureSource.h"
 #include "Logging.h"
 #include "MediaStreamPrivate.h"
 #include <wtf/MainThread.h>
@@ -60,6 +62,9 @@ RealtimeMediaSourceCenterMac::RealtimeMediaSourceCenterMac()
     m_supportedConstraints.setSupportsEchoCancellation(false);
     m_supportedConstraints.setSupportsDeviceId(true);
     m_supportedConstraints.setSupportsGroupId(true);
+
+    m_audioFactory = &AVAudioCaptureSource::factory();
+    m_videoFactory = &AVVideoCaptureSource::factory();
 }
 
 RealtimeMediaSourceCenterMac::~RealtimeMediaSourceCenterMac()
@@ -73,7 +78,7 @@ void RealtimeMediaSourceCenterMac::validateRequestConstraints(ValidConstraintsHa
     String invalidConstraint;
 
     if (audioConstraints.isValid()) {
-        audioSourceUIDs = AVCaptureDeviceManager::singleton().bestSourcesForTypeAndConstraints(RealtimeMediaSource::Type::Audio, audioConstraints, invalidConstraint);
+        audioSourceUIDs = bestSourcesForTypeAndConstraints(RealtimeMediaSource::Type::Audio, audioConstraints, invalidConstraint);
         if (!invalidConstraint.isEmpty()) {
             invalidHandler(invalidConstraint);
             return;
@@ -81,7 +86,7 @@ void RealtimeMediaSourceCenterMac::validateRequestConstraints(ValidConstraintsHa
     }
 
     if (videoConstraints.isValid()) {
-        videoSourceUIDs = AVCaptureDeviceManager::singleton().bestSourcesForTypeAndConstraints(RealtimeMediaSource::Type::Video, videoConstraints, invalidConstraint);
+        videoSourceUIDs = bestSourcesForTypeAndConstraints(RealtimeMediaSource::Type::Video, videoConstraints, invalidConstraint);
         if (!invalidConstraint.isEmpty()) {
             invalidHandler(invalidConstraint);
             return;
@@ -98,23 +103,26 @@ void RealtimeMediaSourceCenterMac::createMediaStream(NewMediaStreamHandler compl
     String invalidConstraint;
 
     if (!audioDeviceID.isEmpty()) {
-        auto audioSource = AVCaptureDeviceManager::singleton().sourceWithUID(audioDeviceID, RealtimeMediaSource::Type::Audio, audioConstraints, invalidConstraint);
+        auto audioDevice = AVCaptureDeviceManager::singleton().deviceWithUID(audioDeviceID, RealtimeMediaSource::Type::Audio);
+        if (audioDevice && m_audioFactory) {
+            if (auto audioSource = m_audioFactory->createMediaSourceForCaptureDeviceWithConstraints(audioDevice.value(), audioConstraints, invalidConstraint))
+                audioSources.append(audioSource.releaseNonNull());
 #if !LOG_DISABLED
-        if (!invalidConstraint.isEmpty())
-            LOG(Media, "RealtimeMediaSourceCenterMac::createMediaStream(%p), audio constraints failed to apply: %s", this, invalidConstraint.utf8().data());
+            if (!invalidConstraint.isEmpty())
+                LOG(Media, "RealtimeMediaSourceCenterMac::createMediaStream(%p), audio constraints failed to apply: %s", this, invalidConstraint.utf8().data());
 #endif
-
-        if (audioSource)
-            audioSources.append(audioSource.releaseNonNull());
+        }
     }
     if (!videoDeviceID.isEmpty()) {
-        auto videoSource = AVCaptureDeviceManager::singleton().sourceWithUID(videoDeviceID, RealtimeMediaSource::Type::Video, videoConstraints, invalidConstraint);
+        auto videoDevice = AVCaptureDeviceManager::singleton().deviceWithUID(videoDeviceID, RealtimeMediaSource::Type::Video);
+        if (videoDevice && m_videoFactory) {
+            if (auto videoSource = m_videoFactory->createMediaSourceForCaptureDeviceWithConstraints(videoDevice.value(), videoConstraints, invalidConstraint))
+                videoSources.append(videoSource.releaseNonNull());
 #if !LOG_DISABLED
         if (!invalidConstraint.isEmpty())
             LOG(Media, "RealtimeMediaSourceCenterMac::createMediaStream(%p), video constraints failed to apply: %s", this, invalidConstraint.utf8().data());
 #endif
-        if (videoSource)
-            videoSources.append(videoSource.releaseNonNull());
+        }
     }
 
     if (videoSources.isEmpty() && audioSources.isEmpty())
@@ -128,6 +136,52 @@ Vector<CaptureDevice> RealtimeMediaSourceCenterMac::getMediaStreamDevices()
     return AVCaptureDeviceManager::singleton().getSourcesInfo();
 }
 
+Vector<String> RealtimeMediaSourceCenterMac::bestSourcesForTypeAndConstraints(RealtimeMediaSource::Type type, const MediaConstraints& constraints, String& invalidConstraint)
+{
+    Vector<RefPtr<RealtimeMediaSource>> bestSources;
+
+    struct {
+        bool operator()(RefPtr<RealtimeMediaSource> a, RefPtr<RealtimeMediaSource> b)
+        {
+            return a->fitnessScore() < b->fitnessScore();
+        }
+    } sortBasedOnFitnessScore;
+
+    CaptureDevice::DeviceType deviceType = type == RealtimeMediaSource::Type::Video ? CaptureDevice::DeviceType::Video : CaptureDevice::DeviceType::Audio;
+    for (auto& captureDevice : getMediaStreamDevices()) {
+        if (!captureDevice.enabled() || captureDevice.type() != deviceType)
+            continue;
+
+        RealtimeMediaSource::CaptureFactory* factory = type == RealtimeMediaSource::Type::Video ? m_videoFactory : m_audioFactory;
+        if (!factory)
+            continue;
+
+        if (auto captureSource = factory->createMediaSourceForCaptureDeviceWithConstraints(captureDevice, &constraints, invalidConstraint))
+            bestSources.append(captureSource.leakRef());
+    }
+
+    Vector<String> sourceUIDs;
+    if (bestSources.isEmpty())
+        return sourceUIDs;
+
+    sourceUIDs.reserveInitialCapacity(bestSources.size());
+    std::sort(bestSources.begin(), bestSources.end(), sortBasedOnFitnessScore);
+    for (auto& device : bestSources)
+        sourceUIDs.uncheckedAppend(device->persistentID());
+
+    return sourceUIDs;
+}
+
+RealtimeMediaSource::CaptureFactory* RealtimeMediaSourceCenterMac::defaultAudioFactory()
+{
+    return &AVAudioCaptureSource::factory();
+}
+
+RealtimeMediaSource::CaptureFactory* RealtimeMediaSourceCenterMac::defaultVideoFactory()
+{
+    return &AVVideoCaptureSource::factory();
+}
+
 } // namespace WebCore
 
 #endif // ENABLE(MEDIA_STREAM)
index 6149f1e..76bc827 100644 (file)
@@ -50,6 +50,11 @@ private:
     void validateRequestConstraints(ValidConstraintsHandler validHandler, InvalidConstraintsHandler invalidHandler, const MediaConstraints& audioConstraints, const MediaConstraints& videoConstraints) final;
     void createMediaStream(NewMediaStreamHandler, const String& audioDeviceID, const String& videoDeviceID, const MediaConstraints* audioConstraints, const MediaConstraints* videoConstraints) final;
     Vector<CaptureDevice> getMediaStreamDevices() final;
+
+    Vector<String> bestSourcesForTypeAndConstraints(RealtimeMediaSource::Type, const MediaConstraints&, String& invalidConstraint);
+
+    RealtimeMediaSource::CaptureFactory* defaultAudioFactory() final;
+    RealtimeMediaSource::CaptureFactory* defaultVideoFactory() final;
 };
 
 } // namespace WebCore
index 0c4877b..6c4b052 100644 (file)
@@ -32,6 +32,7 @@
 #include "MockRealtimeAudioSource.h"
 
 #if ENABLE(MEDIA_STREAM)
+#include "CaptureDevice.h"
 #include "Logging.h"
 #include "MediaConstraints.h"
 #include "NotImplemented.h"
 
 namespace WebCore {
 
+class MockRealtimeAudioSourceFactory : public RealtimeMediaSource::CaptureFactory {
+public:
+    RefPtr<RealtimeMediaSource> createMediaSourceForCaptureDeviceWithConstraints(const CaptureDevice& captureDevice, const MediaConstraints* constraints, String&) final {
+        if (captureDevice.type() == CaptureDevice::DeviceType::Audio)
+            return MockRealtimeAudioSource::create(captureDevice.label(), constraints);
+        return nullptr;
+    }
+};
+
 #if !PLATFORM(MAC) && !PLATFORM(IOS)
 RefPtr<MockRealtimeAudioSource> MockRealtimeAudioSource::create(const String& name, const MediaConstraints* constraints)
 {
@@ -57,7 +67,13 @@ RefPtr<MockRealtimeAudioSource> MockRealtimeAudioSource::createMuted(const Strin
     return source;
 }
 #endif
-    
+
+RealtimeMediaSource::CaptureFactory& MockRealtimeAudioSource::factory()
+{
+    NeverDestroyed<MockRealtimeAudioSourceFactory> factory;
+    return factory.get();
+}
+
 MockRealtimeAudioSource::MockRealtimeAudioSource(const String& name)
     : MockRealtimeMediaSource(createCanonicalUUIDString(), RealtimeMediaSource::Type::Audio, name)
     , m_timer(RunLoop::current(), this, &MockRealtimeAudioSource::tick)
index b7e0008..6e8d0ce 100644 (file)
@@ -45,6 +45,8 @@ public:
     static RefPtr<MockRealtimeAudioSource> create(const String&, const MediaConstraints*);
     static RefPtr<MockRealtimeAudioSource> createMuted(const String& name);
 
+    static CaptureFactory& factory();
+
     virtual ~MockRealtimeAudioSource() = default;
 
 protected:
index bda24d5..697139a 100644 (file)
@@ -131,6 +131,17 @@ Vector<CaptureDevice> MockRealtimeMediaSourceCenter::getMediaStreamDevices()
     return sources;
 }
 
+RealtimeMediaSource::CaptureFactory* MockRealtimeMediaSourceCenter::defaultAudioFactory()
+{
+    return &MockRealtimeAudioSource::factory();
+}
+
+RealtimeMediaSource::CaptureFactory* MockRealtimeMediaSourceCenter::defaultVideoFactory()
+{
+    return &MockRealtimeVideoSource::factory();
+}
+
+
 } // namespace WebCore
 
 #endif // ENABLE(MEDIA_STREAM)
index b5f7645..cde650f 100644 (file)
@@ -44,6 +44,9 @@ private:
     void validateRequestConstraints(ValidConstraintsHandler validHandler, InvalidConstraintsHandler invalidHandler, const MediaConstraints& audioConstraints, const MediaConstraints& videoConstraints) final;
     Vector<CaptureDevice> getMediaStreamDevices() final;
     void createMediaStream(NewMediaStreamHandler, const String& audioDeviceID, const String& videoDeviceID, const MediaConstraints* audioConstraints, const MediaConstraints* videoConstraints) final;
+
+    RealtimeMediaSource::CaptureFactory* defaultAudioFactory() final;
+    RealtimeMediaSource::CaptureFactory* defaultVideoFactory() final;
 };
 
 }
index d10a243..043de43 100644 (file)
@@ -32,6 +32,7 @@
 #include "MockRealtimeVideoSource.h"
 
 #if ENABLE(MEDIA_STREAM)
+#include "CaptureDevice.h"
 #include "GraphicsContext.h"
 #include "ImageBuffer.h"
 #include "IntRect.h"
 
 namespace WebCore {
 
+class MockRealtimeVideoSourceFactory : public RealtimeMediaSource::CaptureFactory {
+public:
+    RefPtr<RealtimeMediaSource> createMediaSourceForCaptureDeviceWithConstraints(const CaptureDevice& captureDevice, const MediaConstraints* constraints, String&) final {
+        if (captureDevice.type() == CaptureDevice::DeviceType::Video)
+            return MockRealtimeVideoSource::create(captureDevice.label(), constraints);
+        return nullptr;
+    }
+};
+
 #if !PLATFORM(MAC) && !PLATFORM(IOS)
 RefPtr<MockRealtimeVideoSource> MockRealtimeVideoSource::create(const String& name, const MediaConstraints* constraints)
 {
@@ -65,6 +75,12 @@ RefPtr<MockRealtimeVideoSource> MockRealtimeVideoSource::createMuted(const Strin
 }
 #endif
 
+RealtimeMediaSource::CaptureFactory& MockRealtimeVideoSource::factory()
+{
+    NeverDestroyed<MockRealtimeVideoSourceFactory> factory;
+    return factory.get();
+}
+
 MockRealtimeVideoSource::MockRealtimeVideoSource(const String& name)
     : MockRealtimeMediaSource(createCanonicalUUIDString(), RealtimeMediaSource::Type::Video, name)
     , m_timer(RunLoop::current(), this, &MockRealtimeVideoSource::generateFrame)
index 81e13cb..662f031 100644 (file)
@@ -49,6 +49,8 @@ public:
     static RefPtr<MockRealtimeVideoSource> create(const String&, const MediaConstraints*);
     static RefPtr<MockRealtimeVideoSource> createMuted(const String& name);
 
+    static CaptureFactory& factory();
+
     virtual ~MockRealtimeVideoSource() { }
 
 protected:
index 67cf07f..c0b27e7 100644 (file)
@@ -1,3 +1,18 @@
+2017-03-06  Jer Noble  <jer.noble@apple.com>
+
+        Refactor: Allow WebKit2 to override the creation of RealtimeMediaSources
+        https://bugs.webkit.org/show_bug.cgi?id=169227
+
+        Reviewed by Eric Carlson.
+
+        * WebKit2.xcodeproj/project.pbxproj:
+        * WebProcess/WebCoreSupport/WebUserMediaClient.cpp:
+        (WebKit::WebUserMediaClient::WebUserMediaClient):
+        (WebKit::WebUserMediaClient::initializeFactories): Add empty non-Cocoa implementation.
+        * WebProcess/WebCoreSupport/WebUserMediaClient.h:
+        * WebProcess/WebCoreSupport/cocoa/WebUserMediaClientMac.mm: Added.
+        (WebKit::WebUserMediaClient::initializeFactories): Initialize a (for now) pass-through factory.
+
 2017-03-14  Dean Jackson  <dino@apple.com>
 
         Rename LayerTypeWebGLLayer and use it for both WebGL and WebGPU
index ef887dd..13e41c6 100644 (file)
                CD4B4D9D1E765E0000D27092 /* SharedRingBufferStorage.h in Headers */ = {isa = PBXBuildFile; fileRef = CD4B4D9B1E765E0000D27092 /* SharedRingBufferStorage.h */; };
                CD5C66A0134B9D38004FE2A8 /* InjectedBundlePageFullScreenClient.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CD5C669E134B9D36004FE2A8 /* InjectedBundlePageFullScreenClient.cpp */; };
                CD5C66A1134B9D38004FE2A8 /* InjectedBundlePageFullScreenClient.h in Headers */ = {isa = PBXBuildFile; fileRef = CD5C669F134B9D37004FE2A8 /* InjectedBundlePageFullScreenClient.h */; };
+               CD6178141E6DE9A000FDA57D /* WebUserMediaClientMac.mm in Sources */ = {isa = PBXBuildFile; fileRef = CD6178121E6DE9A000FDA57D /* WebUserMediaClientMac.mm */; };
                CD6F75F4131B66D000D6B21E /* WebFullScreenManagerProxy.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CD73BA3E131A2E8A00EEDED2 /* WebFullScreenManagerProxy.cpp */; };
                CD73BA47131ACC9A00EEDED2 /* WebFullScreenManagerProxyMessageReceiver.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CD73BA45131ACC8800EEDED2 /* WebFullScreenManagerProxyMessageReceiver.cpp */; };
                CD73BA4E131ACDB700EEDED2 /* WebFullScreenManagerMessageReceiver.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CD73BA48131ACD8E00EEDED2 /* WebFullScreenManagerMessageReceiver.cpp */; };
                CD4B4D9B1E765E0000D27092 /* SharedRingBufferStorage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SharedRingBufferStorage.h; sourceTree = "<group>"; };
                CD5C669E134B9D36004FE2A8 /* InjectedBundlePageFullScreenClient.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = InjectedBundlePageFullScreenClient.cpp; sourceTree = "<group>"; };
                CD5C669F134B9D37004FE2A8 /* InjectedBundlePageFullScreenClient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InjectedBundlePageFullScreenClient.h; sourceTree = "<group>"; };
+               CD6178121E6DE9A000FDA57D /* WebUserMediaClientMac.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = WebUserMediaClientMac.mm; path = cocoa/WebUserMediaClientMac.mm; sourceTree = "<group>"; };
                CD73BA37131A29FE00EEDED2 /* WebFullScreenManager.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = WebFullScreenManager.cpp; path = FullScreen/WebFullScreenManager.cpp; sourceTree = "<group>"; };
                CD73BA38131A29FE00EEDED2 /* WebFullScreenManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = WebFullScreenManager.h; path = FullScreen/WebFullScreenManager.h; sourceTree = "<group>"; };
                CD73BA39131A29FE00EEDED2 /* WebFullScreenManager.messages.in */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = WebFullScreenManager.messages.in; path = FullScreen/WebFullScreenManager.messages.in; sourceTree = "<group>"; };
                BC032D5D10F437220058C15A /* WebCoreSupport */ = {
                        isa = PBXGroup;
                        children = (
+                               CD6178111E6DE98000FDA57D /* cocoa */,
                                2D28F3DF1885CCB4004B9EAE /* ios */,
                                BC111ADE112F5B9A00337BAB /* mac */,
                                1A7284441959ED100007BCE5 /* SessionStateConversion.cpp */,
                        name = forms;
                        sourceTree = "<group>";
                };
+               CD6178111E6DE98000FDA57D /* cocoa */ = {
+                       isa = PBXGroup;
+                       children = (
+                               CD6178121E6DE9A000FDA57D /* WebUserMediaClientMac.mm */,
+                       );
+                       name = cocoa;
+                       sourceTree = "<group>";
+               };
                CD73BA3D131A2A2100EEDED2 /* FullScreen */ = {
                        isa = PBXGroup;
                        children = (
                                753E3E0D1887398500188496 /* SessionTracker.cpp in Sources */,
                                1A6420E412DCE2FF00CAAE2C /* ShareableBitmap.cpp in Sources */,
                                C01A260112662F2100C9ED55 /* ShareableBitmapCG.cpp in Sources */,
+                               CD6178141E6DE9A000FDA57D /* WebUserMediaClientMac.mm in Sources */,
                                51217460164C20E30037A5C1 /* ShareableResource.cpp in Sources */,
                                4450AEC01DC3FAE5009943F2 /* SharedMemoryCocoa.cpp in Sources */,
                                2DAF06D718BD1A470081CEB1 /* SmartMagnificationController.mm in Sources */,
index 362202e..aaded34 100644 (file)
@@ -33,6 +33,7 @@ namespace WebKit {
 WebUserMediaClient::WebUserMediaClient(WebPage& page)
     : m_page(page)
 {
+    initializeFactories();
 }
 
 void WebUserMediaClient::pageDestroyed()
@@ -60,6 +61,13 @@ void WebUserMediaClient::cancelMediaDevicesEnumerationRequest(MediaDevicesEnumer
     m_page.userMediaPermissionRequestManager().cancelMediaDevicesEnumeration(request);
 }
 
+#if !PLATFORM(COCOA)
+void WebUserMediaClient::initializeFactories()
+{
+
+}
+#endif
+
 } // namespace WebKit;
 
 #endif // MEDIA_STREAM
index 84d4262..a6e3132 100644 (file)
@@ -42,6 +42,8 @@ private:
     void enumerateMediaDevices(WebCore::MediaDevicesEnumerationRequest&) final;
     void cancelMediaDevicesEnumerationRequest(WebCore::MediaDevicesEnumerationRequest&) final;
 
+    void initializeFactories();
+
     WebPage& m_page;
 };
 
diff --git a/Source/WebKit2/WebProcess/WebCoreSupport/cocoa/WebUserMediaClientMac.mm b/Source/WebKit2/WebProcess/WebCoreSupport/cocoa/WebUserMediaClientMac.mm
new file mode 100644 (file)
index 0000000..a8df2f1
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2017 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "WebUserMediaClient.h"
+
+#if ENABLE(MEDIA_STREAM) && PLATFORM(COCOA)
+
+#import <WebCore/RealtimeMediaSourceCenter.h>
+#import <wtf/NeverDestroyed.h>
+
+using namespace WebCore;
+
+namespace WebKit {
+
+class WebUserMediaClientAudioFactory final : public RealtimeMediaSource::CaptureFactory {
+public:
+    static WebUserMediaClientAudioFactory& singleton()
+    {
+        static NeverDestroyed<WebUserMediaClientAudioFactory> factory;
+        return factory;
+    }
+
+private:
+    RefPtr<RealtimeMediaSource> createMediaSourceForCaptureDeviceWithConstraints(const CaptureDevice& device, const MediaConstraints* constraints, String& invalidConstraints) final {
+        auto* factory = RealtimeMediaSourceCenter::singleton().defaultAudioFactory();
+        return factory ? factory->createMediaSourceForCaptureDeviceWithConstraints(device, constraints, invalidConstraints) : nullptr;
+    }
+};
+
+void WebUserMediaClient::initializeFactories()
+{
+    static dispatch_once_t onceToken;
+    dispatch_once(&onceToken, ^ {
+        WebCore::RealtimeMediaSourceCenter::singleton().setAudioFactory(WebUserMediaClientAudioFactory::singleton());
+    });
+}
+
+}
+
+#endif