blob: 472db49d3f5d17d6257a248d8bb37546a9328fc5 [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
pbos@webrtc.org3d5cb332014-05-14 08:42:07 +000011#include <assert.h>
niklase@google.com470e71d2011-07-07 08:21:25 +000012#include <stdlib.h>
13
pbos@webrtc.orga9b74ad2013-07-12 10:03:52 +000014#include "webrtc/modules/video_capture/device_info_impl.h"
15#include "webrtc/modules/video_capture/video_capture_config.h"
Henrik Kjellander98f53512015-10-28 18:17:40 +010016#include "webrtc/system_wrappers/include/logging.h"
pbos@webrtc.orga9b74ad2013-07-12 10:03:52 +000017
niklase@google.com470e71d2011-07-07 08:21:25 +000018#ifndef abs
19#define abs(a) (a>=0?a:-a)
20#endif
21
22namespace webrtc
23{
24namespace videocapturemodule
25{
nisseb29b9c82016-12-12 00:22:56 -080026DeviceInfoImpl::DeviceInfoImpl()
27 : _apiLock(*RWLockWrapper::CreateRWLock()), _lastUsedDeviceName(NULL),
niklase@google.com470e71d2011-07-07 08:21:25 +000028 _lastUsedDeviceNameLength(0)
29{
30}
31
32DeviceInfoImpl::~DeviceInfoImpl(void)
33{
34 _apiLock.AcquireLockExclusive();
niklase@google.com470e71d2011-07-07 08:21:25 +000035 free(_lastUsedDeviceName);
36 _apiLock.ReleaseLockExclusive();
37
38 delete &_apiLock;
39}
pbos@webrtc.orgdfc5bb92013-04-10 08:23:13 +000040int32_t DeviceInfoImpl::NumberOfCapabilities(
leozwang@webrtc.org1745e932012-03-01 16:30:40 +000041 const char* deviceUniqueIdUTF8)
niklase@google.com470e71d2011-07-07 08:21:25 +000042{
niklase@google.com470e71d2011-07-07 08:21:25 +000043
44 if (!deviceUniqueIdUTF8)
45 return -1;
46
47 _apiLock.AcquireLockShared();
48
49 if (_lastUsedDeviceNameLength == strlen((char*) deviceUniqueIdUTF8))
50 {
51 // Is it the same device that is asked for again.
andrew@webrtc.orgf3b65db2012-09-06 18:17:00 +000052#if defined(WEBRTC_MAC) || defined(WEBRTC_LINUX)
niklase@google.com470e71d2011-07-07 08:21:25 +000053 if(strncasecmp((char*)_lastUsedDeviceName,
54 (char*) deviceUniqueIdUTF8,
55 _lastUsedDeviceNameLength)==0)
56#else
57 if (_strnicmp((char*) _lastUsedDeviceName,
58 (char*) deviceUniqueIdUTF8,
59 _lastUsedDeviceNameLength) == 0)
60#endif
61 {
62 //yes
63 _apiLock.ReleaseLockShared();
pbos@webrtc.org4ca7d3f2013-08-12 19:51:57 +000064 return static_cast<int32_t>(_captureCapabilities.size());
niklase@google.com470e71d2011-07-07 08:21:25 +000065 }
66 }
67 // Need to get exclusive rights to create the new capability map.
68 _apiLock.ReleaseLockShared();
69 WriteLockScoped cs2(_apiLock);
70
pbos@webrtc.orgdfc5bb92013-04-10 08:23:13 +000071 int32_t ret = CreateCapabilityMap(deviceUniqueIdUTF8);
niklase@google.com470e71d2011-07-07 08:21:25 +000072 return ret;
73}
74
pbos@webrtc.orgdfc5bb92013-04-10 08:23:13 +000075int32_t DeviceInfoImpl::GetCapability(const char* deviceUniqueIdUTF8,
76 const uint32_t deviceCapabilityNumber,
77 VideoCaptureCapability& capability)
niklase@google.com470e71d2011-07-07 08:21:25 +000078{
pbos@webrtc.org3d5cb332014-05-14 08:42:07 +000079 assert(deviceUniqueIdUTF8 != NULL);
niklase@google.com470e71d2011-07-07 08:21:25 +000080
niklase@google.com470e71d2011-07-07 08:21:25 +000081 ReadLockScoped cs(_apiLock);
82
83 if ((_lastUsedDeviceNameLength != strlen((char*) deviceUniqueIdUTF8))
andrew@webrtc.orgf3b65db2012-09-06 18:17:00 +000084#if defined(WEBRTC_MAC) || defined(WEBRTC_LINUX)
niklase@google.com470e71d2011-07-07 08:21:25 +000085 || (strncasecmp((char*)_lastUsedDeviceName,
86 (char*) deviceUniqueIdUTF8,
87 _lastUsedDeviceNameLength)!=0))
88#else
89 || (_strnicmp((char*) _lastUsedDeviceName,
90 (char*) deviceUniqueIdUTF8,
91 _lastUsedDeviceNameLength) != 0))
92#endif
93
94 {
95 _apiLock.ReleaseLockShared();
96 _apiLock.AcquireLockExclusive();
97 if (-1 == CreateCapabilityMap(deviceUniqueIdUTF8))
98 {
99 _apiLock.ReleaseLockExclusive();
100 _apiLock.AcquireLockShared();
101 return -1;
102 }
103 _apiLock.ReleaseLockExclusive();
104 _apiLock.AcquireLockShared();
105 }
106
107 // Make sure the number is valid
pbos@webrtc.org4ca7d3f2013-08-12 19:51:57 +0000108 if (deviceCapabilityNumber >= (unsigned int) _captureCapabilities.size())
niklase@google.com470e71d2011-07-07 08:21:25 +0000109 {
pbos@webrtc.org3d5cb332014-05-14 08:42:07 +0000110 LOG(LS_ERROR) << "Invalid deviceCapabilityNumber "
111 << deviceCapabilityNumber << ">= number of capabilities ("
112 << _captureCapabilities.size() << ").";
niklase@google.com470e71d2011-07-07 08:21:25 +0000113 return -1;
114 }
115
fischman@webrtc.org69fc3152013-09-25 17:01:42 +0000116 capability = _captureCapabilities[deviceCapabilityNumber];
niklase@google.com470e71d2011-07-07 08:21:25 +0000117 return 0;
118}
119
pbos@webrtc.orgdfc5bb92013-04-10 08:23:13 +0000120int32_t DeviceInfoImpl::GetBestMatchedCapability(
leozwang@webrtc.org1745e932012-03-01 16:30:40 +0000121 const char*deviceUniqueIdUTF8,
mallinath@webrtc.org12984f02012-02-16 18:18:21 +0000122 const VideoCaptureCapability& requested,
niklase@google.com470e71d2011-07-07 08:21:25 +0000123 VideoCaptureCapability& resulting)
124{
125
niklase@google.com470e71d2011-07-07 08:21:25 +0000126
127 if (!deviceUniqueIdUTF8)
128 return -1;
129
130 ReadLockScoped cs(_apiLock);
131 if ((_lastUsedDeviceNameLength != strlen((char*) deviceUniqueIdUTF8))
andrew@webrtc.orgf3b65db2012-09-06 18:17:00 +0000132#if defined(WEBRTC_MAC) || defined(WEBRTC_LINUX)
niklase@google.com470e71d2011-07-07 08:21:25 +0000133 || (strncasecmp((char*)_lastUsedDeviceName,
134 (char*) deviceUniqueIdUTF8,
135 _lastUsedDeviceNameLength)!=0))
136#else
137 || (_strnicmp((char*) _lastUsedDeviceName,
138 (char*) deviceUniqueIdUTF8,
139 _lastUsedDeviceNameLength) != 0))
140#endif
141 {
142 _apiLock.ReleaseLockShared();
143 _apiLock.AcquireLockExclusive();
144 if (-1 == CreateCapabilityMap(deviceUniqueIdUTF8))
145 {
146 return -1;
147 }
148 _apiLock.ReleaseLockExclusive();
149 _apiLock.AcquireLockShared();
150 }
151
pbos@webrtc.orgdfc5bb92013-04-10 08:23:13 +0000152 int32_t bestformatIndex = -1;
153 int32_t bestWidth = 0;
154 int32_t bestHeight = 0;
155 int32_t bestFrameRate = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000156 RawVideoType bestRawType = kVideoUnknown;
niklase@google.com470e71d2011-07-07 08:21:25 +0000157
pbos@webrtc.org4ca7d3f2013-08-12 19:51:57 +0000158 const int32_t numberOfCapabilies =
159 static_cast<int32_t>(_captureCapabilities.size());
niklase@google.com470e71d2011-07-07 08:21:25 +0000160
pbos@webrtc.orgdfc5bb92013-04-10 08:23:13 +0000161 for (int32_t tmp = 0; tmp < numberOfCapabilies; ++tmp) // Loop through all capabilities
niklase@google.com470e71d2011-07-07 08:21:25 +0000162 {
fischman@webrtc.org69fc3152013-09-25 17:01:42 +0000163 VideoCaptureCapability& capability = _captureCapabilities[tmp];
niklase@google.com470e71d2011-07-07 08:21:25 +0000164
pbos@webrtc.orgdfc5bb92013-04-10 08:23:13 +0000165 const int32_t diffWidth = capability.width - requested.width;
166 const int32_t diffHeight = capability.height - requested.height;
167 const int32_t diffFrameRate = capability.maxFPS - requested.maxFPS;
niklase@google.com470e71d2011-07-07 08:21:25 +0000168
pbos@webrtc.orgdfc5bb92013-04-10 08:23:13 +0000169 const int32_t currentbestDiffWith = bestWidth - requested.width;
170 const int32_t currentbestDiffHeight = bestHeight - requested.height;
171 const int32_t currentbestDiffFrameRate = bestFrameRate - requested.maxFPS;
niklase@google.com470e71d2011-07-07 08:21:25 +0000172
173 if ((diffHeight >= 0 && diffHeight <= abs(currentbestDiffHeight)) // Height better or equalt that previouse.
174 || (currentbestDiffHeight < 0 && diffHeight >= currentbestDiffHeight))
175 {
176
177 if (diffHeight == currentbestDiffHeight) // Found best height. Care about the width)
178 {
179 if ((diffWidth >= 0 && diffWidth <= abs(currentbestDiffWith)) // Width better or equal
180 || (currentbestDiffWith < 0 && diffWidth >= currentbestDiffWith))
181 {
182 if (diffWidth == currentbestDiffWith && diffHeight
183 == currentbestDiffHeight) // Same size as previously
184 {
185 //Also check the best frame rate if the diff is the same as previouse
186 if (((diffFrameRate >= 0 &&
187 diffFrameRate <= currentbestDiffFrameRate) // Frame rate to high but better match than previouse and we have not selected IUV
188 ||
189 (currentbestDiffFrameRate < 0 &&
190 diffFrameRate >= currentbestDiffFrameRate)) // Current frame rate is lower than requested. This is better.
191 )
192 {
193 if ((currentbestDiffFrameRate == diffFrameRate) // Same frame rate as previous or frame rate allready good enough
194 || (currentbestDiffFrameRate >= 0))
195 {
196 if (bestRawType != requested.rawType
197 && requested.rawType != kVideoUnknown
198 && (capability.rawType == requested.rawType
199 || capability.rawType == kVideoI420
200 || capability.rawType == kVideoYUY2
201 || capability.rawType == kVideoYV12))
202 {
niklase@google.com470e71d2011-07-07 08:21:25 +0000203 bestRawType = capability.rawType;
204 bestformatIndex = tmp;
205 }
206 // If width height and frame rate is full filled we can use the camera for encoding if it is supported.
207 if (capability.height == requested.height
208 && capability.width == requested.width
209 && capability.maxFPS >= requested.maxFPS)
210 {
nisse1e321222017-02-20 23:27:37 -0800211 bestformatIndex = tmp;
niklase@google.com470e71d2011-07-07 08:21:25 +0000212 }
213 }
214 else // Better frame rate
215 {
nisse1e321222017-02-20 23:27:37 -0800216 bestWidth = capability.width;
217 bestHeight = capability.height;
218 bestFrameRate = capability.maxFPS;
219 bestRawType = capability.rawType;
220 bestformatIndex = tmp;
niklase@google.com470e71d2011-07-07 08:21:25 +0000221 }
222 }
223 }
224 else // Better width than previously
225 {
nisse1e321222017-02-20 23:27:37 -0800226 bestWidth = capability.width;
227 bestHeight = capability.height;
228 bestFrameRate = capability.maxFPS;
229 bestRawType = capability.rawType;
230 bestformatIndex = tmp;
niklase@google.com470e71d2011-07-07 08:21:25 +0000231 }
232 }// else width no good
233 }
234 else // Better height
235 {
nisse1e321222017-02-20 23:27:37 -0800236 bestWidth = capability.width;
237 bestHeight = capability.height;
238 bestFrameRate = capability.maxFPS;
239 bestRawType = capability.rawType;
240 bestformatIndex = tmp;
niklase@google.com470e71d2011-07-07 08:21:25 +0000241 }
242 }// else height not good
243 }//end for
244
pbos@webrtc.org3d5cb332014-05-14 08:42:07 +0000245 LOG(LS_VERBOSE) << "Best camera format: " << bestWidth << "x" << bestHeight
246 << "@" << bestFrameRate
247 << "fps, color format: " << bestRawType;
niklase@google.com470e71d2011-07-07 08:21:25 +0000248
249 // Copy the capability
fischman@webrtc.org69fc3152013-09-25 17:01:42 +0000250 if (bestformatIndex < 0)
niklase@google.com470e71d2011-07-07 08:21:25 +0000251 return -1;
fischman@webrtc.org69fc3152013-09-25 17:01:42 +0000252 resulting = _captureCapabilities[bestformatIndex];
niklase@google.com470e71d2011-07-07 08:21:25 +0000253 return bestformatIndex;
254}
255
niklase@google.com470e71d2011-07-07 08:21:25 +0000256//Default implementation. This should be overridden by Mobile implementations.
pbos@webrtc.orgdfc5bb92013-04-10 08:23:13 +0000257int32_t DeviceInfoImpl::GetOrientation(const char* deviceUniqueIdUTF8,
guoweis@webrtc.org5a7dc392015-02-13 14:31:26 +0000258 VideoRotation& orientation) {
259 orientation = kVideoRotation_0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000260 return -1;
261}
pbos@webrtc.orgd900e8b2013-07-03 15:12:26 +0000262} // namespace videocapturemodule
263} // namespace webrtc