blob: 1bdaa14f3c8e40498bbb6c9f7d5181f894a5cc18 [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
niklase@google.com470e71d2011-07-07 08:21:25 +000011#include <stdlib.h>
12
pbos@webrtc.orga9b74ad2013-07-12 10:03:52 +000013#include "webrtc/modules/video_capture/device_info_impl.h"
14#include "webrtc/modules/video_capture/video_capture_config.h"
15#include "webrtc/system_wrappers/interface/trace.h"
16
niklase@google.com470e71d2011-07-07 08:21:25 +000017#ifndef abs
18#define abs(a) (a>=0?a:-a)
19#endif
20
21namespace webrtc
22{
23namespace videocapturemodule
24{
pbos@webrtc.orgdfc5bb92013-04-10 08:23:13 +000025DeviceInfoImpl::DeviceInfoImpl(const int32_t id)
niklase@google.com470e71d2011-07-07 08:21:25 +000026 : _id(id), _apiLock(*RWLockWrapper::CreateRWLock()), _lastUsedDeviceName(NULL),
27 _lastUsedDeviceNameLength(0)
28{
29}
30
31DeviceInfoImpl::~DeviceInfoImpl(void)
32{
33 _apiLock.AcquireLockExclusive();
pbos@webrtc.org4ca7d3f2013-08-12 19:51:57 +000034
35 for (VideoCaptureCapabilityMap::iterator it = _captureCapabilities.begin();
36 it != _captureCapabilities.end();
37 ++it) {
38 delete it->second;
niklase@google.com470e71d2011-07-07 08:21:25 +000039 }
pbos@webrtc.org4ca7d3f2013-08-12 19:51:57 +000040
niklase@google.com470e71d2011-07-07 08:21:25 +000041 free(_lastUsedDeviceName);
42 _apiLock.ReleaseLockExclusive();
43
44 delete &_apiLock;
45}
pbos@webrtc.orgdfc5bb92013-04-10 08:23:13 +000046int32_t DeviceInfoImpl::NumberOfCapabilities(
leozwang@webrtc.org1745e932012-03-01 16:30:40 +000047 const char* deviceUniqueIdUTF8)
niklase@google.com470e71d2011-07-07 08:21:25 +000048{
niklase@google.com470e71d2011-07-07 08:21:25 +000049
50 if (!deviceUniqueIdUTF8)
51 return -1;
52
53 _apiLock.AcquireLockShared();
54
55 if (_lastUsedDeviceNameLength == strlen((char*) deviceUniqueIdUTF8))
56 {
57 // Is it the same device that is asked for again.
andrew@webrtc.orgf3b65db2012-09-06 18:17:00 +000058#if defined(WEBRTC_MAC) || defined(WEBRTC_LINUX)
niklase@google.com470e71d2011-07-07 08:21:25 +000059 if(strncasecmp((char*)_lastUsedDeviceName,
60 (char*) deviceUniqueIdUTF8,
61 _lastUsedDeviceNameLength)==0)
62#else
63 if (_strnicmp((char*) _lastUsedDeviceName,
64 (char*) deviceUniqueIdUTF8,
65 _lastUsedDeviceNameLength) == 0)
66#endif
67 {
68 //yes
69 _apiLock.ReleaseLockShared();
pbos@webrtc.org4ca7d3f2013-08-12 19:51:57 +000070 return static_cast<int32_t>(_captureCapabilities.size());
niklase@google.com470e71d2011-07-07 08:21:25 +000071 }
72 }
73 // Need to get exclusive rights to create the new capability map.
74 _apiLock.ReleaseLockShared();
75 WriteLockScoped cs2(_apiLock);
76
pbos@webrtc.orgdfc5bb92013-04-10 08:23:13 +000077 int32_t ret = CreateCapabilityMap(deviceUniqueIdUTF8);
niklase@google.com470e71d2011-07-07 08:21:25 +000078 return ret;
79}
80
pbos@webrtc.orgdfc5bb92013-04-10 08:23:13 +000081int32_t DeviceInfoImpl::GetCapability(const char* deviceUniqueIdUTF8,
82 const uint32_t deviceCapabilityNumber,
83 VideoCaptureCapability& capability)
niklase@google.com470e71d2011-07-07 08:21:25 +000084{
niklase@google.com470e71d2011-07-07 08:21:25 +000085
86 if (!deviceUniqueIdUTF8)
87 {
88 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideoCapture, _id,
89 "deviceUniqueIdUTF8 parameter not set in call to GetCapability");
90 return -1;
91 }
92 ReadLockScoped cs(_apiLock);
93
94 if ((_lastUsedDeviceNameLength != strlen((char*) deviceUniqueIdUTF8))
andrew@webrtc.orgf3b65db2012-09-06 18:17:00 +000095#if defined(WEBRTC_MAC) || defined(WEBRTC_LINUX)
niklase@google.com470e71d2011-07-07 08:21:25 +000096 || (strncasecmp((char*)_lastUsedDeviceName,
97 (char*) deviceUniqueIdUTF8,
98 _lastUsedDeviceNameLength)!=0))
99#else
100 || (_strnicmp((char*) _lastUsedDeviceName,
101 (char*) deviceUniqueIdUTF8,
102 _lastUsedDeviceNameLength) != 0))
103#endif
104
105 {
106 _apiLock.ReleaseLockShared();
107 _apiLock.AcquireLockExclusive();
108 if (-1 == CreateCapabilityMap(deviceUniqueIdUTF8))
109 {
110 _apiLock.ReleaseLockExclusive();
111 _apiLock.AcquireLockShared();
112 return -1;
113 }
114 _apiLock.ReleaseLockExclusive();
115 _apiLock.AcquireLockShared();
116 }
117
118 // Make sure the number is valid
pbos@webrtc.org4ca7d3f2013-08-12 19:51:57 +0000119 if (deviceCapabilityNumber >= (unsigned int) _captureCapabilities.size())
niklase@google.com470e71d2011-07-07 08:21:25 +0000120 {
121 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideoCapture, _id,
122 "deviceCapabilityNumber %d is invalid in call to GetCapability",
123 deviceCapabilityNumber);
124 return -1;
125 }
126
pbos@webrtc.org4ca7d3f2013-08-12 19:51:57 +0000127 VideoCaptureCapabilityMap::iterator item =
128 _captureCapabilities.find(deviceCapabilityNumber);
129
130 if (item == _captureCapabilities.end())
niklase@google.com470e71d2011-07-07 08:21:25 +0000131 {
132 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideoCapture, _id,
133 "Failed to find capability number %d of %d possible",
pbos@webrtc.org4ca7d3f2013-08-12 19:51:57 +0000134 deviceCapabilityNumber, _captureCapabilities.size());
niklase@google.com470e71d2011-07-07 08:21:25 +0000135 return -1;
136 }
137
pbos@webrtc.org4ca7d3f2013-08-12 19:51:57 +0000138 if (item->second == NULL)
niklase@google.com470e71d2011-07-07 08:21:25 +0000139 {
140 return -1;
141 }
142
pbos@webrtc.org4ca7d3f2013-08-12 19:51:57 +0000143 capability = *item->second;
niklase@google.com470e71d2011-07-07 08:21:25 +0000144 return 0;
145}
146
pbos@webrtc.orgdfc5bb92013-04-10 08:23:13 +0000147int32_t DeviceInfoImpl::GetBestMatchedCapability(
leozwang@webrtc.org1745e932012-03-01 16:30:40 +0000148 const char*deviceUniqueIdUTF8,
mallinath@webrtc.org12984f02012-02-16 18:18:21 +0000149 const VideoCaptureCapability& requested,
niklase@google.com470e71d2011-07-07 08:21:25 +0000150 VideoCaptureCapability& resulting)
151{
152
niklase@google.com470e71d2011-07-07 08:21:25 +0000153
154 if (!deviceUniqueIdUTF8)
155 return -1;
156
157 ReadLockScoped cs(_apiLock);
158 if ((_lastUsedDeviceNameLength != strlen((char*) deviceUniqueIdUTF8))
andrew@webrtc.orgf3b65db2012-09-06 18:17:00 +0000159#if defined(WEBRTC_MAC) || defined(WEBRTC_LINUX)
niklase@google.com470e71d2011-07-07 08:21:25 +0000160 || (strncasecmp((char*)_lastUsedDeviceName,
161 (char*) deviceUniqueIdUTF8,
162 _lastUsedDeviceNameLength)!=0))
163#else
164 || (_strnicmp((char*) _lastUsedDeviceName,
165 (char*) deviceUniqueIdUTF8,
166 _lastUsedDeviceNameLength) != 0))
167#endif
168 {
169 _apiLock.ReleaseLockShared();
170 _apiLock.AcquireLockExclusive();
171 if (-1 == CreateCapabilityMap(deviceUniqueIdUTF8))
172 {
173 return -1;
174 }
175 _apiLock.ReleaseLockExclusive();
176 _apiLock.AcquireLockShared();
177 }
178
pbos@webrtc.orgdfc5bb92013-04-10 08:23:13 +0000179 int32_t bestformatIndex = -1;
180 int32_t bestWidth = 0;
181 int32_t bestHeight = 0;
182 int32_t bestFrameRate = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000183 RawVideoType bestRawType = kVideoUnknown;
184 webrtc::VideoCodecType bestCodecType = webrtc::kVideoCodecUnknown;
185
pbos@webrtc.org4ca7d3f2013-08-12 19:51:57 +0000186 const int32_t numberOfCapabilies =
187 static_cast<int32_t>(_captureCapabilities.size());
niklase@google.com470e71d2011-07-07 08:21:25 +0000188
pbos@webrtc.orgdfc5bb92013-04-10 08:23:13 +0000189 for (int32_t tmp = 0; tmp < numberOfCapabilies; ++tmp) // Loop through all capabilities
niklase@google.com470e71d2011-07-07 08:21:25 +0000190 {
pbos@webrtc.org4ca7d3f2013-08-12 19:51:57 +0000191 VideoCaptureCapabilityMap::iterator item = _captureCapabilities.find(tmp);
192 if (item == _captureCapabilities.end())
niklase@google.com470e71d2011-07-07 08:21:25 +0000193 return -1;
194
pbos@webrtc.org4ca7d3f2013-08-12 19:51:57 +0000195 VideoCaptureCapability& capability = *item->second;
niklase@google.com470e71d2011-07-07 08:21:25 +0000196
pbos@webrtc.orgdfc5bb92013-04-10 08:23:13 +0000197 const int32_t diffWidth = capability.width - requested.width;
198 const int32_t diffHeight = capability.height - requested.height;
199 const int32_t diffFrameRate = capability.maxFPS - requested.maxFPS;
niklase@google.com470e71d2011-07-07 08:21:25 +0000200
pbos@webrtc.orgdfc5bb92013-04-10 08:23:13 +0000201 const int32_t currentbestDiffWith = bestWidth - requested.width;
202 const int32_t currentbestDiffHeight = bestHeight - requested.height;
203 const int32_t currentbestDiffFrameRate = bestFrameRate - requested.maxFPS;
niklase@google.com470e71d2011-07-07 08:21:25 +0000204
205 if ((diffHeight >= 0 && diffHeight <= abs(currentbestDiffHeight)) // Height better or equalt that previouse.
206 || (currentbestDiffHeight < 0 && diffHeight >= currentbestDiffHeight))
207 {
208
209 if (diffHeight == currentbestDiffHeight) // Found best height. Care about the width)
210 {
211 if ((diffWidth >= 0 && diffWidth <= abs(currentbestDiffWith)) // Width better or equal
212 || (currentbestDiffWith < 0 && diffWidth >= currentbestDiffWith))
213 {
214 if (diffWidth == currentbestDiffWith && diffHeight
215 == currentbestDiffHeight) // Same size as previously
216 {
217 //Also check the best frame rate if the diff is the same as previouse
218 if (((diffFrameRate >= 0 &&
219 diffFrameRate <= currentbestDiffFrameRate) // Frame rate to high but better match than previouse and we have not selected IUV
220 ||
221 (currentbestDiffFrameRate < 0 &&
222 diffFrameRate >= currentbestDiffFrameRate)) // Current frame rate is lower than requested. This is better.
223 )
224 {
225 if ((currentbestDiffFrameRate == diffFrameRate) // Same frame rate as previous or frame rate allready good enough
226 || (currentbestDiffFrameRate >= 0))
227 {
228 if (bestRawType != requested.rawType
229 && requested.rawType != kVideoUnknown
230 && (capability.rawType == requested.rawType
231 || capability.rawType == kVideoI420
232 || capability.rawType == kVideoYUY2
233 || capability.rawType == kVideoYV12))
234 {
235 bestCodecType = capability.codecType;
236 bestRawType = capability.rawType;
237 bestformatIndex = tmp;
238 }
239 // If width height and frame rate is full filled we can use the camera for encoding if it is supported.
240 if (capability.height == requested.height
241 && capability.width == requested.width
242 && capability.maxFPS >= requested.maxFPS)
243 {
244 if (capability.codecType == requested.codecType
245 && bestCodecType != requested.codecType)
246 {
247 bestCodecType = capability.codecType;
248 bestformatIndex = tmp;
249 }
250 }
251 }
252 else // Better frame rate
253 {
254 if (requested.codecType == capability.codecType)
255 {
256
257 bestWidth = capability.width;
258 bestHeight = capability.height;
259 bestFrameRate = capability.maxFPS;
260 bestCodecType = capability.codecType;
261 bestRawType = capability.rawType;
262 bestformatIndex = tmp;
263 }
264 }
265 }
266 }
267 else // Better width than previously
268 {
269 if (requested.codecType == capability.codecType)
270 {
271 bestWidth = capability.width;
272 bestHeight = capability.height;
273 bestFrameRate = capability.maxFPS;
274 bestCodecType = capability.codecType;
275 bestRawType = capability.rawType;
276 bestformatIndex = tmp;
277 }
278 }
279 }// else width no good
280 }
281 else // Better height
282 {
283 if (requested.codecType == capability.codecType)
284 {
285 bestWidth = capability.width;
286 bestHeight = capability.height;
287 bestFrameRate = capability.maxFPS;
288 bestCodecType = capability.codecType;
289 bestRawType = capability.rawType;
290 bestformatIndex = tmp;
291 }
292 }
293 }// else height not good
294 }//end for
295
296 WEBRTC_TRACE(webrtc::kTraceInfo, webrtc::kTraceVideoCapture, _id,
297 "Best camera format: Width %d, Height %d, Frame rate %d, Color format %d",
298 bestWidth, bestHeight, bestFrameRate, bestRawType);
299
300 // Copy the capability
pbos@webrtc.org4ca7d3f2013-08-12 19:51:57 +0000301 VideoCaptureCapabilityMap::iterator item =
302 _captureCapabilities.find(bestformatIndex);
303 if (item == _captureCapabilities.end())
niklase@google.com470e71d2011-07-07 08:21:25 +0000304 return -1;
pbos@webrtc.org4ca7d3f2013-08-12 19:51:57 +0000305 if (item->second == NULL)
niklase@google.com470e71d2011-07-07 08:21:25 +0000306 return -1;
307
pbos@webrtc.org4ca7d3f2013-08-12 19:51:57 +0000308 resulting = *item->second;
niklase@google.com470e71d2011-07-07 08:21:25 +0000309
310 return bestformatIndex;
311}
312
313/* Returns the expected Capture delay*/
pbos@webrtc.orgdfc5bb92013-04-10 08:23:13 +0000314int32_t DeviceInfoImpl::GetExpectedCaptureDelay(
niklase@google.com470e71d2011-07-07 08:21:25 +0000315 const DelayValues delayValues[],
pbos@webrtc.orgdfc5bb92013-04-10 08:23:13 +0000316 const uint32_t sizeOfDelayValues,
leozwang@webrtc.org1745e932012-03-01 16:30:40 +0000317 const char* productId,
pbos@webrtc.orgdfc5bb92013-04-10 08:23:13 +0000318 const uint32_t width,
319 const uint32_t height)
niklase@google.com470e71d2011-07-07 08:21:25 +0000320{
pbos@webrtc.orgdfc5bb92013-04-10 08:23:13 +0000321 int32_t bestDelay = kDefaultCaptureDelay;
niklase@google.com470e71d2011-07-07 08:21:25 +0000322
pbos@webrtc.orgdfc5bb92013-04-10 08:23:13 +0000323 for (uint32_t device = 0; device < sizeOfDelayValues; ++device)
niklase@google.com470e71d2011-07-07 08:21:25 +0000324 {
325 if (delayValues[device].productId && strncmp((char*) productId,
326 (char*) delayValues[device].productId,
327 kVideoCaptureProductIdLength) == 0)
328 {
329 // We have found the camera
330
pbos@webrtc.orgdfc5bb92013-04-10 08:23:13 +0000331 int32_t bestWidth = 0;
332 int32_t bestHeight = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000333
334 //Loop through all tested sizes and find one that seems fitting
pbos@webrtc.orgdfc5bb92013-04-10 08:23:13 +0000335 for (uint32_t delayIndex = 0; delayIndex < NoOfDelayValues; ++delayIndex)
niklase@google.com470e71d2011-07-07 08:21:25 +0000336 {
337 const DelayValue& currentValue = delayValues[device].delayValues[delayIndex];
338
pbos@webrtc.orgdfc5bb92013-04-10 08:23:13 +0000339 const int32_t diffWidth = currentValue.width - width;
340 const int32_t diffHeight = currentValue.height - height;
niklase@google.com470e71d2011-07-07 08:21:25 +0000341
pbos@webrtc.orgdfc5bb92013-04-10 08:23:13 +0000342 const int32_t currentbestDiffWith = bestWidth - width;
343 const int32_t currentbestDiffHeight = bestHeight - height;
niklase@google.com470e71d2011-07-07 08:21:25 +0000344
345 if ((diffHeight >= 0 && diffHeight <= abs(currentbestDiffHeight)) // Height better or equal than previous.
346 || (currentbestDiffHeight < 0 && diffHeight >= currentbestDiffHeight))
347 {
348
349 if (diffHeight == currentbestDiffHeight) // Found best height. Care about the width)
350 {
351 if ((diffWidth >= 0 && diffWidth <= abs(currentbestDiffWith)) // Width better or equal
352 || (currentbestDiffWith < 0 && diffWidth >= currentbestDiffWith))
353 {
354 if (diffWidth == currentbestDiffWith && diffHeight
355 == currentbestDiffHeight) // Same size as previous
356 {
357 }
358 else // Better width than previously
359 {
360 bestWidth = currentValue.width;
361 bestHeight = currentValue.height;
362 bestDelay = currentValue.delay;
363 }
364 }// else width no good
365 }
366 else // Better height
367 {
368 bestWidth = currentValue.width;
369 bestHeight = currentValue.height;
370 bestDelay = currentValue.delay;
371 }
372 }// else height not good
373 }//end for
374 break;
375 }
376 }
377 if (bestDelay > kMaxCaptureDelay)
378 {
379 WEBRTC_TRACE(webrtc::kTraceWarning, webrtc::kTraceVideoCapture, _id,
380 "Expected capture delay too high. %dms, will use %d", bestDelay,
381 kMaxCaptureDelay);
382 bestDelay = kMaxCaptureDelay;
383
384 }
385
386 return bestDelay;
387
388}
389
390//Default implementation. This should be overridden by Mobile implementations.
pbos@webrtc.orgdfc5bb92013-04-10 08:23:13 +0000391int32_t DeviceInfoImpl::GetOrientation(const char* deviceUniqueIdUTF8,
392 VideoCaptureRotation& orientation)
niklase@google.com470e71d2011-07-07 08:21:25 +0000393{
394 orientation = kCameraRotate0;
395 return -1;
396}
pbos@webrtc.orgd900e8b2013-07-03 15:12:26 +0000397} // namespace videocapturemodule
398} // namespace webrtc