Title: [192838] trunk/Source/WebCore
Revision
192838
Author
wenson_hs...@apple.com
Date
2015-11-30 15:48:42 -0800 (Mon, 30 Nov 2015)

Log Message

Split platform-independent logic in AVCaptureDeviceManager out into a new class
https://bugs.webkit.org/show_bug.cgi?id=151388
<rdar://problem/23593980>

Reviewed by Eric Carlson.

To prepare for creating a MockCaptureDeviceManager to be able to test
MediaDevices.getUserMedia, we create a platform-independent capture device manager
which all platforms should extend and add platform-specific logic to.

The methods CaptureDeviceManager::createMediaSourceForCaptureDeviceWithConstraints and
CaptureDeviceManager::captureDeviceList should be overridden by each platform
CaptureDeviceManager to respectively create a RealtimeMediaSource and return a list of
capture devices. createMediaSourceForCaptureDeviceWithConstraints attempts to create
a media source for a given device with some constraints; if the contraints cannot be
satisfied, this returns null.

The refactored capture device manager also introduces the notion of a platform-
independent capture session which may be extended by platform device managers for
determining whether a given constraint name, value and media type is valid.

A platform-independent CaptureDeviceInfo now represents either the video or audio
component of a capture device, but not both at once. This means a capture device that
supports both video and audio will emit two separate capture devices.

No new tests, since there should be no behavior change.

* Modules/mediastream/CaptureDeviceInfo.h: Added.
(WebCore::CaptureSessionInfo::~CaptureSessionInfo):
(WebCore::CaptureSessionInfo::supportsVideoSize):
(WebCore::CaptureSessionInfo::bestSessionPresetForVideoDimensions):
* Modules/mediastream/CaptureDeviceManager.cpp: Added.
(CaptureDeviceManager::~CaptureDeviceManager):
(CaptureDeviceManager::getSourcesInfo):
(CaptureDeviceManager::captureDeviceFromDeviceID):
(CaptureDeviceManager::verifyConstraintsForMediaType):
(CaptureDeviceManager::bestSourcesForTypeAndConstraints):
(CaptureDeviceManager::sourceWithUID):
(CaptureDeviceManager::bestDeviceForFacingMode):
(facingModeFromString):
(CaptureDeviceManager::sessionSupportsConstraint):
(CaptureDeviceManager::isSupportedFrameRate):
* Modules/mediastream/CaptureDeviceManager.h: Added.
(WebCore::CaptureDeviceManager::refreshCaptureDeviceList):
(WebCore::CaptureDeviceManager::defaultCaptureSession):
* WebCore.xcodeproj/project.pbxproj:
* platform/mediastream/RealtimeMediaSourceSupportedConstraints.cpp: Added.
(WebCore::RealtimeMediaSourceSupportedConstraints::nameForConstraint):
(WebCore::RealtimeMediaSourceSupportedConstraints::constraintFromName):
(WebCore::RealtimeMediaSourceSupportedConstraints::supportsConstraint):
* platform/mediastream/RealtimeMediaSourceSupportedConstraints.h:
* platform/mediastream/mac/AVCaptureDeviceManager.h:
* platform/mediastream/mac/AVCaptureDeviceManager.mm:
(WebCore::AVCaptureSessionInfo::AVCaptureSessionInfo):
(WebCore::AVCaptureSessionInfo::supportsVideoSize):
(WebCore::AVCaptureSessionInfo::bestSessionPresetForVideoDimensions):
(WebCore::AVCaptureDeviceManager::captureDeviceList):
(WebCore::shouldConsiderDeviceInDeviceList):
(WebCore::AVCaptureDeviceManager::refreshCaptureDeviceList):
(WebCore::AVCaptureDeviceManager::AVCaptureDeviceManager):
(WebCore::AVCaptureDeviceManager::bestSourcesForTypeAndConstraints):
(WebCore::AVCaptureDeviceManager::sourceWithUID):
(WebCore::AVCaptureDeviceManager::getSourcesInfo):
(WebCore::AVCaptureDeviceManager::verifyConstraintsForMediaType):
(WebCore::AVCaptureDeviceManager::defaultCaptureSession):
(WebCore::AVCaptureDeviceManager::sessionSupportsConstraint):
(WebCore::AVCaptureDeviceManager::createMediaSourceForCaptureDeviceWithConstraints):
(WebCore::AVCaptureDeviceManager::deviceDisconnected):
(WebCore::AVCaptureDeviceManager::isSupportedFrameRate):
(WebCore::CaptureDevice:::m_enabled): Deleted.
(WebCore::captureDeviceList): Deleted.
(WebCore::captureDeviceFromDeviceID): Deleted.
(WebCore::refreshCaptureDeviceList): Deleted.
(WebCore::AVCaptureDeviceManager::bestSessionPresetForVideoSize): Deleted.
(WebCore::AVCaptureDeviceManager::deviceSupportsFacingMode): Deleted.
(WebCore::AVCaptureDeviceManager::bestDeviceForFacingMode): Deleted.
(WebCore::AVCaptureDeviceManager::isValidConstraint): Deleted.
(WebCore::AVCaptureDeviceManager::validConstraintNames): Deleted.
(WebCore::AVCaptureDeviceManager::validFacingModes): Deleted.
* platform/mediastream/mac/AVVideoCaptureSource.mm:
(WebCore::AVVideoCaptureSource::applyConstraints):
* platform/mediastream/mac/RealtimeMediaSourceCenterMac.cpp:
(WebCore::RealtimeMediaSourceCenterMac::validateRequestConstraints):
(WebCore::RealtimeMediaSourceCenterMac::createMediaStream):

Modified Paths

Added Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (192837 => 192838)


--- trunk/Source/WebCore/ChangeLog	2015-11-30 23:27:23 UTC (rev 192837)
+++ trunk/Source/WebCore/ChangeLog	2015-11-30 23:48:42 UTC (rev 192838)
@@ -1,3 +1,90 @@
+2015-11-30  Wenson Hsieh  <wenson_hs...@apple.com>
+
+        Split platform-independent logic in AVCaptureDeviceManager out into a new class
+        https://bugs.webkit.org/show_bug.cgi?id=151388
+        <rdar://problem/23593980>
+
+        Reviewed by Eric Carlson.
+
+        To prepare for creating a MockCaptureDeviceManager to be able to test
+        MediaDevices.getUserMedia, we create a platform-independent capture device manager
+        which all platforms should extend and add platform-specific logic to.
+
+        The methods CaptureDeviceManager::createMediaSourceForCaptureDeviceWithConstraints and
+        CaptureDeviceManager::captureDeviceList should be overridden by each platform
+        CaptureDeviceManager to respectively create a RealtimeMediaSource and return a list of
+        capture devices. createMediaSourceForCaptureDeviceWithConstraints attempts to create
+        a media source for a given device with some constraints; if the contraints cannot be
+        satisfied, this returns null.
+
+        The refactored capture device manager also introduces the notion of a platform-
+        independent capture session which may be extended by platform device managers for
+        determining whether a given constraint name, value and media type is valid.
+
+        A platform-independent CaptureDeviceInfo now represents either the video or audio
+        component of a capture device, but not both at once. This means a capture device that
+        supports both video and audio will emit two separate capture devices.
+
+        No new tests, since there should be no behavior change.
+
+        * Modules/mediastream/CaptureDeviceInfo.h: Added.
+        (WebCore::CaptureSessionInfo::~CaptureSessionInfo):
+        (WebCore::CaptureSessionInfo::supportsVideoSize):
+        (WebCore::CaptureSessionInfo::bestSessionPresetForVideoDimensions):
+        * Modules/mediastream/CaptureDeviceManager.cpp: Added.
+        (CaptureDeviceManager::~CaptureDeviceManager):
+        (CaptureDeviceManager::getSourcesInfo):
+        (CaptureDeviceManager::captureDeviceFromDeviceID):
+        (CaptureDeviceManager::verifyConstraintsForMediaType):
+        (CaptureDeviceManager::bestSourcesForTypeAndConstraints):
+        (CaptureDeviceManager::sourceWithUID):
+        (CaptureDeviceManager::bestDeviceForFacingMode):
+        (facingModeFromString):
+        (CaptureDeviceManager::sessionSupportsConstraint):
+        (CaptureDeviceManager::isSupportedFrameRate):
+        * Modules/mediastream/CaptureDeviceManager.h: Added.
+        (WebCore::CaptureDeviceManager::refreshCaptureDeviceList):
+        (WebCore::CaptureDeviceManager::defaultCaptureSession):
+        * WebCore.xcodeproj/project.pbxproj:
+        * platform/mediastream/RealtimeMediaSourceSupportedConstraints.cpp: Added.
+        (WebCore::RealtimeMediaSourceSupportedConstraints::nameForConstraint):
+        (WebCore::RealtimeMediaSourceSupportedConstraints::constraintFromName):
+        (WebCore::RealtimeMediaSourceSupportedConstraints::supportsConstraint):
+        * platform/mediastream/RealtimeMediaSourceSupportedConstraints.h:
+        * platform/mediastream/mac/AVCaptureDeviceManager.h:
+        * platform/mediastream/mac/AVCaptureDeviceManager.mm:
+        (WebCore::AVCaptureSessionInfo::AVCaptureSessionInfo):
+        (WebCore::AVCaptureSessionInfo::supportsVideoSize):
+        (WebCore::AVCaptureSessionInfo::bestSessionPresetForVideoDimensions):
+        (WebCore::AVCaptureDeviceManager::captureDeviceList):
+        (WebCore::shouldConsiderDeviceInDeviceList):
+        (WebCore::AVCaptureDeviceManager::refreshCaptureDeviceList):
+        (WebCore::AVCaptureDeviceManager::AVCaptureDeviceManager):
+        (WebCore::AVCaptureDeviceManager::bestSourcesForTypeAndConstraints):
+        (WebCore::AVCaptureDeviceManager::sourceWithUID):
+        (WebCore::AVCaptureDeviceManager::getSourcesInfo):
+        (WebCore::AVCaptureDeviceManager::verifyConstraintsForMediaType):
+        (WebCore::AVCaptureDeviceManager::defaultCaptureSession):
+        (WebCore::AVCaptureDeviceManager::sessionSupportsConstraint):
+        (WebCore::AVCaptureDeviceManager::createMediaSourceForCaptureDeviceWithConstraints):
+        (WebCore::AVCaptureDeviceManager::deviceDisconnected):
+        (WebCore::AVCaptureDeviceManager::isSupportedFrameRate):
+        (WebCore::CaptureDevice:::m_enabled): Deleted.
+        (WebCore::captureDeviceList): Deleted.
+        (WebCore::captureDeviceFromDeviceID): Deleted.
+        (WebCore::refreshCaptureDeviceList): Deleted.
+        (WebCore::AVCaptureDeviceManager::bestSessionPresetForVideoSize): Deleted.
+        (WebCore::AVCaptureDeviceManager::deviceSupportsFacingMode): Deleted.
+        (WebCore::AVCaptureDeviceManager::bestDeviceForFacingMode): Deleted.
+        (WebCore::AVCaptureDeviceManager::isValidConstraint): Deleted.
+        (WebCore::AVCaptureDeviceManager::validConstraintNames): Deleted.
+        (WebCore::AVCaptureDeviceManager::validFacingModes): Deleted.
+        * platform/mediastream/mac/AVVideoCaptureSource.mm:
+        (WebCore::AVVideoCaptureSource::applyConstraints):
+        * platform/mediastream/mac/RealtimeMediaSourceCenterMac.cpp:
+        (WebCore::RealtimeMediaSourceCenterMac::validateRequestConstraints):
+        (WebCore::RealtimeMediaSourceCenterMac::createMediaStream):
+
 2015-11-30  Brady Eidson  <beid...@apple.com>
 
         Modern IDB: Set the correct source on the IDBRequest for cursor updates

Added: trunk/Source/WebCore/Modules/mediastream/CaptureDeviceInfo.h (0 => 192838)


--- trunk/Source/WebCore/Modules/mediastream/CaptureDeviceInfo.h	                        (rev 0)
+++ trunk/Source/WebCore/Modules/mediastream/CaptureDeviceInfo.h	2015-11-30 23:48:42 UTC (rev 192838)
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2015 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. ``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
+ * 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.
+ */
+
+#ifndef CaptureDeviceInfo_h
+#define CaptureDeviceInfo_h
+
+#if ENABLE(MEDIA_STREAM)
+
+#include <RealtimeMediaSource.h>
+#include <wtf/text/WTFString.h>
+
+namespace WebCore {
+
+struct CaptureDeviceInfo {
+    String m_persistentDeviceID;
+    String m_localizedName;
+    String m_groupID;
+
+    String m_sourceId;
+
+    bool m_enabled { false };
+    RealtimeMediaSource::Type m_sourceType { RealtimeMediaSource::None };
+    RealtimeMediaSourceStates::VideoFacingMode m_position { RealtimeMediaSourceStates::Unknown };
+};
+
+class CaptureSessionInfo {
+public:
+    virtual ~CaptureSessionInfo() { }
+    virtual bool supportsVideoSize(const String& /* videoSize */) const { return false; }
+    virtual String bestSessionPresetForVideoDimensions(int /* width */, int /* height */) const { return emptyString(); }
+};
+
+} // namespace WebCore
+
+#endif // ENABLE(MEDIA_STREAM)
+
+#endif /* CaptureDeviceInfo_h */

Added: trunk/Source/WebCore/Modules/mediastream/CaptureDeviceManager.cpp (0 => 192838)


--- trunk/Source/WebCore/Modules/mediastream/CaptureDeviceManager.cpp	                        (rev 0)
+++ trunk/Source/WebCore/Modules/mediastream/CaptureDeviceManager.cpp	2015-11-30 23:48:42 UTC (rev 192838)
@@ -0,0 +1,193 @@
+/*
+ * Copyright (C) 2015 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. ``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
+ * 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.
+ */
+
+#import "config.h"
+#import "CaptureDeviceManager.h"
+
+#if ENABLE(MEDIA_STREAM)
+
+#import "Logging.h"
+#import "MediaConstraints.h"
+#import "RealtimeMediaSource.h"
+#import "RealtimeMediaSourceCenter.h"
+#import "RealtimeMediaSourceStates.h"
+#import "UUID.h"
+#import <wtf/MainThread.h>
+#import <wtf/NeverDestroyed.h>
+
+using namespace WebCore;
+
+CaptureDeviceManager::~CaptureDeviceManager()
+{
+}
+
+Vector<RefPtr<TrackSourceInfo>> CaptureDeviceManager::getSourcesInfo(const String& requestOrigin)
+{
+    UNUSED_PARAM(requestOrigin);
+    Vector<RefPtr<TrackSourceInfo>> sourcesInfo;
+    for (auto captureDevice : captureDeviceList()) {
+        if (!captureDevice.m_enabled || captureDevice.m_sourceType == RealtimeMediaSource::None)
+            continue;
+
+        TrackSourceInfo::SourceKind trackSourceType = captureDevice.m_sourceType == RealtimeMediaSource::Video ? TrackSourceInfo::Video : TrackSourceInfo::Audio;
+        sourcesInfo.append(TrackSourceInfo::create(captureDevice.m_sourceId, trackSourceType, captureDevice.m_localizedName, captureDevice.m_groupID));
+    }
+    LOG(Media, "CaptureDeviceManager::getSourcesInfo(%p), found %zu active devices", this, sourcesInfo.size());
+    return sourcesInfo;
+}
+
+bool CaptureDeviceManager::captureDeviceFromDeviceID(const String& captureDeviceID, CaptureDeviceInfo& foundDevice)
+{
+    for (auto& device : captureDeviceList()) {
+        if (device.m_persistentDeviceID == captureDeviceID) {
+            foundDevice = device;
+            return true;
+        }
+    }
+
+    return false;
+}
+
+bool CaptureDeviceManager::verifyConstraintsForMediaType(RealtimeMediaSource::Type type, MediaConstraints* constraints, const CaptureSessionInfo* session, String& invalidConstraint)
+{
+    if (!constraints)
+        return true;
+
+    Vector<MediaConstraint> mandatoryConstraints;
+    constraints->getMandatoryConstraints(mandatoryConstraints);
+    for (auto& constraint : mandatoryConstraints) {
+        if (sessionSupportsConstraint(session, type, constraint.m_name, constraint.m_value))
+            continue;
+
+        invalidConstraint = constraint.m_name;
+        return false;
+    }
+
+    return true;
+}
+
+Vector<RefPtr<RealtimeMediaSource>> CaptureDeviceManager::bestSourcesForTypeAndConstraints(RealtimeMediaSource::Type type, PassRefPtr<MediaConstraints> constraints)
+{
+    Vector<RefPtr<RealtimeMediaSource>> bestSourcesList;
+
+    struct {
+        bool operator()(RefPtr<RealtimeMediaSource> a, RefPtr<RealtimeMediaSource> b)
+        {
+            return a->fitnessScore() < b->fitnessScore();
+        }
+    } sortBasedOnFitnessScore;
+
+    for (auto& captureDevice : captureDeviceList()) {
+        if (!captureDevice.m_enabled || captureDevice.m_sourceId.isEmpty() || captureDevice.m_sourceType == RealtimeMediaSource::None)
+            continue;
+
+        if (RefPtr<RealtimeMediaSource> captureSource = sourceWithUID(captureDevice.m_persistentDeviceID, type, constraints.get()))
+            bestSourcesList.append(captureSource.leakRef());
+    }
+    std::sort(bestSourcesList.begin(), bestSourcesList.end(), sortBasedOnFitnessScore);
+    return bestSourcesList;
+}
+
+RefPtr<RealtimeMediaSource> CaptureDeviceManager::sourceWithUID(const String& deviceUID, RealtimeMediaSource::Type type, MediaConstraints* constraints)
+{
+    for (auto& captureDevice : captureDeviceList()) {
+        if (captureDevice.m_persistentDeviceID != deviceUID || captureDevice.m_sourceType != type)
+            continue;
+
+        if (!captureDevice.m_enabled || type == RealtimeMediaSource::None || captureDevice.m_sourceId.isEmpty())
+            continue;
+
+        if (RealtimeMediaSource* mediaSource = createMediaSourceForCaptureDeviceWithConstraints(captureDevice, constraints))
+            return mediaSource;
+    }
+    return nullptr;
+}
+
+CaptureDeviceInfo* CaptureDeviceManager::bestDeviceForFacingMode(RealtimeMediaSourceStates::VideoFacingMode facingMode)
+{
+    if (facingMode == RealtimeMediaSourceStates::Unknown)
+        return nullptr;
+
+    for (auto& device : captureDeviceList()) {
+        if (device.m_sourceType == RealtimeMediaSource::Video && device.m_position == facingMode)
+            return &device;
+    }
+    return nullptr;
+}
+
+static inline RealtimeMediaSourceStates::VideoFacingMode facingModeFromString(const String& facingModeString)
+{
+    static NeverDestroyed<AtomicString> userFacingModeString("user", AtomicString::ConstructFromLiteral);
+    static NeverDestroyed<AtomicString> environmentFacingModeString("environment", AtomicString::ConstructFromLiteral);
+    static NeverDestroyed<AtomicString> leftFacingModeString("left", AtomicString::ConstructFromLiteral);
+    static NeverDestroyed<AtomicString> rightFacingModeString("right", AtomicString::ConstructFromLiteral);
+    if (facingModeString == userFacingModeString)
+        return RealtimeMediaSourceStates::User;
+    if (facingModeString == environmentFacingModeString)
+        return RealtimeMediaSourceStates::Environment;
+    if (facingModeString == leftFacingModeString)
+        return RealtimeMediaSourceStates::Left;
+    if (facingModeString == rightFacingModeString)
+        return RealtimeMediaSourceStates::Right;
+    return RealtimeMediaSourceStates::Unknown;
+}
+
+bool CaptureDeviceManager::sessionSupportsConstraint(const CaptureSessionInfo*, RealtimeMediaSource::Type type, const String& name, const String& value)
+{
+    const RealtimeMediaSourceSupportedConstraints& supportedConstraints = RealtimeMediaSourceCenter::singleton().supportedConstraints();
+    MediaConstraintType constraint = supportedConstraints.constraintFromName(name);
+    if (!supportedConstraints.supportsConstraint(constraint))
+        return false;
+
+    switch (constraint) {
+    case MediaConstraintType::Width:
+        return type == RealtimeMediaSource::Video;
+
+    case MediaConstraintType::Height:
+        return type == RealtimeMediaSource::Video;
+
+    case MediaConstraintType::FrameRate: {
+        if (type == RealtimeMediaSource::Audio)
+            return false;
+
+        return isSupportedFrameRate(value.toFloat());
+    }
+    case MediaConstraintType::FacingMode: {
+        if (type == RealtimeMediaSource::Audio)
+            return false;
+
+        return bestDeviceForFacingMode(facingModeFromString(value));
+    }
+    default:
+        return false;
+    }
+}
+
+bool CaptureDeviceManager::isSupportedFrameRate(float frameRate) const
+{
+    return 0 < frameRate && frameRate <= 60;
+}
+
+#endif // ENABLE(MEDIA_STREAM)

Added: trunk/Source/WebCore/Modules/mediastream/CaptureDeviceManager.h (0 => 192838)


--- trunk/Source/WebCore/Modules/mediastream/CaptureDeviceManager.h	                        (rev 0)
+++ trunk/Source/WebCore/Modules/mediastream/CaptureDeviceManager.h	2015-11-30 23:48:42 UTC (rev 192838)
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2015 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. ``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
+ * 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.
+ */
+
+#ifndef CaptureDeviceManager_h
+#define CaptureDeviceManager_h
+
+#if ENABLE(MEDIA_STREAM)
+
+#include "CaptureDeviceInfo.h"
+#include "MediaStreamTrackSourcesRequestClient.h"
+#include "RealtimeMediaSource.h"
+#include <wtf/text/WTFString.h>
+
+namespace WebCore {
+
+class CaptureDeviceManager {
+public:
+    virtual Vector<CaptureDeviceInfo>& captureDeviceList() = 0;
+    virtual void refreshCaptureDeviceList() { }
+    virtual TrackSourceInfoVector getSourcesInfo(const String&);
+    virtual Vector<RefPtr<RealtimeMediaSource>> bestSourcesForTypeAndConstraints(RealtimeMediaSource::Type, PassRefPtr<MediaConstraints>);
+    virtual RefPtr<RealtimeMediaSource> sourceWithUID(const String&, RealtimeMediaSource::Type, MediaConstraints*);
+
+    virtual bool verifyConstraintsForMediaType(RealtimeMediaSource::Type, MediaConstraints*, const CaptureSessionInfo*, String&);
+
+protected:
+    virtual ~CaptureDeviceManager();
+    virtual RealtimeMediaSource* createMediaSourceForCaptureDeviceWithConstraints(const CaptureDeviceInfo&, MediaConstraints*) = 0;
+
+    virtual CaptureSessionInfo defaultCaptureSession() const { return CaptureSessionInfo(); }
+    virtual bool sessionSupportsConstraint(const CaptureSessionInfo*, RealtimeMediaSource::Type, const String& name, const String& value);
+    virtual bool isSupportedFrameRate(float frameRate) const;
+
+    bool captureDeviceFromDeviceID(const String& captureDeviceID, CaptureDeviceInfo& source);
+    CaptureDeviceInfo* bestDeviceForFacingMode(RealtimeMediaSourceStates::VideoFacingMode);
+};
+
+} // namespace WebCore
+
+#endif // ENABLE(MEDIA_STREAM)
+
+#endif /* CaptureDeviceManager_h */

Modified: trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj (192837 => 192838)


--- trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj	2015-11-30 23:27:23 UTC (rev 192837)
+++ trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj	2015-11-30 23:48:42 UTC (rev 192838)
@@ -1210,6 +1210,9 @@
 		2E3BC108117D479800B9409A /* DOMFileError.h in Headers */ = {isa = PBXBuildFile; fileRef = 2E3BC106117D479800B9409A /* DOMFileError.h */; };
 		2E3BC109117D479800B9409A /* DOMFileError.mm in Sources */ = {isa = PBXBuildFile; fileRef = 2E3BC107117D479800B9409A /* DOMFileError.mm */; };
 		2E3BC10B117D47C800B9409A /* DOMFileErrorInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = 2E3BC10A117D47C800B9409A /* DOMFileErrorInternal.h */; };
+		2E3C8C621BFBA97500309566 /* CaptureDeviceManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 2E3C8C611BFBA8DC00309566 /* CaptureDeviceManager.h */; };
+		2E3C8C641BFBB75D00309566 /* CaptureDeviceManager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2E3C8C631BFBB75D00309566 /* CaptureDeviceManager.cpp */; };
+		2E3C8C681BFBF8E100309566 /* CaptureDeviceInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 2E3C8C661BFBF8E100309566 /* CaptureDeviceInfo.h */; };
 		2E4346450F546A8200B0F1BA /* Worker.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2E4346330F546A8200B0F1BA /* Worker.cpp */; };
 		2E4346460F546A8200B0F1BA /* Worker.h in Headers */ = {isa = PBXBuildFile; fileRef = 2E4346340F546A8200B0F1BA /* Worker.h */; };
 		2E4346480F546A8200B0F1BA /* WorkerGlobalScope.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2E4346360F546A8200B0F1BA /* WorkerGlobalScope.cpp */; };
@@ -1237,6 +1240,7 @@
 		2EB4BCD2121F03E300EC4885 /* BlobResourceHandle.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2EB4BCD0121F03E300EC4885 /* BlobResourceHandle.cpp */; };
 		2EB4BCD3121F03E300EC4885 /* BlobResourceHandle.h in Headers */ = {isa = PBXBuildFile; fileRef = 2EB4BCD1121F03E300EC4885 /* BlobResourceHandle.h */; };
 		2EBBC3D81B65988300F5253D /* WheelEventDeltaFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = 2EBBC3D71B65988300F5253D /* WheelEventDeltaFilter.h */; settings = {ATTRIBUTES = (Private, ); }; };
+		2EC41DE41C0410A300D294FE /* RealtimeMediaSourceSupportedConstraints.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2EC41DE21C0410A300D294FE /* RealtimeMediaSourceSupportedConstraints.cpp */; };
 		2ECF7ADC10162B3800427DE7 /* JSErrorEvent.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2ECF7ADA10162B3800427DE7 /* JSErrorEvent.cpp */; };
 		2ECF7ADD10162B3800427DE7 /* JSErrorEvent.h in Headers */ = {isa = PBXBuildFile; fileRef = 2ECF7ADB10162B3800427DE7 /* JSErrorEvent.h */; };
 		2ECF7AE110162B5800427DE7 /* ErrorEvent.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2ECF7ADE10162B5800427DE7 /* ErrorEvent.cpp */; };
@@ -8587,6 +8591,9 @@
 		2E3BC106117D479800B9409A /* DOMFileError.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DOMFileError.h; sourceTree = "<group>"; };
 		2E3BC107117D479800B9409A /* DOMFileError.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = DOMFileError.mm; sourceTree = "<group>"; };
 		2E3BC10A117D47C800B9409A /* DOMFileErrorInternal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DOMFileErrorInternal.h; sourceTree = "<group>"; };
+		2E3C8C611BFBA8DC00309566 /* CaptureDeviceManager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CaptureDeviceManager.h; sourceTree = "<group>"; };
+		2E3C8C631BFBB75D00309566 /* CaptureDeviceManager.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CaptureDeviceManager.cpp; sourceTree = "<group>"; };
+		2E3C8C661BFBF8E100309566 /* CaptureDeviceInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CaptureDeviceInfo.h; sourceTree = "<group>"; };
 		2E4346330F546A8200B0F1BA /* Worker.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Worker.cpp; sourceTree = "<group>"; };
 		2E4346340F546A8200B0F1BA /* Worker.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Worker.h; sourceTree = "<group>"; };
 		2E4346350F546A8200B0F1BA /* Worker.idl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = Worker.idl; sourceTree = "<group>"; };
@@ -8617,6 +8624,7 @@
 		2EB4BCD0121F03E300EC4885 /* BlobResourceHandle.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = BlobResourceHandle.cpp; sourceTree = "<group>"; };
 		2EB4BCD1121F03E300EC4885 /* BlobResourceHandle.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BlobResourceHandle.h; sourceTree = "<group>"; };
 		2EBBC3D71B65988300F5253D /* WheelEventDeltaFilter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WheelEventDeltaFilter.h; sourceTree = "<group>"; };
+		2EC41DE21C0410A300D294FE /* RealtimeMediaSourceSupportedConstraints.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RealtimeMediaSourceSupportedConstraints.cpp; sourceTree = "<group>"; };
 		2ECF7ADA10162B3800427DE7 /* JSErrorEvent.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSErrorEvent.cpp; sourceTree = "<group>"; };
 		2ECF7ADB10162B3800427DE7 /* JSErrorEvent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSErrorEvent.h; sourceTree = "<group>"; };
 		2ECF7ADE10162B5800427DE7 /* ErrorEvent.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ErrorEvent.cpp; sourceTree = "<group>"; };
@@ -15138,6 +15146,9 @@
 				070584FE17F9F05E005F2BCB /* CapabilityRange.cpp */,
 				07C59B7417F7D09D000FBCBB /* CapabilityRange.h */,
 				07C59B7517F7D09D000FBCBB /* CapabilityRange.idl */,
+				2E3C8C611BFBA8DC00309566 /* CaptureDeviceManager.h */,
+				2E3C8C631BFBB75D00309566 /* CaptureDeviceManager.cpp */,
+				2E3C8C661BFBF8E100309566 /* CaptureDeviceInfo.h */,
 				073794ED19EE364200E5A045 /* DOMURLMediaStream.cpp */,
 				15FCC9FD1B4DF85600E72326 /* DOMURLMediaStream.h */,
 				073794EE19EE364200E5A045 /* DOMURLMediaStream.idl */,
@@ -15276,6 +15287,7 @@
 				07FFDE66181AED420072D409 /* MediaStreamTrackPrivate.cpp */,
 				07FFDE67181AED420072D409 /* MediaStreamTrackPrivate.h */,
 				07C1C0E41BFB60ED00BD2256 /* RealtimeMediaSourceSupportedConstraints.h */,
+				2EC41DE21C0410A300D294FE /* RealtimeMediaSourceSupportedConstraints.cpp */,
 				076306E217E22A43005A7C4E /* MediaStreamTrackSourcesRequestClient.h */,
 				4A4F656B1AA997F100E38CDD /* RealtimeMediaSource.cpp */,
 				4A4F656C1AA997F100E38CDD /* RealtimeMediaSource.h */,
@@ -26619,6 +26631,7 @@
 				BCEFE1EB0DCA5F6400739219 /* JSXSLTProcessor.h in Headers */,
 				85031B440A44EFC700F992E0 /* KeyboardEvent.h in Headers */,
 				1AE00D59182DAC8D00087DD7 /* KeyedCoding.h in Headers */,
+				2E3C8C621BFBA97500309566 /* CaptureDeviceManager.h in Headers */,
 				517A63C51B74318F00E7DCDC /* KeyedDecoderCF.h in Headers */,
 				517A63C61B74319200E7DCDC /* KeyedEncoderCF.h in Headers */,
 				A513B3D7114B1666001C429B /* KeyEventCocoa.h in Headers */,
@@ -26704,6 +26717,7 @@
 				FABE72F91059C1EB00D999DD /* MathMLMathElement.h in Headers */,
 				44A28AAF12DFB8BF00AE923B /* MathMLNames.h in Headers */,
 				FA654A6C1108ABED002615E0 /* MathMLTextElement.h in Headers */,
+				2E3C8C681BFBF8E100309566 /* CaptureDeviceInfo.h in Headers */,
 				49D5DC2C0F423A73008F20FD /* Matrix3DTransformOperation.h in Headers */,
 				49E911C70EF86D47009D0CAF /* MatrixTransformOperation.h in Headers */,
 				5CBC8DAD1AAA302200E1C803 /* MediaAccessibilitySoftLink.h in Headers */,
@@ -28652,6 +28666,7 @@
 				E164A2ED191AE6350010737D /* BlobDataFileReferenceMac.mm in Sources */,
 				E14A94D716DFDF950068DE82 /* BlobRegistry.cpp in Sources */,
 				2EDEF1F6121B0EFC00726DB2 /* BlobRegistryImpl.cpp in Sources */,
+				2EC41DE41C0410A300D294FE /* RealtimeMediaSourceSupportedConstraints.cpp in Sources */,
 				2EB4BCD2121F03E300EC4885 /* BlobResourceHandle.cpp in Sources */,
 				976D6C7E122B8A3D001FD1F7 /* BlobURL.cpp in Sources */,
 				93F19AE108245E59001E9ABC /* BlockExceptions.mm in Sources */,
@@ -30373,6 +30388,7 @@
 				E4B65A5A132FAAF90070E7BE /* LegacyTileGrid.mm in Sources */,
 				E424A3A01330DF1E00CF6DC9 /* LegacyTileGridTile.mm in Sources */,
 				E4B65A5E132FADB60070E7BE /* LegacyTileLayer.mm in Sources */,
+				2E3C8C641BFBB75D00309566 /* CaptureDeviceManager.cpp in Sources */,
 				E4E39AFD1330EFC6003AB274 /* LegacyTileLayerPool.mm in Sources */,
 				51645B6A1B9FA6C800F789CE /* LegacyTransaction.cpp in Sources */,
 				51645B6C1B9FA6C800F789CE /* LegacyVersionChangeEvent.cpp in Sources */,

Added: trunk/Source/WebCore/platform/mediastream/RealtimeMediaSourceSupportedConstraints.cpp (0 => 192838)


--- trunk/Source/WebCore/platform/mediastream/RealtimeMediaSourceSupportedConstraints.cpp	                        (rev 0)
+++ trunk/Source/WebCore/platform/mediastream/RealtimeMediaSourceSupportedConstraints.cpp	2015-11-30 23:48:42 UTC (rev 192838)
@@ -0,0 +1,133 @@
+/*
+ * Copyright (C) 2015 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 THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT
+ * OWNER OR 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 "RealtimeMediaSourceSupportedConstraints.h"
+
+#if ENABLE(MEDIA_STREAM)
+
+#include <wtf/HashMap.h>
+#include <wtf/NeverDestroyed.h>
+#include <wtf/text/AtomicString.h>
+#include <wtf/text/AtomicStringHash.h>
+
+namespace WebCore {
+
+const AtomicString& RealtimeMediaSourceSupportedConstraints::nameForConstraint(MediaConstraintType constraint) const
+{
+    static NeverDestroyed<AtomicString> unknownConstraintName(emptyString());
+    static NeverDestroyed<AtomicString> widthConstraintName("width");
+    static NeverDestroyed<AtomicString> heightConstraintName("height");
+    static NeverDestroyed<AtomicString> aspectRatioConstraintName("aspectRatio");
+    static NeverDestroyed<AtomicString> frameRateConstraintName("frameRate");
+    static NeverDestroyed<AtomicString> facingModeConstraintName("facingMode");
+    static NeverDestroyed<AtomicString> volumeConstraintName("volume");
+    static NeverDestroyed<AtomicString> sampleRateConstraintName("sampleRate");
+    static NeverDestroyed<AtomicString> sampleSizeConstraintName("sampleSize");
+    static NeverDestroyed<AtomicString> echoCancellationConstraintName("echoCancellation");
+    static NeverDestroyed<AtomicString> deviceIdConstraintName("deviceId");
+    static NeverDestroyed<AtomicString> groupIdConstraintName("groupId");
+    switch (constraint) {
+    case MediaConstraintType::Unknown:
+        return unknownConstraintName;
+    case MediaConstraintType::Width:
+        return widthConstraintName;
+    case MediaConstraintType::Height:
+        return heightConstraintName;
+    case MediaConstraintType::AspectRatio:
+        return aspectRatioConstraintName;
+    case MediaConstraintType::FrameRate:
+        return frameRateConstraintName;
+    case MediaConstraintType::FacingMode:
+        return facingModeConstraintName;
+    case MediaConstraintType::Volume:
+        return volumeConstraintName;
+    case MediaConstraintType::SampleRate:
+        return sampleRateConstraintName;
+    case MediaConstraintType::SampleSize:
+        return sampleSizeConstraintName;
+    case MediaConstraintType::EchoCancellation:
+        return echoCancellationConstraintName;
+    case MediaConstraintType::DeviceId:
+        return deviceIdConstraintName;
+    case MediaConstraintType::GroupId:
+        return groupIdConstraintName;
+    }
+}
+
+MediaConstraintType RealtimeMediaSourceSupportedConstraints::constraintFromName(const String& constraintName) const
+{
+    static NeverDestroyed<HashMap<AtomicString, MediaConstraintType>> nameToConstraintMap;
+    HashMap<AtomicString, MediaConstraintType>& nameToConstraintMapValue = nameToConstraintMap.get();
+    if (!nameToConstraintMapValue.size()) {
+        nameToConstraintMapValue.add("width", MediaConstraintType::Width);
+        nameToConstraintMapValue.add("height", MediaConstraintType::Height);
+        nameToConstraintMapValue.add("aspectRatio", MediaConstraintType::AspectRatio);
+        nameToConstraintMapValue.add("frameRate", MediaConstraintType::FrameRate);
+        nameToConstraintMapValue.add("facingMode", MediaConstraintType::FacingMode);
+        nameToConstraintMapValue.add("volume", MediaConstraintType::Volume);
+        nameToConstraintMapValue.add("sampleRate", MediaConstraintType::SampleRate);
+        nameToConstraintMapValue.add("sampleSize", MediaConstraintType::SampleSize);
+        nameToConstraintMapValue.add("echoCancellation", MediaConstraintType::EchoCancellation);
+        nameToConstraintMapValue.add("deviceId", MediaConstraintType::DeviceId);
+        nameToConstraintMapValue.add("groupId", MediaConstraintType::GroupId);
+    }
+    auto iter = nameToConstraintMapValue.find(constraintName);
+    return iter == nameToConstraintMapValue.end() ? MediaConstraintType::Unknown : iter->value;
+}
+
+bool RealtimeMediaSourceSupportedConstraints::supportsConstraint(MediaConstraintType constraint) const
+{
+    switch (constraint) {
+    case MediaConstraintType::Unknown:
+        return false;
+    case MediaConstraintType::Width:
+        return supportsWidth();
+    case MediaConstraintType::Height:
+        return supportsHeight();
+    case MediaConstraintType::AspectRatio:
+        return supportsAspectRatio();
+    case MediaConstraintType::FrameRate:
+        return supportsFrameRate();
+    case MediaConstraintType::FacingMode:
+        return supportsFacingMode();
+    case MediaConstraintType::Volume:
+        return supportsVolume();
+    case MediaConstraintType::SampleRate:
+        return supportsSampleRate();
+    case MediaConstraintType::SampleSize:
+        return supportsSampleSize();
+    case MediaConstraintType::EchoCancellation:
+        return supportsEchoCancellation();
+    case MediaConstraintType::DeviceId:
+        return supportsDeviceId();
+    case MediaConstraintType::GroupId:
+        return supportsGroupId();
+    }
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(MEDIA_STREAM)

Modified: trunk/Source/WebCore/platform/mediastream/RealtimeMediaSourceSupportedConstraints.h (192837 => 192838)


--- trunk/Source/WebCore/platform/mediastream/RealtimeMediaSourceSupportedConstraints.h	2015-11-30 23:27:23 UTC (rev 192837)
+++ trunk/Source/WebCore/platform/mediastream/RealtimeMediaSourceSupportedConstraints.h	2015-11-30 23:48:42 UTC (rev 192838)
@@ -33,8 +33,25 @@
 
 #if ENABLE(MEDIA_STREAM)
 
+#include <wtf/text/WTFString.h>
+
 namespace WebCore {
 
+enum class MediaConstraintType {
+    Unknown,
+    Width,
+    Height,
+    AspectRatio,
+    FrameRate,
+    FacingMode,
+    Volume,
+    SampleRate,
+    SampleSize,
+    EchoCancellation,
+    DeviceId,
+    GroupId
+};
+
 class RealtimeMediaSourceSupportedConstraints {
 public:
     RealtimeMediaSourceSupportedConstraints()
@@ -74,6 +91,10 @@
     bool supportsGroupId() const { return m_supportsGroupId; }
     void setSupportsGroupId(bool value) { m_supportsGroupId = value; }
 
+    const AtomicString& nameForConstraint(MediaConstraintType) const;
+    MediaConstraintType constraintFromName(const String& constraintName) const;
+    bool supportsConstraint(MediaConstraintType) const;
+
 private:
     bool m_supportsWidth { false };
     bool m_supportsHeight { false };

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


--- trunk/Source/WebCore/platform/mediastream/mac/AVCaptureDeviceManager.h	2015-11-30 23:27:23 UTC (rev 192837)
+++ trunk/Source/WebCore/platform/mediastream/mac/AVCaptureDeviceManager.h	2015-11-30 23:48:42 UTC (rev 192838)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2013 Apple Inc. All rights reserved.
+ * Copyright (C) 2013-2015 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -28,6 +28,7 @@
 
 #if ENABLE(MEDIA_STREAM) && USE(AVFOUNDATION)
 
+#include "CaptureDeviceManager.h"
 #include "MediaStreamTrackSourcesRequestClient.h"
 #include "RealtimeMediaSource.h"
 #include <wtf/RetainPtr.h>
@@ -40,38 +41,46 @@
 
 namespace WebCore {
 
-class CaptureDevice;
+class AVCaptureSessionInfo : public CaptureSessionInfo {
+public:
+    AVCaptureSessionInfo(AVCaptureSession*);
+    virtual bool supportsVideoSize(const String&) const override;
+    virtual String bestSessionPresetForVideoDimensions(int width, int height) const override;
 
-class AVCaptureDeviceManager {
+private:
+    AVCaptureSession *m_platformSession;
+};
+
+class AVCaptureDeviceManager final : public CaptureDeviceManager {
 public:
+    virtual Vector<CaptureDeviceInfo>& captureDeviceList() override;
+
     static AVCaptureDeviceManager& singleton();
-    static bool isAvailable();
 
-    TrackSourceInfoVector getSourcesInfo(const String&);
-    bool verifyConstraintsForMediaType(AVCaptureSession *, RealtimeMediaSource::Type, MediaConstraints*, String&);
-    Vector<RefPtr<RealtimeMediaSource>> bestSourcesForTypeAndConstraints(RealtimeMediaSource::Type, PassRefPtr<MediaConstraints>);
-    RefPtr<RealtimeMediaSource> sourceWithUID(const String&, RealtimeMediaSource::Type, MediaConstraints*);
+    virtual RefPtr<RealtimeMediaSource> sourceWithUID(const String&, RealtimeMediaSource::Type, MediaConstraints*) override;
+    virtual Vector<RefPtr<RealtimeMediaSource>> bestSourcesForTypeAndConstraints(RealtimeMediaSource::Type, PassRefPtr<MediaConstraints>) override;
 
-    enum ValidConstraints { Width = 0, Height, FrameRate, FacingMode, Gain };
-    static const Vector<AtomicString>& validConstraintNames();
-    static const Vector<AtomicString>& validFacingModes();
+    virtual TrackSourceInfoVector getSourcesInfo(const String&) override;
+    virtual bool verifyConstraintsForMediaType(RealtimeMediaSource::Type, MediaConstraints*, const CaptureSessionInfo*, String&) override;
 
-    static bool deviceSupportsFacingMode(AVCaptureDevice*, RealtimeMediaSourceStates::VideoFacingMode);
-    static bool isValidConstraint(RealtimeMediaSource::Type, const String&);
-    static String bestSessionPresetForVideoSize(AVCaptureSession*, int width, int height);
-
-    void registerForDeviceNotifications();
     void deviceConnected();
     void deviceDisconnected(AVCaptureDevice*);
 
 protected:
+    static bool isAvailable();
+
     AVCaptureDeviceManager();
-    ~AVCaptureDeviceManager();
+    virtual ~AVCaptureDeviceManager() override;
+    virtual bool sessionSupportsConstraint(const CaptureSessionInfo*, RealtimeMediaSource::Type, const String& name, const String& value) override;
+    virtual RealtimeMediaSource* createMediaSourceForCaptureDeviceWithConstraints(const CaptureDeviceInfo&, MediaConstraints*) override;
+    virtual CaptureSessionInfo defaultCaptureSession() const override;
+    virtual void refreshCaptureDeviceList() override;
+    virtual bool isSupportedFrameRate(float frameRate) const override;
 
-    CaptureDevice* bestDeviceForFacingMode(RealtimeMediaSourceStates::VideoFacingMode);
-    bool sessionSupportsConstraint(AVCaptureSession*, RealtimeMediaSource::Type, const String& name, const String& value);
+    void registerForDeviceNotifications();
 
     RetainPtr<WebCoreAVCaptureDeviceManagerObserver> m_objcObserver;
+    Vector<CaptureDeviceInfo> m_devices;
 };
 
 } // namespace WebCore

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


--- trunk/Source/WebCore/platform/mediastream/mac/AVCaptureDeviceManager.mm	2015-11-30 23:27:23 UTC (rev 192837)
+++ trunk/Source/WebCore/platform/mediastream/mac/AVCaptureDeviceManager.mm	2015-11-30 23:48:42 UTC (rev 192838)
@@ -35,7 +35,9 @@
 #import "Logging.h"
 #import "MediaConstraints.h"
 #import "RealtimeMediaSource.h"
+#import "RealtimeMediaSourceCenter.h"
 #import "RealtimeMediaSourceStates.h"
+#import "RealtimeMediaSourceSupportedConstraints.h"
 #import "SoftLinking.h"
 #import "UUID.h"
 #import <AVFoundation/AVFoundation.h>
@@ -89,86 +91,113 @@
 
 namespace WebCore {
 
-static void refreshCaptureDeviceList();
+AVCaptureSessionInfo::AVCaptureSessionInfo(AVCaptureSessionType *platformSession)
+    : m_platformSession(platformSession)
+{
+}
 
-class CaptureDevice {
-public:
-    CaptureDevice()
-        :m_enabled(false)
-    {
+bool AVCaptureSessionInfo::supportsVideoSize(const String& videoSize) const
+{
+    return [m_platformSession canSetSessionPreset:videoSize];
+}
+
+String AVCaptureSessionInfo::bestSessionPresetForVideoDimensions(int width, int height) const
+{
+    ASSERT(width >= 0);
+    ASSERT(height >= 0);
+
+    if (width > 1280 || height > 720) {
+        // FIXME: this restriction could be adjusted with the videoMaxScaleAndCropFactor property.
+        return emptyString();
     }
 
-    String m_captureDeviceID;
-    String m_localizedName;
-    String m_groupID;
+    if (width > 640 || height > 480) {
+        if (supportsVideoSize(AVCaptureSessionPreset1280x720))
+            return AVCaptureSessionPreset1280x720;
 
-    String m_audioSourceId;
-    String m_videoSourceId;
+        return emptyString();
+    }
 
-    bool m_enabled;
-};
+    if (width > 352 || height > 288) {
+        if (supportsVideoSize(AVCaptureSessionPreset640x480))
+            return AVCaptureSessionPreset640x480;
 
-static Vector<CaptureDevice>& captureDeviceList()
+        return emptyString();
+    }
+
+    if (supportsVideoSize(AVCaptureSessionPreset352x288))
+        return AVCaptureSessionPreset352x288;
+
+    if (supportsVideoSize(AVCaptureSessionPresetLow))
+        return AVCaptureSessionPresetLow;
+
+    return emptyString();
+}
+
+
+Vector<CaptureDeviceInfo>& AVCaptureDeviceManager::captureDeviceList()
 {
-    DEPRECATED_DEFINE_STATIC_LOCAL(Vector<CaptureDevice>, captureDeviceList, ());
     static bool firstTime = true;
-
-    if (firstTime && !captureDeviceList.size()) {
+    if (firstTime && !m_devices.size()) {
         firstTime = false;
         refreshCaptureDeviceList();
-        AVCaptureDeviceManager::singleton().registerForDeviceNotifications();
+        registerForDeviceNotifications();
     }
 
-    return captureDeviceList;
+    return m_devices;
 }
 
-static bool captureDeviceFromDeviceID(const String& captureDeviceID, CaptureDevice& source)
+inline static bool shouldConsiderDeviceInDeviceList(AVCaptureDeviceType *device)
 {
-    Vector<CaptureDevice>& devices = captureDeviceList();
-    
-    size_t count = devices.size();
-    for (size_t i = 0; i < count; ++i) {
-        if (devices[i].m_captureDeviceID == captureDeviceID) {
-            source = devices[i];
-            return true;
-        }
-    }
-    
-    return false;
+    if (![device isConnected])
+        return false;
+
+#if !PLATFORM(IOS)
+    if ([device isSuspended] || [device isInUseByAnotherApplication])
+        return false;
+#endif
+
+    return true;
 }
 
-static void refreshCaptureDeviceList()
+void AVCaptureDeviceManager::refreshCaptureDeviceList()
 {
-    Vector<CaptureDevice>& devices = captureDeviceList();
-    
-    for (AVCaptureDeviceType *device in [getAVCaptureDeviceClass() devices]) {
-        CaptureDevice source;
-
-        if (![device isConnected])
+    for (AVCaptureDeviceType *platformDevice in [getAVCaptureDeviceClass() devices]) {
+        if (!shouldConsiderDeviceInDeviceList(platformDevice))
             continue;
 
-#if !PLATFORM(IOS)
-        if ([device isSuspended] || [device isInUseByAnotherApplication])
-            continue;
-#endif
-
-        if (!captureDeviceFromDeviceID(device.uniqueID, source)) {
+        CaptureDeviceInfo captureDevice;
+        if (!captureDeviceFromDeviceID(platformDevice.uniqueID, captureDevice)) {
             // An AVCaptureDevice has a unique ID, but we can't use it for the source ID because:
             // 1. if it provides both audio and video we will need to create two sources for it
             // 2. the unique ID persists on one system across device connections, disconnections,
             //    application restarts, and reboots, so it could be used to figerprint a user.
-            source.m_captureDeviceID = device.uniqueID;
-            source.m_enabled = true;
-            if ([device hasMediaType:AVMediaTypeAudio] || [device hasMediaType:AVMediaTypeMuxed])
-                source.m_audioSourceId = createCanonicalUUIDString();
+            captureDevice.m_persistentDeviceID = platformDevice.uniqueID;
+            captureDevice.m_enabled = true;
+            captureDevice.m_groupID = createCanonicalUUIDString();
+            captureDevice.m_localizedName = platformDevice.localizedName;
+            if ([platformDevice position] == AVCaptureDevicePositionFront)
+                captureDevice.m_position = RealtimeMediaSourceStates::User;
+            if ([platformDevice position] == AVCaptureDevicePositionBack)
+                captureDevice.m_position = RealtimeMediaSourceStates::Environment;
 
-            if ([device hasMediaType:AVMediaTypeVideo] || [device hasMediaType:AVMediaTypeMuxed])
-                source.m_videoSourceId = createCanonicalUUIDString();
+            bool hasAudio = [platformDevice hasMediaType:AVMediaTypeAudio] || [platformDevice hasMediaType:AVMediaTypeMuxed];
+            bool hasVideo = [platformDevice hasMediaType:AVMediaTypeVideo] || [platformDevice hasMediaType:AVMediaTypeMuxed];
+            if (!hasAudio && !hasVideo)
+                continue;
 
-            source.m_groupID = createCanonicalUUIDString();
-            source.m_localizedName = device.localizedName;
-
-            devices.append(source);
+            // FIXME: For a given device, the source ID should persist when visiting the same request origin,
+            // but differ across different request origins.
+            captureDevice.m_sourceId = createCanonicalUUIDString();
+            captureDevice.m_sourceType = hasVideo ? RealtimeMediaSource::Video : RealtimeMediaSource::Audio;
+            if (hasVideo && hasAudio) {
+                // Add the audio component as a separate device.
+                CaptureDeviceInfo audioCaptureDevice = captureDevice;
+                audioCaptureDevice.m_sourceId = createCanonicalUUIDString();
+                audioCaptureDevice.m_sourceType = RealtimeMediaSource::Audio;
+                m_devices.append(audioCaptureDevice);
+            }
+            m_devices.append(captureDevice);
         }
     }
 }
@@ -185,7 +214,7 @@
 }
 
 AVCaptureDeviceManager::AVCaptureDeviceManager()
-    : m_objcObserver(adoptNS([[WebCoreAVCaptureDeviceManagerObserver alloc] initWithCallback:this]))
+    : m_objcObserver(adoptNS([[WebCoreAVCaptureDeviceManagerObserver alloc] initWithCallback: this]))
 {
 }
 
@@ -195,269 +224,91 @@
     [m_objcObserver disconnect];
 }
 
-String AVCaptureDeviceManager::bestSessionPresetForVideoSize(AVCaptureSessionType *captureSession, int width, int height)
+Vector<RefPtr<RealtimeMediaSource>> AVCaptureDeviceManager::bestSourcesForTypeAndConstraints(RealtimeMediaSource::Type type, PassRefPtr<MediaConstraints> constraints)
 {
-    ASSERT(width >= 0);
-    ASSERT(height >= 0);
-    
-    if (width > 1280 || height > 720)
-        // FIXME: this restriction could be adjusted with the videoMaxScaleAndCropFactor property.
-        return emptyString();
-    
-    if (width > 640 || height > 480) {
-        if (![captureSession canSetSessionPreset:AVCaptureSessionPreset1280x720])
-            emptyString();
-        return AVCaptureSessionPreset1280x720;
-    }
-    
-    if (width > 352 || height > 288) {
-        if (![captureSession canSetSessionPreset:AVCaptureSessionPreset640x480])
-            emptyString();
-        return AVCaptureSessionPreset640x480;
-    }
-    
-    if ([captureSession canSetSessionPreset:AVCaptureSessionPreset352x288])
-        return AVCaptureSessionPreset352x288;
-    
-    if ([captureSession canSetSessionPreset:AVCaptureSessionPresetLow])
-        return AVCaptureSessionPresetLow;
-    
-    return emptyString();
-}
+    if (!isAvailable())
+        return Vector<RefPtr<RealtimeMediaSource>>();
 
-bool AVCaptureDeviceManager::deviceSupportsFacingMode(AVCaptureDeviceType *device, RealtimeMediaSourceStates::VideoFacingMode facingMode)
-{
-    if (![device hasMediaType:AVMediaTypeVideo])
-        return false;
-    
-    switch (facingMode) {
-    case RealtimeMediaSourceStates::User:
-        if ([device position] == AVCaptureDevicePositionFront)
-            return true;
-        break;
-    case RealtimeMediaSourceStates::Environment:
-        if ([device position] == AVCaptureDevicePositionBack)
-            return true;
-        break;
-    case RealtimeMediaSourceStates::Left:
-    case RealtimeMediaSourceStates::Right:
-    case RealtimeMediaSourceStates::Unknown:
-        return false;
-    }
-    
-    return false;
+    return CaptureDeviceManager::bestSourcesForTypeAndConstraints(type, constraints);
 }
 
-CaptureDevice* AVCaptureDeviceManager::bestDeviceForFacingMode(RealtimeMediaSourceStates::VideoFacingMode facingMode)
+RefPtr<RealtimeMediaSource> AVCaptureDeviceManager::sourceWithUID(const String& deviceUID, RealtimeMediaSource::Type type, MediaConstraints* constraints)
 {
-    Vector<CaptureDevice>& devices = captureDeviceList();
-    
-    size_t count = devices.size();
-    for (size_t i = 0; i < count; ++i) {
-        AVCaptureDeviceType *device = [getAVCaptureDeviceClass() deviceWithUniqueID:devices[i].m_captureDeviceID];
-        ASSERT(device);
-        
-        if (device && deviceSupportsFacingMode(device, facingMode))
-            return &devices[i];
-    }
-    
-    return 0;
+    if (!isAvailable())
+        return nullptr;
+
+    return CaptureDeviceManager::sourceWithUID(deviceUID, type, constraints);
 }
 
-bool AVCaptureDeviceManager::sessionSupportsConstraint(AVCaptureSessionType *session, RealtimeMediaSource::Type type, const String& name, const String& value)
+TrackSourceInfoVector AVCaptureDeviceManager::getSourcesInfo(const String& requestOrigin)
 {
-    size_t constraint = validConstraintNames().find(name);
-    if (constraint == notFound)
-        return true;
-    
-    switch (constraint) {
-    case Width:
-        if (type == RealtimeMediaSource::Audio)
-            return false;
+    if (!isAvailable())
+        return TrackSourceInfoVector();
 
-        return !bestSessionPresetForVideoSize(session, value.toInt(), 0).isEmpty();
-    case Height:
-        if (type == RealtimeMediaSource::Audio)
-            return false;
-
-        return !bestSessionPresetForVideoSize(session, 0, value.toInt()).isEmpty();
-    case FrameRate: {
-        if (type == RealtimeMediaSource::Audio)
-            return false;
-        
-        // It would make sense to use [AVCaptureConnection videoMinFrameDuration] and
-        // [AVCaptureConnection videoMaxFrameDuration], but they only work with a "live" AVCaptureConnection.
-        float rate = value.toFloat();
-        return rate > 0 && rate <= 60;
-    }
-    case Gain: {
-        if (type != RealtimeMediaSource::Audio)
-            return false;
-        
-        float level = value.toFloat();
-        return level > 0 && level <= 1;
-    }
-    case FacingMode: {
-        if (type == RealtimeMediaSource::Audio)
-            return false;
-
-        size_t facingMode =  validFacingModes().find(value);
-        if (facingMode != notFound)
-            return false;
-        return bestDeviceForFacingMode(static_cast<RealtimeMediaSourceStates::VideoFacingMode>(facingMode));
-    }
-    }
-    
-    return false;
+    return CaptureDeviceManager::getSourcesInfo(requestOrigin);
 }
 
-bool AVCaptureDeviceManager::isValidConstraint(RealtimeMediaSource::Type type, const String& name)
+bool AVCaptureDeviceManager::verifyConstraintsForMediaType(RealtimeMediaSource::Type type, MediaConstraints* constraints, const CaptureSessionInfo* session, String& invalidConstraint)
 {
-    size_t constraint = validConstraintNames().find(name);
-    if (constraint == notFound)
+    if (!isAvailable())
         return false;
 
-    if (constraint == Gain)
-        return type == RealtimeMediaSource::Audio;
-
-    return true;
+    return CaptureDeviceManager::verifyConstraintsForMediaType(type, constraints, session, invalidConstraint);
 }
 
-Vector<RefPtr<TrackSourceInfo>> AVCaptureDeviceManager::getSourcesInfo(const String& requestOrigin)
+CaptureSessionInfo AVCaptureDeviceManager::defaultCaptureSession() const
 {
-    UNUSED_PARAM(requestOrigin);
-    Vector<RefPtr<TrackSourceInfo>> sourcesInfo;
-
-    if (!isAvailable())
-        return sourcesInfo;
-
-    Vector<CaptureDevice>& devices = captureDeviceList();
-    for (auto captureDevice : devices) {
-
-        if (!captureDevice.m_enabled)
-            continue;
-
-        if (!captureDevice.m_videoSourceId.isEmpty())
-            sourcesInfo.append(TrackSourceInfo::create(captureDevice.m_videoSourceId, TrackSourceInfo::Video, captureDevice.m_localizedName, captureDevice.m_groupID));
-        if (!captureDevice.m_audioSourceId.isEmpty())
-            sourcesInfo.append(TrackSourceInfo::create(captureDevice.m_audioSourceId, TrackSourceInfo::Audio, captureDevice.m_localizedName, captureDevice.m_groupID));
-    }
-
-    LOG(Media, "AVCaptureDeviceManager::getSourcesInfo(%p), found %d active devices", this, sourcesInfo.size());
-
-    return sourcesInfo;
+    // FIXME: I don't know if it's safe to use a static var here, since the state of a newly
+    // initialized AVCaptureSession may be different. If not, this should be static and use a
+    // static NeverDestroyed<CaptureSessionInfo>.
+    return AVCaptureSessionInfo([allocAVCaptureSessionInstance() init]);
 }
 
-bool AVCaptureDeviceManager::verifyConstraintsForMediaType(AVCaptureSessionType *session, RealtimeMediaSource::Type type, MediaConstraints* constraints, String& invalidConstraint)
+bool AVCaptureDeviceManager::sessionSupportsConstraint(const CaptureSessionInfo* session, RealtimeMediaSource::Type type, const String& name, const String& value)
 {
-    if (!isAvailable())
+    const RealtimeMediaSourceSupportedConstraints& supportedConstraints = RealtimeMediaSourceCenter::singleton().supportedConstraints();
+    MediaConstraintType constraint = supportedConstraints.constraintFromName(name);
+    if (!supportedConstraints.supportsConstraint(constraint))
         return false;
 
-    if (!constraints)
-        return true;
+    CaptureSessionInfo defaultSession = defaultCaptureSession();
+    if (!session)
+        session = &defaultSession;
 
-    Vector<MediaConstraint> mandatoryConstraints;
-    constraints->getMandatoryConstraints(mandatoryConstraints);
-    if (mandatoryConstraints.size()) {
+    if (type == RealtimeMediaSource::Video) {
+        if (constraint == MediaConstraintType::Width)
+            return session->bestSessionPresetForVideoDimensions(value.toInt(), 0) != emptyString();
 
-        RetainPtr<AVCaptureSessionType> captureSession = session ? session : adoptNS([allocAVCaptureSessionInstance() init]);
-        for (size_t i = 0; i < mandatoryConstraints.size(); ++i) {
-            const MediaConstraint& constraint = mandatoryConstraints[i];
-            if (!sessionSupportsConstraint(captureSession.get(), type, constraint.m_name, constraint.m_value)) {
-                invalidConstraint = constraint.m_name;
-                return false;
-            }
-        }
+        if (constraint == MediaConstraintType::Height)
+            return session->bestSessionPresetForVideoDimensions(0, value.toInt()) != emptyString();
     }
-
-    return true;
+    return CaptureDeviceManager::sessionSupportsConstraint(session, type, name, value);
 }
 
-Vector<RefPtr<RealtimeMediaSource>> AVCaptureDeviceManager::bestSourcesForTypeAndConstraints(RealtimeMediaSource::Type type, PassRefPtr<MediaConstraints> constraints)
+RealtimeMediaSource* AVCaptureDeviceManager::createMediaSourceForCaptureDeviceWithConstraints(const CaptureDeviceInfo& captureDevice, MediaConstraints* constraints)
 {
-    Vector<RefPtr<RealtimeMediaSource>> bestSourcesList;
-    
-    if (!isAvailable())
-        return bestSourcesList;
-    
-    struct {
-        bool operator()(RefPtr<RealtimeMediaSource> a, RefPtr<RealtimeMediaSource> b)
-        {
-            return a->fitnessScore() < b->fitnessScore();
-        }
-    } sortBasedOffFitnessScore;
+    AVCaptureDeviceType *device = [getAVCaptureDeviceClass() deviceWithUniqueID:captureDevice.m_persistentDeviceID];
+    if (!device)
+        return nullptr;
 
-    Vector<CaptureDevice>& devices = captureDeviceList();
+    RefPtr<AVMediaCaptureSource> captureSource;
+    if (captureDevice.m_sourceType == RealtimeMediaSource::Audio)
+        captureSource = AVAudioCaptureSource::create(device, captureDevice.m_sourceId, constraints);
+    else
+        captureSource = AVVideoCaptureSource::create(device, captureDevice.m_sourceId, constraints);
 
-    for (auto& captureDevice : devices) {
-        if (!captureDevice.m_enabled)
-            continue;
+    if (constraints) {
+        CaptureSessionInfo captureSession = defaultCaptureSession();
+        if (captureDevice.m_sourceType != RealtimeMediaSource::None)
+            captureSession = AVCaptureSessionInfo(captureSource->session());
 
-        if (type == RealtimeMediaSource::Audio && !captureDevice.m_audioSourceId.isEmpty()) {
-            RefPtr<RealtimeMediaSource> captureSource = AVCaptureDeviceManager::sourceWithUID(captureDevice.m_captureDeviceID, RealtimeMediaSource::Audio, constraints.get());
-            if (!captureSource)
-                continue;
-
-            bestSourcesList.append(captureSource.leakRef());
-        }
-
-        if (type == RealtimeMediaSource::Video && !captureDevice.m_videoSourceId.isEmpty()) {
-            RefPtr<RealtimeMediaSource> captureSource = AVCaptureDeviceManager::sourceWithUID(captureDevice.m_captureDeviceID, RealtimeMediaSource::Video, constraints.get());
-            if (!captureSource)
-                continue;
-
-            bestSourcesList.append(captureSource.leakRef());
-        }
+        String ignoredInvalidConstraints;
+        if (!verifyConstraintsForMediaType(captureDevice.m_sourceType, constraints, &captureSession, ignoredInvalidConstraints))
+            return nullptr;
     }
-    std::sort(bestSourcesList.begin(), bestSourcesList.end(), sortBasedOffFitnessScore);
-    return bestSourcesList;
+    return captureSource.leakRef();
 }
 
-RefPtr<RealtimeMediaSource> AVCaptureDeviceManager::sourceWithUID(const String& deviceUID, RealtimeMediaSource::Type type, MediaConstraints* constraints)
-{
-    if (!isAvailable())
-        return 0;
-
-    Vector<CaptureDevice>& devices = captureDeviceList();
-    for (auto& captureDevice : devices) {
-        if (captureDevice.m_captureDeviceID != deviceUID || !captureDevice.m_enabled)
-            continue;
-
-        if (type == RealtimeMediaSource::Audio && captureDevice.m_audioSourceId.isEmpty())
-            continue;
-        if (type == RealtimeMediaSource::Video && captureDevice.m_videoSourceId.isEmpty())
-            continue;
-
-        AVCaptureDeviceType *device = [getAVCaptureDeviceClass() deviceWithUniqueID:captureDevice.m_captureDeviceID];
-        ASSERT(device);
-
-        RefPtr<AVMediaCaptureSource> captureSource;
-        if (type == RealtimeMediaSource::Audio)
-            captureSource = AVAudioCaptureSource::create(device, captureDevice.m_audioSourceId, constraints);
-        else
-            captureSource = AVVideoCaptureSource::create(device, captureDevice.m_videoSourceId, constraints);
-
-        if (constraints) {
-            String invalidConstraints;
-            AVCaptureSessionType *session = nil;
-
-            if (type == RealtimeMediaSource::Video)
-                session = captureSource->session();
-            else if (type == RealtimeMediaSource::Audio)
-                session = captureSource->session();
-            AVCaptureDeviceManager::singleton().verifyConstraintsForMediaType(session, type, constraints, invalidConstraints);
-
-            if (!invalidConstraints.isEmpty())
-                continue;
-        }
-        
-        return captureSource.leakRef();
-    }
-    
-    return nullptr;
-
-}
-
 void AVCaptureDeviceManager::registerForDeviceNotifications()
 {
     [[NSNotificationCenter defaultCenter] addObserver:m_objcObserver.get() selector:@selector(deviceConnected:) name:AVCaptureDeviceWasConnectedNotification object:nil];
@@ -471,7 +322,7 @@
 
 void AVCaptureDeviceManager::deviceDisconnected(AVCaptureDeviceType* device)
 {
-    Vector<CaptureDevice>& devices = captureDeviceList();
+    Vector<CaptureDeviceInfo>& devices = captureDeviceList();
 
     size_t count = devices.size();
     if (!count)
@@ -479,47 +330,20 @@
 
     String deviceID = device.uniqueID;
     for (size_t i = 0; i < count; ++i) {
-        if (devices[i].m_captureDeviceID == deviceID) {
+        if (devices[i].m_persistentDeviceID == deviceID) {
             LOG(Media, "AVCaptureDeviceManager::deviceDisconnected(%p), device %d disabled", this, i);
             devices[i].m_enabled = false;
         }
     }
 }
 
-const Vector<AtomicString>& AVCaptureDeviceManager::validConstraintNames()
+bool AVCaptureDeviceManager::isSupportedFrameRate(float frameRate) const
 {
-    DEPRECATED_DEFINE_STATIC_LOCAL(Vector<AtomicString>, constraints, ());
-    static NeverDestroyed<AtomicString> heightConstraint("height", AtomicString::ConstructFromLiteral);
-    static NeverDestroyed<AtomicString> widthConstraint("width", AtomicString::ConstructFromLiteral);
-    static NeverDestroyed<AtomicString> frameRateConstraint("frameRate", AtomicString::ConstructFromLiteral);
-    static NeverDestroyed<AtomicString> facingModeConstraint("facingMode", AtomicString::ConstructFromLiteral);
-    static NeverDestroyed<AtomicString> gainConstraint("gain", AtomicString::ConstructFromLiteral);
-    
-    if (!constraints.size()) {
-        constraints.insert(Width, widthConstraint);
-        constraints.insert(Height, heightConstraint);
-        constraints.insert(FrameRate, frameRateConstraint);
-        constraints.insert(FacingMode, facingModeConstraint);
-        constraints.insert(Gain, gainConstraint);
-    }
-    
-    return constraints;
+    // FIXME: We should use [AVCaptureConnection videoMinFrameDuration] and [AVCaptureConnection videoMaxFrameDuration],
+    // but they only work with a "live" AVCaptureConnection. For now, just use the default platform-independent behavior.
+    return CaptureDeviceManager::isSupportedFrameRate(frameRate);
 }
 
-const Vector<AtomicString>& AVCaptureDeviceManager::validFacingModes()
-{
-    DEPRECATED_DEFINE_STATIC_LOCAL(Vector<AtomicString>, modes, ());
-    
-    if (!modes.size()) {
-        modes.insert(RealtimeMediaSourceStates::User, RealtimeMediaSourceStates::facingMode(RealtimeMediaSourceStates::User));
-        modes.insert(RealtimeMediaSourceStates::Environment, RealtimeMediaSourceStates::facingMode(RealtimeMediaSourceStates::Environment));
-        modes.insert(RealtimeMediaSourceStates::Left, RealtimeMediaSourceStates::facingMode(RealtimeMediaSourceStates::Left));
-        modes.insert(RealtimeMediaSourceStates::Right, RealtimeMediaSourceStates::facingMode(RealtimeMediaSourceStates::Right));
-    }
-    
-    return modes;
-}
-
 } // namespace WebCore
 
 @implementation WebCoreAVCaptureDeviceManagerObserver

Modified: trunk/Source/WebCore/platform/mediastream/mac/AVVideoCaptureSource.mm (192837 => 192838)


--- trunk/Source/WebCore/platform/mediastream/mac/AVVideoCaptureSource.mm	2015-11-30 23:27:23 UTC (rev 192837)
+++ trunk/Source/WebCore/platform/mediastream/mac/AVVideoCaptureSource.mm	2015-11-30 23:48:42 UTC (rev 192838)
@@ -37,6 +37,7 @@
 #import "MediaConstraints.h"
 #import "NotImplemented.h"
 #import "PlatformLayer.h"
+#import "RealtimeMediaSourceCenter.h"
 #import "RealtimeMediaSourceStates.h"
 #import <AVFoundation/AVFoundation.h>
 #import <objc/runtime.h>
@@ -179,36 +180,39 @@
 {
     ASSERT(constraints);
 
-    const Vector<AtomicString>& constraintNames = AVCaptureDeviceManager::validConstraintNames();
-    String widthConstraint;
-    String heightConstraint;
+    const RealtimeMediaSourceSupportedConstraints& supportedConstraints = RealtimeMediaSourceCenter::singleton().supportedConstraints();
+    String widthConstraintValue;
+    String heightConstraintValue;
+    String widthConstraintName = supportedConstraints.nameForConstraint(MediaConstraintType::Width);
+    String heightConstraintName = supportedConstraints.nameForConstraint(MediaConstraintType::Height);
 
-    constraints->getMandatoryConstraintValue(constraintNames[AVCaptureDeviceManager::Width], widthConstraint);
-    constraints->getMandatoryConstraintValue(constraintNames[AVCaptureDeviceManager::Height], heightConstraint);
+    constraints->getMandatoryConstraintValue(widthConstraintName, widthConstraintValue);
+    constraints->getMandatoryConstraintValue(heightConstraintName, heightConstraintValue);
 
-    int width = widthConstraint.toInt();
-    int height = heightConstraint.toInt();
+    int width = widthConstraintValue.toInt();
+    int height = heightConstraintValue.toInt();
     if (!width && !height) {
-        constraints->getOptionalConstraintValue(constraintNames[AVCaptureDeviceManager::Width], widthConstraint);
-        constraints->getOptionalConstraintValue(constraintNames[AVCaptureDeviceManager::Height], heightConstraint);
-        width = widthConstraint.toInt();
-        height = heightConstraint.toInt();
+        constraints->getOptionalConstraintValue(widthConstraintName, widthConstraintValue);
+        constraints->getOptionalConstraintValue(heightConstraintName, heightConstraintValue);
+        width = widthConstraintValue.toInt();
+        height = heightConstraintValue.toInt();
     }
     
     if (width || height) {
-        NSString *preset = AVCaptureDeviceManager::bestSessionPresetForVideoSize(session(), width, height);
+        NSString *preset = AVCaptureSessionInfo(session()).bestSessionPresetForVideoDimensions(width, height);
         if (!preset || ![session() canSetSessionPreset:preset])
             return false;
         
         [session() setSessionPreset:preset];
     }
 
-    String frameRateConstraint;
-    constraints->getMandatoryConstraintValue(constraintNames[AVCaptureDeviceManager::FrameRate], frameRateConstraint);
-    float frameRate = frameRateConstraint.toFloat();
+    String frameRateConstraintValue;
+    String frameRateConstraintName = supportedConstraints.nameForConstraint(MediaConstraintType::FrameRate);
+    constraints->getMandatoryConstraintValue(frameRateConstraintName, frameRateConstraintValue);
+    float frameRate = frameRateConstraintValue.toFloat();
     if (!frameRate) {
-        constraints->getOptionalConstraintValue(constraintNames[AVCaptureDeviceManager::FrameRate], frameRateConstraint);
-        frameRate = frameRateConstraint.toFloat();
+        constraints->getOptionalConstraintValue(frameRateConstraintName, frameRateConstraintValue);
+        frameRate = frameRateConstraintValue.toFloat();
     }
     if (frameRate && !setFrameRateConstraint(frameRate, 0))
         return false;

Modified: trunk/Source/WebCore/platform/mediastream/mac/RealtimeMediaSourceCenterMac.cpp (192837 => 192838)


--- trunk/Source/WebCore/platform/mediastream/mac/RealtimeMediaSourceCenterMac.cpp	2015-11-30 23:27:23 UTC (rev 192837)
+++ trunk/Source/WebCore/platform/mediastream/mac/RealtimeMediaSourceCenterMac.cpp	2015-11-30 23:48:42 UTC (rev 192838)
@@ -76,7 +76,7 @@
 
     if (audioConstraints) {
         String invalidConstraint;
-        AVCaptureDeviceManager::singleton().verifyConstraintsForMediaType(nil, RealtimeMediaSource::Audio, audioConstraints.get(), invalidConstraint);
+        AVCaptureDeviceManager::singleton().verifyConstraintsForMediaType(RealtimeMediaSource::Audio, audioConstraints.get(), nullptr, invalidConstraint);
         if (!invalidConstraint.isEmpty()) {
             client->constraintsInvalid(invalidConstraint);
             return;
@@ -87,7 +87,7 @@
 
     if (videoConstraints) {
         String invalidConstraint;
-        AVCaptureDeviceManager::singleton().verifyConstraintsForMediaType(nil, RealtimeMediaSource::Video, videoConstraints.get(), invalidConstraint);
+        AVCaptureDeviceManager::singleton().verifyConstraintsForMediaType(RealtimeMediaSource::Video, videoConstraints.get(), nullptr, invalidConstraint);
         if (!invalidConstraint.isEmpty()) {
             client->constraintsInvalid(invalidConstraint);
             return;
@@ -109,7 +109,7 @@
     
     if (audioConstraints) {
         String invalidConstraint;
-        AVCaptureDeviceManager::singleton().verifyConstraintsForMediaType(nil, RealtimeMediaSource::Audio, audioConstraints.get(), invalidConstraint);
+        AVCaptureDeviceManager::singleton().verifyConstraintsForMediaType(RealtimeMediaSource::Audio, audioConstraints.get(), nullptr, invalidConstraint);
         if (!invalidConstraint.isEmpty()) {
             client->failedToCreateStreamWithConstraintsError(invalidConstraint);
             return;
@@ -124,7 +124,7 @@
     
     if (videoConstraints) {
         String invalidConstraint;
-        AVCaptureDeviceManager::singleton().verifyConstraintsForMediaType(nil, RealtimeMediaSource::Video, videoConstraints.get(), invalidConstraint);
+        AVCaptureDeviceManager::singleton().verifyConstraintsForMediaType(RealtimeMediaSource::Video, videoConstraints.get(), nullptr, invalidConstraint);
         if (!invalidConstraint.isEmpty()) {
             client->failedToCreateStreamWithConstraintsError(invalidConstraint);
             return;
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to