2 * Copyright (C) 2015 Apple Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 #import "CaptureDeviceManager.h"
29 #if ENABLE(MEDIA_STREAM)
32 #import "MediaConstraints.h"
33 #import "RealtimeMediaSource.h"
34 #import "RealtimeMediaSourceCenter.h"
35 #import "RealtimeMediaSourceSettings.h"
37 #import <wtf/MainThread.h>
38 #import <wtf/NeverDestroyed.h>
40 using namespace WebCore;
42 CaptureDeviceManager::~CaptureDeviceManager()
46 Vector<RefPtr<TrackSourceInfo>> CaptureDeviceManager::getSourcesInfo(const String& requestOrigin)
48 UNUSED_PARAM(requestOrigin);
49 Vector<RefPtr<TrackSourceInfo>> sourcesInfo;
50 for (auto captureDevice : captureDeviceList()) {
51 if (!captureDevice.m_enabled || captureDevice.m_sourceType == RealtimeMediaSource::None)
54 TrackSourceInfo::SourceKind trackSourceType = captureDevice.m_sourceType == RealtimeMediaSource::Video ? TrackSourceInfo::Video : TrackSourceInfo::Audio;
55 sourcesInfo.append(TrackSourceInfo::create(captureDevice.m_persistentDeviceID, captureDevice.m_sourceId, trackSourceType, captureDevice.m_localizedName, captureDevice.m_groupID));
57 LOG(Media, "CaptureDeviceManager::getSourcesInfo(%p), found %zu active devices", this, sourcesInfo.size());
61 bool CaptureDeviceManager::captureDeviceFromDeviceID(const String& captureDeviceID, CaptureDeviceInfo& foundDevice)
63 for (auto& device : captureDeviceList()) {
64 if (device.m_persistentDeviceID == captureDeviceID) {
73 bool CaptureDeviceManager::verifyConstraintsForMediaType(RealtimeMediaSource::Type type, MediaConstraints* constraints, const CaptureSessionInfo* session, String& invalidConstraint)
78 Vector<MediaConstraint> mandatoryConstraints;
79 constraints->getMandatoryConstraints(mandatoryConstraints);
80 for (auto& constraint : mandatoryConstraints) {
81 if (sessionSupportsConstraint(session, type, constraint.m_name, constraint.m_value))
84 invalidConstraint = constraint.m_name;
91 Vector<RefPtr<RealtimeMediaSource>> CaptureDeviceManager::bestSourcesForTypeAndConstraints(RealtimeMediaSource::Type type, MediaConstraints& constraints)
93 Vector<RefPtr<RealtimeMediaSource>> bestSourcesList;
96 bool operator()(RefPtr<RealtimeMediaSource> a, RefPtr<RealtimeMediaSource> b)
98 return a->fitnessScore() < b->fitnessScore();
100 } sortBasedOnFitnessScore;
102 for (auto& captureDevice : captureDeviceList()) {
103 if (!captureDevice.m_enabled || captureDevice.m_sourceId.isEmpty() || captureDevice.m_sourceType == RealtimeMediaSource::None)
106 if (RefPtr<RealtimeMediaSource> captureSource = sourceWithUID(captureDevice.m_persistentDeviceID, type, &constraints))
107 bestSourcesList.append(captureSource.leakRef());
109 std::sort(bestSourcesList.begin(), bestSourcesList.end(), sortBasedOnFitnessScore);
110 return bestSourcesList;
113 RefPtr<RealtimeMediaSource> CaptureDeviceManager::sourceWithUID(const String& deviceUID, RealtimeMediaSource::Type type, MediaConstraints* constraints)
115 for (auto& captureDevice : captureDeviceList()) {
116 if (captureDevice.m_persistentDeviceID != deviceUID || captureDevice.m_sourceType != type)
119 if (!captureDevice.m_enabled || type == RealtimeMediaSource::None || captureDevice.m_sourceId.isEmpty())
122 if (RealtimeMediaSource* mediaSource = createMediaSourceForCaptureDeviceWithConstraints(captureDevice, constraints))
128 CaptureDeviceInfo* CaptureDeviceManager::bestDeviceForFacingMode(RealtimeMediaSourceSettings::VideoFacingMode facingMode)
130 if (facingMode == RealtimeMediaSourceSettings::Unknown)
133 for (auto& device : captureDeviceList()) {
134 if (device.m_sourceType == RealtimeMediaSource::Video && device.m_position == facingMode)
140 static inline RealtimeMediaSourceSettings::VideoFacingMode facingModeFromString(const String& facingModeString)
142 static NeverDestroyed<AtomicString> userFacingModeString("user", AtomicString::ConstructFromLiteral);
143 static NeverDestroyed<AtomicString> environmentFacingModeString("environment", AtomicString::ConstructFromLiteral);
144 static NeverDestroyed<AtomicString> leftFacingModeString("left", AtomicString::ConstructFromLiteral);
145 static NeverDestroyed<AtomicString> rightFacingModeString("right", AtomicString::ConstructFromLiteral);
146 if (facingModeString == userFacingModeString)
147 return RealtimeMediaSourceSettings::User;
148 if (facingModeString == environmentFacingModeString)
149 return RealtimeMediaSourceSettings::Environment;
150 if (facingModeString == leftFacingModeString)
151 return RealtimeMediaSourceSettings::Left;
152 if (facingModeString == rightFacingModeString)
153 return RealtimeMediaSourceSettings::Right;
154 return RealtimeMediaSourceSettings::Unknown;
157 bool CaptureDeviceManager::sessionSupportsConstraint(const CaptureSessionInfo*, RealtimeMediaSource::Type type, const String& name, const String& value)
159 const RealtimeMediaSourceSupportedConstraints& supportedConstraints = RealtimeMediaSourceCenter::singleton().supportedConstraints();
160 MediaConstraintType constraint = supportedConstraints.constraintFromName(name);
161 if (!supportedConstraints.supportsConstraint(constraint))
164 switch (constraint) {
165 case MediaConstraintType::Width:
166 return type == RealtimeMediaSource::Video;
168 case MediaConstraintType::Height:
169 return type == RealtimeMediaSource::Video;
171 case MediaConstraintType::FrameRate: {
172 if (type == RealtimeMediaSource::Audio)
175 return isSupportedFrameRate(value.toFloat());
177 case MediaConstraintType::FacingMode: {
178 if (type == RealtimeMediaSource::Audio)
181 return bestDeviceForFacingMode(facingModeFromString(value));
188 bool CaptureDeviceManager::isSupportedFrameRate(float frameRate) const
190 return 0 < frameRate && frameRate <= 60;
193 #endif // ENABLE(MEDIA_STREAM)