blob: 2d2bc7fb547a486e88a9b729d8ea7f88c83402cc [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();
niklase@google.com470e71d2011-07-07 08:21:25 +000034 free(_lastUsedDeviceName);
35 _apiLock.ReleaseLockExclusive();
36
37 delete &_apiLock;
38}
pbos@webrtc.orgdfc5bb92013-04-10 08:23:13 +000039int32_t DeviceInfoImpl::NumberOfCapabilities(
leozwang@webrtc.org1745e932012-03-01 16:30:40 +000040 const char* deviceUniqueIdUTF8)
niklase@google.com470e71d2011-07-07 08:21:25 +000041{
niklase@google.com470e71d2011-07-07 08:21:25 +000042
43 if (!deviceUniqueIdUTF8)
44 return -1;
45
46 _apiLock.AcquireLockShared();
47
48 if (_lastUsedDeviceNameLength == strlen((char*) deviceUniqueIdUTF8))
49 {
50 // Is it the same device that is asked for again.
andrew@webrtc.orgf3b65db2012-09-06 18:17:00 +000051#if defined(WEBRTC_MAC) || defined(WEBRTC_LINUX)
niklase@google.com470e71d2011-07-07 08:21:25 +000052 if(strncasecmp((char*)_lastUsedDeviceName,
53 (char*) deviceUniqueIdUTF8,
54 _lastUsedDeviceNameLength)==0)
55#else
56 if (_strnicmp((char*) _lastUsedDeviceName,
57 (char*) deviceUniqueIdUTF8,
58 _lastUsedDeviceNameLength) == 0)
59#endif
60 {
61 //yes
62 _apiLock.ReleaseLockShared();
pbos@webrtc.org4ca7d3f2013-08-12 19:51:57 +000063 return static_cast<int32_t>(_captureCapabilities.size());
niklase@google.com470e71d2011-07-07 08:21:25 +000064 }
65 }
66 // Need to get exclusive rights to create the new capability map.
67 _apiLock.ReleaseLockShared();
68 WriteLockScoped cs2(_apiLock);
69
pbos@webrtc.orgdfc5bb92013-04-10 08:23:13 +000070 int32_t ret = CreateCapabilityMap(deviceUniqueIdUTF8);
niklase@google.com470e71d2011-07-07 08:21:25 +000071 return ret;
72}
73
pbos@webrtc.orgdfc5bb92013-04-10 08:23:13 +000074int32_t DeviceInfoImpl::GetCapability(const char* deviceUniqueIdUTF8,
75 const uint32_t deviceCapabilityNumber,
76 VideoCaptureCapability& capability)
niklase@google.com470e71d2011-07-07 08:21:25 +000077{
niklase@google.com470e71d2011-07-07 08:21:25 +000078
79 if (!deviceUniqueIdUTF8)
80 {
81 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideoCapture, _id,
82 "deviceUniqueIdUTF8 parameter not set in call to GetCapability");
83 return -1;
84 }
85 ReadLockScoped cs(_apiLock);
86
87 if ((_lastUsedDeviceNameLength != strlen((char*) deviceUniqueIdUTF8))
andrew@webrtc.orgf3b65db2012-09-06 18:17:00 +000088#if defined(WEBRTC_MAC) || defined(WEBRTC_LINUX)
niklase@google.com470e71d2011-07-07 08:21:25 +000089 || (strncasecmp((char*)_lastUsedDeviceName,
90 (char*) deviceUniqueIdUTF8,
91 _lastUsedDeviceNameLength)!=0))
92#else
93 || (_strnicmp((char*) _lastUsedDeviceName,
94 (char*) deviceUniqueIdUTF8,
95 _lastUsedDeviceNameLength) != 0))
96#endif
97
98 {
99 _apiLock.ReleaseLockShared();
100 _apiLock.AcquireLockExclusive();
101 if (-1 == CreateCapabilityMap(deviceUniqueIdUTF8))
102 {
103 _apiLock.ReleaseLockExclusive();
104 _apiLock.AcquireLockShared();
105 return -1;
106 }
107 _apiLock.ReleaseLockExclusive();
108 _apiLock.AcquireLockShared();
109 }
110
111 // Make sure the number is valid
pbos@webrtc.org4ca7d3f2013-08-12 19:51:57 +0000112 if (deviceCapabilityNumber >= (unsigned int) _captureCapabilities.size())
niklase@google.com470e71d2011-07-07 08:21:25 +0000113 {
114 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideoCapture, _id,
115 "deviceCapabilityNumber %d is invalid in call to GetCapability",
116 deviceCapabilityNumber);
117 return -1;
118 }
119
fischman@webrtc.org69fc3152013-09-25 17:01:42 +0000120 capability = _captureCapabilities[deviceCapabilityNumber];
niklase@google.com470e71d2011-07-07 08:21:25 +0000121 return 0;
122}
123
pbos@webrtc.orgdfc5bb92013-04-10 08:23:13 +0000124int32_t DeviceInfoImpl::GetBestMatchedCapability(
leozwang@webrtc.org1745e932012-03-01 16:30:40 +0000125 const char*deviceUniqueIdUTF8,
mallinath@webrtc.org12984f02012-02-16 18:18:21 +0000126 const VideoCaptureCapability& requested,
niklase@google.com470e71d2011-07-07 08:21:25 +0000127 VideoCaptureCapability& resulting)
128{
129
niklase@google.com470e71d2011-07-07 08:21:25 +0000130
131 if (!deviceUniqueIdUTF8)
132 return -1;
133
134 ReadLockScoped cs(_apiLock);
135 if ((_lastUsedDeviceNameLength != strlen((char*) deviceUniqueIdUTF8))
andrew@webrtc.orgf3b65db2012-09-06 18:17:00 +0000136#if defined(WEBRTC_MAC) || defined(WEBRTC_LINUX)
niklase@google.com470e71d2011-07-07 08:21:25 +0000137 || (strncasecmp((char*)_lastUsedDeviceName,
138 (char*) deviceUniqueIdUTF8,
139 _lastUsedDeviceNameLength)!=0))
140#else
141 || (_strnicmp((char*) _lastUsedDeviceName,
142 (char*) deviceUniqueIdUTF8,
143 _lastUsedDeviceNameLength) != 0))
144#endif
145 {
146 _apiLock.ReleaseLockShared();
147 _apiLock.AcquireLockExclusive();
148 if (-1 == CreateCapabilityMap(deviceUniqueIdUTF8))
149 {
150 return -1;
151 }
152 _apiLock.ReleaseLockExclusive();
153 _apiLock.AcquireLockShared();
154 }
155
pbos@webrtc.orgdfc5bb92013-04-10 08:23:13 +0000156 int32_t bestformatIndex = -1;
157 int32_t bestWidth = 0;
158 int32_t bestHeight = 0;
159 int32_t bestFrameRate = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000160 RawVideoType bestRawType = kVideoUnknown;
161 webrtc::VideoCodecType bestCodecType = webrtc::kVideoCodecUnknown;
162
pbos@webrtc.org4ca7d3f2013-08-12 19:51:57 +0000163 const int32_t numberOfCapabilies =
164 static_cast<int32_t>(_captureCapabilities.size());
niklase@google.com470e71d2011-07-07 08:21:25 +0000165
pbos@webrtc.orgdfc5bb92013-04-10 08:23:13 +0000166 for (int32_t tmp = 0; tmp < numberOfCapabilies; ++tmp) // Loop through all capabilities
niklase@google.com470e71d2011-07-07 08:21:25 +0000167 {
fischman@webrtc.org69fc3152013-09-25 17:01:42 +0000168 VideoCaptureCapability& capability = _captureCapabilities[tmp];
niklase@google.com470e71d2011-07-07 08:21:25 +0000169
pbos@webrtc.orgdfc5bb92013-04-10 08:23:13 +0000170 const int32_t diffWidth = capability.width - requested.width;
171 const int32_t diffHeight = capability.height - requested.height;
172 const int32_t diffFrameRate = capability.maxFPS - requested.maxFPS;
niklase@google.com470e71d2011-07-07 08:21:25 +0000173
pbos@webrtc.orgdfc5bb92013-04-10 08:23:13 +0000174 const int32_t currentbestDiffWith = bestWidth - requested.width;
175 const int32_t currentbestDiffHeight = bestHeight - requested.height;
176 const int32_t currentbestDiffFrameRate = bestFrameRate - requested.maxFPS;
niklase@google.com470e71d2011-07-07 08:21:25 +0000177
178 if ((diffHeight >= 0 && diffHeight <= abs(currentbestDiffHeight)) // Height better or equalt that previouse.
179 || (currentbestDiffHeight < 0 && diffHeight >= currentbestDiffHeight))
180 {
181
182 if (diffHeight == currentbestDiffHeight) // Found best height. Care about the width)
183 {
184 if ((diffWidth >= 0 && diffWidth <= abs(currentbestDiffWith)) // Width better or equal
185 || (currentbestDiffWith < 0 && diffWidth >= currentbestDiffWith))
186 {
187 if (diffWidth == currentbestDiffWith && diffHeight
188 == currentbestDiffHeight) // Same size as previously
189 {
190 //Also check the best frame rate if the diff is the same as previouse
191 if (((diffFrameRate >= 0 &&
192 diffFrameRate <= currentbestDiffFrameRate) // Frame rate to high but better match than previouse and we have not selected IUV
193 ||
194 (currentbestDiffFrameRate < 0 &&
195 diffFrameRate >= currentbestDiffFrameRate)) // Current frame rate is lower than requested. This is better.
196 )
197 {
198 if ((currentbestDiffFrameRate == diffFrameRate) // Same frame rate as previous or frame rate allready good enough
199 || (currentbestDiffFrameRate >= 0))
200 {
201 if (bestRawType != requested.rawType
202 && requested.rawType != kVideoUnknown
203 && (capability.rawType == requested.rawType
204 || capability.rawType == kVideoI420
205 || capability.rawType == kVideoYUY2
206 || capability.rawType == kVideoYV12))
207 {
208 bestCodecType = capability.codecType;
209 bestRawType = capability.rawType;
210 bestformatIndex = tmp;
211 }
212 // If width height and frame rate is full filled we can use the camera for encoding if it is supported.
213 if (capability.height == requested.height
214 && capability.width == requested.width
215 && capability.maxFPS >= requested.maxFPS)
216 {
217 if (capability.codecType == requested.codecType
218 && bestCodecType != requested.codecType)
219 {
220 bestCodecType = capability.codecType;
221 bestformatIndex = tmp;
222 }
223 }
224 }
225 else // Better frame rate
226 {
227 if (requested.codecType == capability.codecType)
228 {
229
230 bestWidth = capability.width;
231 bestHeight = capability.height;
232 bestFrameRate = capability.maxFPS;
233 bestCodecType = capability.codecType;
234 bestRawType = capability.rawType;
235 bestformatIndex = tmp;
236 }
237 }
238 }
239 }
240 else // Better width than previously
241 {
242 if (requested.codecType == capability.codecType)
243 {
244 bestWidth = capability.width;
245 bestHeight = capability.height;
246 bestFrameRate = capability.maxFPS;
247 bestCodecType = capability.codecType;
248 bestRawType = capability.rawType;
249 bestformatIndex = tmp;
250 }
251 }
252 }// else width no good
253 }
254 else // Better height
255 {
256 if (requested.codecType == capability.codecType)
257 {
258 bestWidth = capability.width;
259 bestHeight = capability.height;
260 bestFrameRate = capability.maxFPS;
261 bestCodecType = capability.codecType;
262 bestRawType = capability.rawType;
263 bestformatIndex = tmp;
264 }
265 }
266 }// else height not good
267 }//end for
268
269 WEBRTC_TRACE(webrtc::kTraceInfo, webrtc::kTraceVideoCapture, _id,
270 "Best camera format: Width %d, Height %d, Frame rate %d, Color format %d",
271 bestWidth, bestHeight, bestFrameRate, bestRawType);
272
273 // Copy the capability
fischman@webrtc.org69fc3152013-09-25 17:01:42 +0000274 if (bestformatIndex < 0)
niklase@google.com470e71d2011-07-07 08:21:25 +0000275 return -1;
fischman@webrtc.org69fc3152013-09-25 17:01:42 +0000276 resulting = _captureCapabilities[bestformatIndex];
niklase@google.com470e71d2011-07-07 08:21:25 +0000277 return bestformatIndex;
278}
279
280/* Returns the expected Capture delay*/
pbos@webrtc.orgdfc5bb92013-04-10 08:23:13 +0000281int32_t DeviceInfoImpl::GetExpectedCaptureDelay(
niklase@google.com470e71d2011-07-07 08:21:25 +0000282 const DelayValues delayValues[],
pbos@webrtc.orgdfc5bb92013-04-10 08:23:13 +0000283 const uint32_t sizeOfDelayValues,
leozwang@webrtc.org1745e932012-03-01 16:30:40 +0000284 const char* productId,
pbos@webrtc.orgdfc5bb92013-04-10 08:23:13 +0000285 const uint32_t width,
286 const uint32_t height)
niklase@google.com470e71d2011-07-07 08:21:25 +0000287{
pbos@webrtc.orgdfc5bb92013-04-10 08:23:13 +0000288 int32_t bestDelay = kDefaultCaptureDelay;
niklase@google.com470e71d2011-07-07 08:21:25 +0000289
pbos@webrtc.orgdfc5bb92013-04-10 08:23:13 +0000290 for (uint32_t device = 0; device < sizeOfDelayValues; ++device)
niklase@google.com470e71d2011-07-07 08:21:25 +0000291 {
292 if (delayValues[device].productId && strncmp((char*) productId,
293 (char*) delayValues[device].productId,
294 kVideoCaptureProductIdLength) == 0)
295 {
296 // We have found the camera
297
pbos@webrtc.orgdfc5bb92013-04-10 08:23:13 +0000298 int32_t bestWidth = 0;
299 int32_t bestHeight = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000300
301 //Loop through all tested sizes and find one that seems fitting
pbos@webrtc.orgdfc5bb92013-04-10 08:23:13 +0000302 for (uint32_t delayIndex = 0; delayIndex < NoOfDelayValues; ++delayIndex)
niklase@google.com470e71d2011-07-07 08:21:25 +0000303 {
304 const DelayValue& currentValue = delayValues[device].delayValues[delayIndex];
305
pbos@webrtc.orgdfc5bb92013-04-10 08:23:13 +0000306 const int32_t diffWidth = currentValue.width - width;
307 const int32_t diffHeight = currentValue.height - height;
niklase@google.com470e71d2011-07-07 08:21:25 +0000308
pbos@webrtc.orgdfc5bb92013-04-10 08:23:13 +0000309 const int32_t currentbestDiffWith = bestWidth - width;
310 const int32_t currentbestDiffHeight = bestHeight - height;
niklase@google.com470e71d2011-07-07 08:21:25 +0000311
312 if ((diffHeight >= 0 && diffHeight <= abs(currentbestDiffHeight)) // Height better or equal than previous.
313 || (currentbestDiffHeight < 0 && diffHeight >= currentbestDiffHeight))
314 {
315
316 if (diffHeight == currentbestDiffHeight) // Found best height. Care about the width)
317 {
318 if ((diffWidth >= 0 && diffWidth <= abs(currentbestDiffWith)) // Width better or equal
319 || (currentbestDiffWith < 0 && diffWidth >= currentbestDiffWith))
320 {
321 if (diffWidth == currentbestDiffWith && diffHeight
322 == currentbestDiffHeight) // Same size as previous
323 {
324 }
325 else // Better width than previously
326 {
327 bestWidth = currentValue.width;
328 bestHeight = currentValue.height;
329 bestDelay = currentValue.delay;
330 }
331 }// else width no good
332 }
333 else // Better height
334 {
335 bestWidth = currentValue.width;
336 bestHeight = currentValue.height;
337 bestDelay = currentValue.delay;
338 }
339 }// else height not good
340 }//end for
341 break;
342 }
343 }
344 if (bestDelay > kMaxCaptureDelay)
345 {
346 WEBRTC_TRACE(webrtc::kTraceWarning, webrtc::kTraceVideoCapture, _id,
347 "Expected capture delay too high. %dms, will use %d", bestDelay,
348 kMaxCaptureDelay);
349 bestDelay = kMaxCaptureDelay;
350
351 }
352
353 return bestDelay;
354
355}
356
357//Default implementation. This should be overridden by Mobile implementations.
pbos@webrtc.orgdfc5bb92013-04-10 08:23:13 +0000358int32_t DeviceInfoImpl::GetOrientation(const char* deviceUniqueIdUTF8,
359 VideoCaptureRotation& orientation)
niklase@google.com470e71d2011-07-07 08:21:25 +0000360{
361 orientation = kCameraRotate0;
362 return -1;
363}
pbos@webrtc.orgd900e8b2013-07-03 15:12:26 +0000364} // namespace videocapturemodule
365} // namespace webrtc