blob: ac78cbc84a59b1fc2f1bbb41385f5bdfac1b4eaf [file] [log] [blame]
niklase@google.com470e71d2011-07-07 08:21:25 +00001/*
mallinath@webrtc.org12984f02012-02-16 18:18:21 +00002 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
niklase@google.com470e71d2011-07-07 08:21:25 +00003 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
Jonas Olssona4d87372019-07-05 19:08:33 +020011#include "modules/video_capture/device_info_impl.h"
12
niklase@google.com470e71d2011-07-07 08:21:25 +000013#include <stdlib.h>
14
Niels Mölleraa3c1cc2018-11-02 10:54:56 +010015#include "absl/strings/match.h"
Yves Gerey3e707812018-11-28 16:47:49 +010016#include "absl/strings/string_view.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020017#include "rtc_base/logging.h"
pbos@webrtc.orga9b74ad2013-07-12 10:03:52 +000018
niklase@google.com470e71d2011-07-07 08:21:25 +000019#ifndef abs
Mirko Bonadei72c42502017-11-09 09:33:23 +010020#define abs(a) (a >= 0 ? a : -a)
niklase@google.com470e71d2011-07-07 08:21:25 +000021#endif
22
Mirko Bonadei72c42502017-11-09 09:33:23 +010023namespace webrtc {
24namespace videocapturemodule {
Sergey Ulanov6acefdb2017-12-11 17:38:13 -080025
nisseb29b9c82016-12-12 00:22:56 -080026DeviceInfoImpl::DeviceInfoImpl()
Niels Möller5b5de212020-10-28 17:18:56 +010027 : _lastUsedDeviceName(NULL), _lastUsedDeviceNameLength(0) {}
Mirko Bonadei72c42502017-11-09 09:33:23 +010028
29DeviceInfoImpl::~DeviceInfoImpl(void) {
Niels Möller5b5de212020-10-28 17:18:56 +010030 MutexLock lock(&_apiLock);
Mirko Bonadei72c42502017-11-09 09:33:23 +010031 free(_lastUsedDeviceName);
niklase@google.com470e71d2011-07-07 08:21:25 +000032}
Sergey Ulanov6acefdb2017-12-11 17:38:13 -080033
Mirko Bonadei72c42502017-11-09 09:33:23 +010034int32_t DeviceInfoImpl::NumberOfCapabilities(const char* deviceUniqueIdUTF8) {
35 if (!deviceUniqueIdUTF8)
36 return -1;
niklase@google.com470e71d2011-07-07 08:21:25 +000037
Niels Möller5b5de212020-10-28 17:18:56 +010038 MutexLock lock(&_apiLock);
niklase@google.com470e71d2011-07-07 08:21:25 +000039
Niels Mölleraa3c1cc2018-11-02 10:54:56 +010040 // Is it the same device that is asked for again.
41 if (absl::EqualsIgnoreCase(
42 deviceUniqueIdUTF8,
43 absl::string_view(_lastUsedDeviceName, _lastUsedDeviceNameLength))) {
Niels Mölleraa3c1cc2018-11-02 10:54:56 +010044 return static_cast<int32_t>(_captureCapabilities.size());
Mirko Bonadei72c42502017-11-09 09:33:23 +010045 }
niklase@google.com470e71d2011-07-07 08:21:25 +000046
Mirko Bonadei72c42502017-11-09 09:33:23 +010047 int32_t ret = CreateCapabilityMap(deviceUniqueIdUTF8);
48 return ret;
niklase@google.com470e71d2011-07-07 08:21:25 +000049}
50
pbos@webrtc.orgdfc5bb92013-04-10 08:23:13 +000051int32_t DeviceInfoImpl::GetCapability(const char* deviceUniqueIdUTF8,
52 const uint32_t deviceCapabilityNumber,
Mirko Bonadei72c42502017-11-09 09:33:23 +010053 VideoCaptureCapability& capability) {
Mirko Bonadei25ab3222021-07-08 20:08:20 +020054 RTC_DCHECK(deviceUniqueIdUTF8);
niklase@google.com470e71d2011-07-07 08:21:25 +000055
Niels Möller5b5de212020-10-28 17:18:56 +010056 MutexLock lock(&_apiLock);
niklase@google.com470e71d2011-07-07 08:21:25 +000057
Niels Mölleraa3c1cc2018-11-02 10:54:56 +010058 if (!absl::EqualsIgnoreCase(
59 deviceUniqueIdUTF8,
60 absl::string_view(_lastUsedDeviceName, _lastUsedDeviceNameLength))) {
Mirko Bonadei72c42502017-11-09 09:33:23 +010061 if (-1 == CreateCapabilityMap(deviceUniqueIdUTF8)) {
Mirko Bonadei72c42502017-11-09 09:33:23 +010062 return -1;
niklase@google.com470e71d2011-07-07 08:21:25 +000063 }
Mirko Bonadei72c42502017-11-09 09:33:23 +010064 }
niklase@google.com470e71d2011-07-07 08:21:25 +000065
Mirko Bonadei72c42502017-11-09 09:33:23 +010066 // Make sure the number is valid
67 if (deviceCapabilityNumber >= (unsigned int)_captureCapabilities.size()) {
Mirko Bonadei675513b2017-11-09 11:09:25 +010068 RTC_LOG(LS_ERROR) << "Invalid deviceCapabilityNumber "
69 << deviceCapabilityNumber << ">= number of capabilities ("
70 << _captureCapabilities.size() << ").";
Mirko Bonadei72c42502017-11-09 09:33:23 +010071 return -1;
72 }
niklase@google.com470e71d2011-07-07 08:21:25 +000073
Mirko Bonadei72c42502017-11-09 09:33:23 +010074 capability = _captureCapabilities[deviceCapabilityNumber];
75 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +000076}
77
pbos@webrtc.orgdfc5bb92013-04-10 08:23:13 +000078int32_t DeviceInfoImpl::GetBestMatchedCapability(
Mirko Bonadei72c42502017-11-09 09:33:23 +010079 const char* deviceUniqueIdUTF8,
80 const VideoCaptureCapability& requested,
81 VideoCaptureCapability& resulting) {
82 if (!deviceUniqueIdUTF8)
83 return -1;
niklase@google.com470e71d2011-07-07 08:21:25 +000084
Niels Möller5b5de212020-10-28 17:18:56 +010085 MutexLock lock(&_apiLock);
Niels Mölleraa3c1cc2018-11-02 10:54:56 +010086 if (!absl::EqualsIgnoreCase(
87 deviceUniqueIdUTF8,
88 absl::string_view(_lastUsedDeviceName, _lastUsedDeviceNameLength))) {
Mirko Bonadei72c42502017-11-09 09:33:23 +010089 if (-1 == CreateCapabilityMap(deviceUniqueIdUTF8)) {
90 return -1;
niklase@google.com470e71d2011-07-07 08:21:25 +000091 }
Mirko Bonadei72c42502017-11-09 09:33:23 +010092 }
niklase@google.com470e71d2011-07-07 08:21:25 +000093
Mirko Bonadei72c42502017-11-09 09:33:23 +010094 int32_t bestformatIndex = -1;
95 int32_t bestWidth = 0;
96 int32_t bestHeight = 0;
97 int32_t bestFrameRate = 0;
98 VideoType bestVideoType = VideoType::kUnknown;
niklase@google.com470e71d2011-07-07 08:21:25 +000099
Mirko Bonadei72c42502017-11-09 09:33:23 +0100100 const int32_t numberOfCapabilies =
101 static_cast<int32_t>(_captureCapabilities.size());
niklase@google.com470e71d2011-07-07 08:21:25 +0000102
Mirko Bonadei72c42502017-11-09 09:33:23 +0100103 for (int32_t tmp = 0; tmp < numberOfCapabilies;
104 ++tmp) // Loop through all capabilities
105 {
106 VideoCaptureCapability& capability = _captureCapabilities[tmp];
niklase@google.com470e71d2011-07-07 08:21:25 +0000107
Mirko Bonadei72c42502017-11-09 09:33:23 +0100108 const int32_t diffWidth = capability.width - requested.width;
109 const int32_t diffHeight = capability.height - requested.height;
110 const int32_t diffFrameRate = capability.maxFPS - requested.maxFPS;
niklase@google.com470e71d2011-07-07 08:21:25 +0000111
Mirko Bonadei72c42502017-11-09 09:33:23 +0100112 const int32_t currentbestDiffWith = bestWidth - requested.width;
113 const int32_t currentbestDiffHeight = bestHeight - requested.height;
114 const int32_t currentbestDiffFrameRate = bestFrameRate - requested.maxFPS;
niklase@google.com470e71d2011-07-07 08:21:25 +0000115
Mirko Bonadei72c42502017-11-09 09:33:23 +0100116 if ((diffHeight >= 0 &&
117 diffHeight <= abs(currentbestDiffHeight)) // Height better or equalt
118 // that previouse.
119 || (currentbestDiffHeight < 0 && diffHeight >= currentbestDiffHeight)) {
120 if (diffHeight ==
121 currentbestDiffHeight) // Found best height. Care about the width)
122 {
123 if ((diffWidth >= 0 &&
124 diffWidth <= abs(currentbestDiffWith)) // Width better or equal
125 || (currentbestDiffWith < 0 && diffWidth >= currentbestDiffWith)) {
126 if (diffWidth == currentbestDiffWith &&
127 diffHeight == currentbestDiffHeight) // Same size as previously
128 {
129 // Also check the best frame rate if the diff is the same as
130 // previouse
131 if (((diffFrameRate >= 0 &&
132 diffFrameRate <=
133 currentbestDiffFrameRate) // Frame rate to high but
134 // better match than previouse
135 // and we have not selected IUV
136 || (currentbestDiffFrameRate < 0 &&
137 diffFrameRate >=
138 currentbestDiffFrameRate)) // Current frame rate is
139 // lower than requested.
140 // This is better.
Jonas Olssona4d87372019-07-05 19:08:33 +0200141 ) {
Mirko Bonadei72c42502017-11-09 09:33:23 +0100142 if ((currentbestDiffFrameRate ==
143 diffFrameRate) // Same frame rate as previous or frame rate
144 // allready good enough
145 || (currentbestDiffFrameRate >= 0)) {
146 if (bestVideoType != requested.videoType &&
147 requested.videoType != VideoType::kUnknown &&
148 (capability.videoType == requested.videoType ||
149 capability.videoType == VideoType::kI420 ||
150 capability.videoType == VideoType::kYUY2 ||
151 capability.videoType == VideoType::kYV12)) {
152 bestVideoType = capability.videoType;
153 bestformatIndex = tmp;
154 }
155 // If width height and frame rate is full filled we can use the
156 // camera for encoding if it is supported.
157 if (capability.height == requested.height &&
158 capability.width == requested.width &&
159 capability.maxFPS >= requested.maxFPS) {
160 bestformatIndex = tmp;
161 }
162 } else // Better frame rate
163 {
nisse1e321222017-02-20 23:27:37 -0800164 bestWidth = capability.width;
165 bestHeight = capability.height;
166 bestFrameRate = capability.maxFPS;
nisseeb44b392017-04-28 07:18:05 -0700167 bestVideoType = capability.videoType;
nisse1e321222017-02-20 23:27:37 -0800168 bestformatIndex = tmp;
Mirko Bonadei72c42502017-11-09 09:33:23 +0100169 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000170 }
Mirko Bonadei72c42502017-11-09 09:33:23 +0100171 } else // Better width than previously
172 {
173 bestWidth = capability.width;
174 bestHeight = capability.height;
175 bestFrameRate = capability.maxFPS;
176 bestVideoType = capability.videoType;
177 bestformatIndex = tmp;
178 }
179 } // else width no good
180 } else // Better height
181 {
182 bestWidth = capability.width;
183 bestHeight = capability.height;
184 bestFrameRate = capability.maxFPS;
185 bestVideoType = capability.videoType;
186 bestformatIndex = tmp;
187 }
188 } // else height not good
189 } // end for
niklase@google.com470e71d2011-07-07 08:21:25 +0000190
Mirko Bonadei675513b2017-11-09 11:09:25 +0100191 RTC_LOG(LS_VERBOSE) << "Best camera format: " << bestWidth << "x"
192 << bestHeight << "@" << bestFrameRate
193 << "fps, color format: "
194 << static_cast<int>(bestVideoType);
niklase@google.com470e71d2011-07-07 08:21:25 +0000195
Mirko Bonadei72c42502017-11-09 09:33:23 +0100196 // Copy the capability
197 if (bestformatIndex < 0)
198 return -1;
199 resulting = _captureCapabilities[bestformatIndex];
200 return bestformatIndex;
niklase@google.com470e71d2011-07-07 08:21:25 +0000201}
202
Mirko Bonadei72c42502017-11-09 09:33:23 +0100203// Default implementation. This should be overridden by Mobile implementations.
pbos@webrtc.orgdfc5bb92013-04-10 08:23:13 +0000204int32_t DeviceInfoImpl::GetOrientation(const char* deviceUniqueIdUTF8,
guoweis@webrtc.org5a7dc392015-02-13 14:31:26 +0000205 VideoRotation& orientation) {
206 orientation = kVideoRotation_0;
Mirko Bonadei72c42502017-11-09 09:33:23 +0100207 return -1;
niklase@google.com470e71d2011-07-07 08:21:25 +0000208}
pbos@webrtc.orgd900e8b2013-07-03 15:12:26 +0000209} // namespace videocapturemodule
210} // namespace webrtc