| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. | 2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. |
| 3 * | 3 * |
| 4 * Use of this source code is governed by a BSD-style license | 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 | 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 | 6 * tree. An additional intellectual property rights grant can be found |
| 7 * in the file PATENTS. All contributing project authors may | 7 * in the file PATENTS. All contributing project authors may |
| 8 * be found in the AUTHORS file in the root of the source tree. | 8 * be found in the AUTHORS file in the root of the source tree. |
| 9 */ | 9 */ |
| 10 | 10 |
| (...skipping 24 matching lines...) Expand all Loading... |
| 35 {176,144,101}, | 35 {176,144,101}, |
| 36 {160,120,109}, | 36 {160,120,109}, |
| 37 {1280,720,166}, | 37 {1280,720,166}, |
| 38 {960,544,126}, | 38 {960,544,126}, |
| 39 {800,448,120}, | 39 {800,448,120}, |
| 40 {800,600,127} | 40 {800,600,127} |
| 41 }, | 41 }, |
| 42 }; | 42 }; |
| 43 | 43 |
| 44 // static | 44 // static |
| 45 DeviceInfoDS* DeviceInfoDS::Create(const int32_t id) | 45 DeviceInfoDS* DeviceInfoDS::Create() |
| 46 { | 46 { |
| 47 DeviceInfoDS* dsInfo = new DeviceInfoDS(id); | 47 DeviceInfoDS* dsInfo = new DeviceInfoDS(); |
| 48 if (!dsInfo || dsInfo->Init() != 0) | 48 if (!dsInfo || dsInfo->Init() != 0) |
| 49 { | 49 { |
| 50 delete dsInfo; | 50 delete dsInfo; |
| 51 dsInfo = NULL; | 51 dsInfo = NULL; |
| 52 } | 52 } |
| 53 return dsInfo; | 53 return dsInfo; |
| 54 } | 54 } |
| 55 | 55 |
| 56 DeviceInfoDS::DeviceInfoDS(const int32_t id) | 56 DeviceInfoDS::DeviceInfoDS() |
| 57 : DeviceInfoImpl(id), _dsDevEnum(NULL), _dsMonikerDevEnum(NULL), | 57 : _dsDevEnum(NULL), _dsMonikerDevEnum(NULL), |
| 58 _CoUninitializeIsRequired(true) | 58 _CoUninitializeIsRequired(true) |
| 59 { | 59 { |
| 60 // 1) Initialize the COM library (make Windows load the DLLs). | 60 // 1) Initialize the COM library (make Windows load the DLLs). |
| 61 // | 61 // |
| 62 // CoInitializeEx must be called at least once, and is usually called only o
nce, | 62 // CoInitializeEx must be called at least once, and is usually called only o
nce, |
| 63 // for each thread that uses the COM library. Multiple calls to CoInitialize
Ex | 63 // for each thread that uses the COM library. Multiple calls to CoInitialize
Ex |
| 64 // by the same thread are allowed as long as they pass the same concurrency
flag, | 64 // by the same thread are allowed as long as they pass the same concurrency
flag, |
| 65 // but subsequent valid calls return S_FALSE. | 65 // but subsequent valid calls return S_FALSE. |
| 66 // To close the COM library gracefully on a thread, each successful call to | 66 // To close the COM library gracefully on a thread, each successful call to |
| 67 // CoInitializeEx, including any call that returns S_FALSE, must be balanced | 67 // CoInitializeEx, including any call that returns S_FALSE, must be balanced |
| (...skipping 13 matching lines...) Expand all Loading... |
| 81 { | 81 { |
| 82 // Avoid calling CoUninitialize() since CoInitializeEx() failed. | 82 // Avoid calling CoUninitialize() since CoInitializeEx() failed. |
| 83 _CoUninitializeIsRequired = FALSE; | 83 _CoUninitializeIsRequired = FALSE; |
| 84 | 84 |
| 85 if (hr == RPC_E_CHANGED_MODE) | 85 if (hr == RPC_E_CHANGED_MODE) |
| 86 { | 86 { |
| 87 // Calling thread has already initialized COM to be used in a single
-threaded | 87 // Calling thread has already initialized COM to be used in a single
-threaded |
| 88 // apartment (STA). We are then prevented from using STA. | 88 // apartment (STA). We are then prevented from using STA. |
| 89 // Details: hr = 0x80010106 <=> "Cannot change thread mode after it
is set". | 89 // Details: hr = 0x80010106 <=> "Cannot change thread mode after it
is set". |
| 90 // | 90 // |
| 91 WEBRTC_TRACE(webrtc::kTraceWarning, webrtc::kTraceVideoCapture, _id, | 91 WEBRTC_TRACE(webrtc::kTraceWarning, webrtc::kTraceVideoCapture, 0, |
| 92 "VideoCaptureWindowsDSInfo::VideoCaptureWindowsDSInfo " | 92 "VideoCaptureWindowsDSInfo::VideoCaptureWindowsDSInfo " |
| 93 "CoInitializeEx(NULL, COINIT_APARTMENTTHREADED) => " | 93 "CoInitializeEx(NULL, COINIT_APARTMENTTHREADED) => " |
| 94 "RPC_E_CHANGED_MODE, error 0x%x", | 94 "RPC_E_CHANGED_MODE, error 0x%x", |
| 95 hr); | 95 hr); |
| 96 } | 96 } |
| 97 } | 97 } |
| 98 } | 98 } |
| 99 | 99 |
| 100 DeviceInfoDS::~DeviceInfoDS() | 100 DeviceInfoDS::~DeviceInfoDS() |
| 101 { | 101 { |
| 102 RELEASE_AND_CLEAR(_dsMonikerDevEnum); | 102 RELEASE_AND_CLEAR(_dsMonikerDevEnum); |
| 103 RELEASE_AND_CLEAR(_dsDevEnum); | 103 RELEASE_AND_CLEAR(_dsDevEnum); |
| 104 if (_CoUninitializeIsRequired) | 104 if (_CoUninitializeIsRequired) |
| 105 { | 105 { |
| 106 CoUninitialize(); | 106 CoUninitialize(); |
| 107 } | 107 } |
| 108 } | 108 } |
| 109 | 109 |
| 110 int32_t DeviceInfoDS::Init() | 110 int32_t DeviceInfoDS::Init() |
| 111 { | 111 { |
| 112 HRESULT hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC, | 112 HRESULT hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC, |
| 113 IID_ICreateDevEnum, (void **) &_dsDevEnum); | 113 IID_ICreateDevEnum, (void **) &_dsDevEnum); |
| 114 if (hr != NOERROR) | 114 if (hr != NOERROR) |
| 115 { | 115 { |
| 116 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideoCapture, _id, | 116 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideoCapture, 0, |
| 117 "Failed to create CLSID_SystemDeviceEnum, error 0x%x", hr); | 117 "Failed to create CLSID_SystemDeviceEnum, error 0x%x", hr); |
| 118 return -1; | 118 return -1; |
| 119 } | 119 } |
| 120 return 0; | 120 return 0; |
| 121 } | 121 } |
| 122 uint32_t DeviceInfoDS::NumberOfDevices() | 122 uint32_t DeviceInfoDS::NumberOfDevices() |
| 123 { | 123 { |
| 124 ReadLockScoped cs(_apiLock); | 124 ReadLockScoped cs(_apiLock); |
| 125 return GetDeviceInfo(0, 0, 0, 0, 0, 0, 0); | 125 return GetDeviceInfo(0, 0, 0, 0, 0, 0, 0); |
| 126 } | 126 } |
| (...skipping 28 matching lines...) Expand all Loading... |
| 155 | 155 |
| 156 { | 156 { |
| 157 | 157 |
| 158 // enumerate all video capture devices | 158 // enumerate all video capture devices |
| 159 RELEASE_AND_CLEAR(_dsMonikerDevEnum); | 159 RELEASE_AND_CLEAR(_dsMonikerDevEnum); |
| 160 HRESULT hr = | 160 HRESULT hr = |
| 161 _dsDevEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory, | 161 _dsDevEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory, |
| 162 &_dsMonikerDevEnum, 0); | 162 &_dsMonikerDevEnum, 0); |
| 163 if (hr != NOERROR) | 163 if (hr != NOERROR) |
| 164 { | 164 { |
| 165 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideoCapture, _id, | 165 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideoCapture, 0, |
| 166 "Failed to enumerate CLSID_SystemDeviceEnum, error 0x%x." | 166 "Failed to enumerate CLSID_SystemDeviceEnum, error 0x%x." |
| 167 " No webcam exist?", hr); | 167 " No webcam exist?", hr); |
| 168 return 0; | 168 return 0; |
| 169 } | 169 } |
| 170 | 170 |
| 171 _dsMonikerDevEnum->Reset(); | 171 _dsMonikerDevEnum->Reset(); |
| 172 ULONG cFetched; | 172 ULONG cFetched; |
| 173 IMoniker *pM; | 173 IMoniker *pM; |
| 174 int index = 0; | 174 int index = 0; |
| 175 while (S_OK == _dsMonikerDevEnum->Next(1, &pM, &cFetched)) | 175 while (S_OK == _dsMonikerDevEnum->Next(1, &pM, &cFetched)) |
| (...skipping 24 matching lines...) Expand all Loading... |
| 200 if (deviceNameLength > 0) | 200 if (deviceNameLength > 0) |
| 201 { | 201 { |
| 202 convResult = WideCharToMultiByte(CP_UTF8, 0, | 202 convResult = WideCharToMultiByte(CP_UTF8, 0, |
| 203 varName.bstrVal, -1
, | 203 varName.bstrVal, -1
, |
| 204 (char*) deviceNameU
TF8, | 204 (char*) deviceNameU
TF8, |
| 205 deviceNameLength, N
ULL, | 205 deviceNameLength, N
ULL, |
| 206 NULL); | 206 NULL); |
| 207 if (convResult == 0) | 207 if (convResult == 0) |
| 208 { | 208 { |
| 209 WEBRTC_TRACE(webrtc::kTraceError, | 209 WEBRTC_TRACE(webrtc::kTraceError, |
| 210 webrtc::kTraceVideoCapture, _id, | 210 webrtc::kTraceVideoCapture, 0, |
| 211 "Failed to convert device name to U
TF8. %d", | 211 "Failed to convert device name to U
TF8. %d", |
| 212 GetLastError()); | 212 GetLastError()); |
| 213 return -1; | 213 return -1; |
| 214 } | 214 } |
| 215 } | 215 } |
| 216 if (deviceUniqueIdUTF8Length > 0) | 216 if (deviceUniqueIdUTF8Length > 0) |
| 217 { | 217 { |
| 218 hr = pBag->Read(L"DevicePath", &varName, 0); | 218 hr = pBag->Read(L"DevicePath", &varName, 0); |
| 219 if (FAILED(hr)) | 219 if (FAILED(hr)) |
| 220 { | 220 { |
| 221 strncpy_s((char *) deviceUniqueIdUTF8, | 221 strncpy_s((char *) deviceUniqueIdUTF8, |
| 222 deviceUniqueIdUTF8Length, | 222 deviceUniqueIdUTF8Length, |
| 223 (char *) deviceNameUTF8, convResult); | 223 (char *) deviceNameUTF8, convResult); |
| 224 WEBRTC_TRACE(webrtc::kTraceError, | 224 WEBRTC_TRACE(webrtc::kTraceError, |
| 225 webrtc::kTraceVideoCapture, _id, | 225 webrtc::kTraceVideoCapture, 0, |
| 226 "Failed to get deviceUniqueIdUTF8 u
sing deviceNameUTF8"); | 226 "Failed to get deviceUniqueIdUTF8 u
sing deviceNameUTF8"); |
| 227 } | 227 } |
| 228 else | 228 else |
| 229 { | 229 { |
| 230 convResult = WideCharToMultiByte( | 230 convResult = WideCharToMultiByte( |
| 231 CP_UTF8, | 231 CP_UTF8, |
| 232 0, | 232 0, |
| 233 varName.bstrVal, | 233 varName.bstrVal, |
| 234 -1, | 234 -1, |
| 235 (char*) deviceUniqueId
UTF8, | 235 (char*) deviceUniqueId
UTF8, |
| 236 deviceUniqueIdUTF8Leng
th, | 236 deviceUniqueIdUTF8Leng
th, |
| 237 NULL, NULL); | 237 NULL, NULL); |
| 238 if (convResult == 0) | 238 if (convResult == 0) |
| 239 { | 239 { |
| 240 WEBRTC_TRACE(webrtc::kTraceError, | 240 WEBRTC_TRACE(webrtc::kTraceError, |
| 241 webrtc::kTraceVideoCapture, _id
, | 241 webrtc::kTraceVideoCapture, 0, |
| 242 "Failed to convert device name
to UTF8. %d", | 242 "Failed to convert device name
to UTF8. %d", |
| 243 GetLastError()); | 243 GetLastError()); |
| 244 return -1; | 244 return -1; |
| 245 } | 245 } |
| 246 if (productUniqueIdUTF8 | 246 if (productUniqueIdUTF8 |
| 247 && productUniqueIdUTF8Length > 0) | 247 && productUniqueIdUTF8Length > 0) |
| 248 { | 248 { |
| 249 GetProductId(deviceUniqueIdUTF8, | 249 GetProductId(deviceUniqueIdUTF8, |
| 250 productUniqueIdUTF8, | 250 productUniqueIdUTF8, |
| 251 productUniqueIdUTF8Length); | 251 productUniqueIdUTF8Length); |
| 252 } | 252 } |
| 253 } | 253 } |
| 254 } | 254 } |
| 255 | 255 |
| 256 } | 256 } |
| 257 ++index; // increase the number of valid devices | 257 ++index; // increase the number of valid devices |
| 258 } | 258 } |
| 259 } | 259 } |
| 260 VariantClear(&varName); | 260 VariantClear(&varName); |
| 261 pBag->Release(); | 261 pBag->Release(); |
| 262 pM->Release(); | 262 pM->Release(); |
| 263 } | 263 } |
| 264 | 264 |
| 265 } | 265 } |
| 266 if (deviceNameLength) | 266 if (deviceNameLength) |
| 267 { | 267 { |
| 268 WEBRTC_TRACE(webrtc::kTraceDebug, webrtc::kTraceVideoCapture, _id, "%s %
s", | 268 WEBRTC_TRACE(webrtc::kTraceDebug, |
| 269 webrtc::kTraceVideoCapture, 0, "%s %s", |
| 269 __FUNCTION__, deviceNameUTF8); | 270 __FUNCTION__, deviceNameUTF8); |
| 270 } | 271 } |
| 271 return index; | 272 return index; |
| 272 } | 273 } |
| 273 | 274 |
| 274 IBaseFilter * DeviceInfoDS::GetDeviceFilter( | 275 IBaseFilter * DeviceInfoDS::GetDeviceFilter( |
| 275 const char* deviceUniqueIdUTF8, | 276 const char* deviceUniqueIdUTF8, |
| 276 char* productUniqueIdUTF8, | 277 char* productUniqueIdUTF8, |
| 277 uint32_t productUniqueIdUTF8Length) | 278 uint32_t productUniqueIdUTF8Length) |
| 278 { | 279 { |
| 279 | 280 |
| 280 const int32_t deviceUniqueIdUTF8Length = | 281 const int32_t deviceUniqueIdUTF8Length = |
| 281 (int32_t) strlen((char*) deviceUniqueIdUTF8); // UTF8 is also NULL termi
nated | 282 (int32_t) strlen((char*) deviceUniqueIdUTF8); // UTF8 is also NULL termi
nated |
| 282 if (deviceUniqueIdUTF8Length > kVideoCaptureUniqueNameLength) | 283 if (deviceUniqueIdUTF8Length > kVideoCaptureUniqueNameLength) |
| 283 { | 284 { |
| 284 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideoCapture, _id, | 285 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideoCapture, 0, |
| 285 "Device name too long"); | 286 "Device name too long"); |
| 286 return NULL; | 287 return NULL; |
| 287 } | 288 } |
| 288 | 289 |
| 289 // enumerate all video capture devices | 290 // enumerate all video capture devices |
| 290 RELEASE_AND_CLEAR(_dsMonikerDevEnum); | 291 RELEASE_AND_CLEAR(_dsMonikerDevEnum); |
| 291 HRESULT hr = _dsDevEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategor
y, | 292 HRESULT hr = _dsDevEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategor
y, |
| 292 &_dsMonikerDevEnum, 0); | 293 &_dsMonikerDevEnum, 0); |
| 293 if (hr != NOERROR) | 294 if (hr != NOERROR) |
| 294 { | 295 { |
| 295 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideoCapture, _id, | 296 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideoCapture, 0, |
| 296 "Failed to enumerate CLSID_SystemDeviceEnum, error 0x%x." | 297 "Failed to enumerate CLSID_SystemDeviceEnum, error 0x%x." |
| 297 " No webcam exist?", hr); | 298 " No webcam exist?", hr); |
| 298 return 0; | 299 return 0; |
| 299 } | 300 } |
| 300 _dsMonikerDevEnum->Reset(); | 301 _dsMonikerDevEnum->Reset(); |
| 301 ULONG cFetched; | 302 ULONG cFetched; |
| 302 IMoniker *pM; | 303 IMoniker *pM; |
| 303 | 304 |
| 304 IBaseFilter *captureFilter = NULL; | 305 IBaseFilter *captureFilter = NULL; |
| 305 bool deviceFound = false; | 306 bool deviceFound = false; |
| (...skipping 28 matching lines...) Expand all Loading... |
| 334 if (strncmp(tempDevicePathUTF8, | 335 if (strncmp(tempDevicePathUTF8, |
| 335 (const char*) deviceUniqueIdUTF8, | 336 (const char*) deviceUniqueIdUTF8, |
| 336 deviceUniqueIdUTF8Length) == 0) | 337 deviceUniqueIdUTF8Length) == 0) |
| 337 { | 338 { |
| 338 // We have found the requested device | 339 // We have found the requested device |
| 339 deviceFound = true; | 340 deviceFound = true; |
| 340 hr = pM->BindToObject(0, 0, IID_IBaseFilter, | 341 hr = pM->BindToObject(0, 0, IID_IBaseFilter, |
| 341 (void**) &captureFilter); | 342 (void**) &captureFilter); |
| 342 if FAILED(hr) | 343 if FAILED(hr) |
| 343 { | 344 { |
| 344 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVide
oCapture, | 345 WEBRTC_TRACE( |
| 345 _id, "Failed to bind to the selected ca
pture device %d",hr); | 346 webrtc::kTraceError, webrtc::kTraceVideoCapture, |
| 347 0, "Failed to bind to the selected capture " |
| 348 "device %d",hr); |
| 346 } | 349 } |
| 347 | 350 |
| 348 if (productUniqueIdUTF8 | 351 if (productUniqueIdUTF8 |
| 349 && productUniqueIdUTF8Length > 0) // Get the device
name | 352 && productUniqueIdUTF8Length > 0) // Get the device
name |
| 350 { | 353 { |
| 351 | 354 |
| 352 GetProductId(deviceUniqueIdUTF8, | 355 GetProductId(deviceUniqueIdUTF8, |
| 353 productUniqueIdUTF8, | 356 productUniqueIdUTF8, |
| 354 productUniqueIdUTF8Length); | 357 productUniqueIdUTF8Length); |
| 355 } | 358 } |
| (...skipping 27 matching lines...) Expand all Loading... |
| 383 const char* deviceUniqueIdUTF8) | 386 const char* deviceUniqueIdUTF8) |
| 384 | 387 |
| 385 { | 388 { |
| 386 // Reset old capability list | 389 // Reset old capability list |
| 387 _captureCapabilities.clear(); | 390 _captureCapabilities.clear(); |
| 388 | 391 |
| 389 const int32_t deviceUniqueIdUTF8Length = | 392 const int32_t deviceUniqueIdUTF8Length = |
| 390 (int32_t) strlen((char*) deviceUniqueIdUTF8); | 393 (int32_t) strlen((char*) deviceUniqueIdUTF8); |
| 391 if (deviceUniqueIdUTF8Length > kVideoCaptureUniqueNameLength) | 394 if (deviceUniqueIdUTF8Length > kVideoCaptureUniqueNameLength) |
| 392 { | 395 { |
| 393 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideoCapture, _id, | 396 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideoCapture, 0, |
| 394 "Device name too long"); | 397 "Device name too long"); |
| 395 return -1; | 398 return -1; |
| 396 } | 399 } |
| 397 WEBRTC_TRACE(webrtc::kTraceInfo, webrtc::kTraceVideoCapture, _id, | 400 WEBRTC_TRACE(webrtc::kTraceInfo, webrtc::kTraceVideoCapture, 0, |
| 398 "CreateCapabilityMap called for device %s", deviceUniqueIdUTF8)
; | 401 "CreateCapabilityMap called for device %s", deviceUniqueIdUTF8)
; |
| 399 | 402 |
| 400 | 403 |
| 401 char productId[kVideoCaptureProductIdLength]; | 404 char productId[kVideoCaptureProductIdLength]; |
| 402 IBaseFilter* captureDevice = DeviceInfoDS::GetDeviceFilter( | 405 IBaseFilter* captureDevice = DeviceInfoDS::GetDeviceFilter( |
| 403 deviceUniqueIdUTF8, | 406 deviceUniqueIdUTF8, |
| 404 productId, | 407 productId, |
| 405 kVideoCaptureProductIdLength); | 408 kVideoCaptureProductIdLength); |
| 406 if (!captureDevice) | 409 if (!captureDevice) |
| 407 return -1; | 410 return -1; |
| 408 IPin* outputCapturePin = GetOutputPin(captureDevice, GUID_NULL); | 411 IPin* outputCapturePin = GetOutputPin(captureDevice, GUID_NULL); |
| 409 if (!outputCapturePin) | 412 if (!outputCapturePin) |
| 410 { | 413 { |
| 411 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideoCapture, _id, | 414 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideoCapture, 0, |
| 412 "Failed to get capture device output pin"); | 415 "Failed to get capture device output pin"); |
| 413 RELEASE_AND_CLEAR(captureDevice); | 416 RELEASE_AND_CLEAR(captureDevice); |
| 414 return -1; | 417 return -1; |
| 415 } | 418 } |
| 416 IAMExtDevice* extDevice = NULL; | 419 IAMExtDevice* extDevice = NULL; |
| 417 HRESULT hr = captureDevice->QueryInterface(IID_IAMExtDevice, | 420 HRESULT hr = captureDevice->QueryInterface(IID_IAMExtDevice, |
| 418 (void **) &extDevice); | 421 (void **) &extDevice); |
| 419 if (SUCCEEDED(hr) && extDevice) | 422 if (SUCCEEDED(hr) && extDevice) |
| 420 { | 423 { |
| 421 WEBRTC_TRACE(webrtc::kTraceInfo, webrtc::kTraceVideoCapture, _id, | 424 WEBRTC_TRACE(webrtc::kTraceInfo, webrtc::kTraceVideoCapture, 0, |
| 422 "This is an external device"); | 425 "This is an external device"); |
| 423 extDevice->Release(); | 426 extDevice->Release(); |
| 424 } | 427 } |
| 425 | 428 |
| 426 IAMStreamConfig* streamConfig = NULL; | 429 IAMStreamConfig* streamConfig = NULL; |
| 427 hr = outputCapturePin->QueryInterface(IID_IAMStreamConfig, | 430 hr = outputCapturePin->QueryInterface(IID_IAMStreamConfig, |
| 428 (void**) &streamConfig); | 431 (void**) &streamConfig); |
| 429 if (FAILED(hr)) | 432 if (FAILED(hr)) |
| 430 { | 433 { |
| 431 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideoCapture, _id, | 434 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideoCapture, 0, |
| 432 "Failed to get IID_IAMStreamConfig interface from capture d
evice"); | 435 "Failed to get IID_IAMStreamConfig interface from capture d
evice"); |
| 433 return -1; | 436 return -1; |
| 434 } | 437 } |
| 435 | 438 |
| 436 // this gets the FPS | 439 // this gets the FPS |
| 437 IAMVideoControl* videoControlConfig = NULL; | 440 IAMVideoControl* videoControlConfig = NULL; |
| 438 HRESULT hrVC = captureDevice->QueryInterface(IID_IAMVideoControl, | 441 HRESULT hrVC = captureDevice->QueryInterface(IID_IAMVideoControl, |
| 439 (void**) &videoControlConfig); | 442 (void**) &videoControlConfig); |
| 440 if (FAILED(hrVC)) | 443 if (FAILED(hrVC)) |
| 441 { | 444 { |
| 442 WEBRTC_TRACE(webrtc::kTraceWarning, webrtc::kTraceVideoCapture, _id, | 445 WEBRTC_TRACE(webrtc::kTraceWarning, webrtc::kTraceVideoCapture, 0, |
| 443 "IID_IAMVideoControl Interface NOT SUPPORTED"); | 446 "IID_IAMVideoControl Interface NOT SUPPORTED"); |
| 444 } | 447 } |
| 445 | 448 |
| 446 AM_MEDIA_TYPE *pmt = NULL; | 449 AM_MEDIA_TYPE *pmt = NULL; |
| 447 VIDEO_STREAM_CONFIG_CAPS caps; | 450 VIDEO_STREAM_CONFIG_CAPS caps; |
| 448 int count, size; | 451 int count, size; |
| 449 | 452 |
| 450 hr = streamConfig->GetNumberOfCapabilities(&count, &size); | 453 hr = streamConfig->GetNumberOfCapabilities(&count, &size); |
| 451 if (FAILED(hr)) | 454 if (FAILED(hr)) |
| 452 { | 455 { |
| 453 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideoCapture, _id, | 456 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideoCapture, 0, |
| 454 "Failed to GetNumberOfCapabilities"); | 457 "Failed to GetNumberOfCapabilities"); |
| 455 RELEASE_AND_CLEAR(videoControlConfig); | 458 RELEASE_AND_CLEAR(videoControlConfig); |
| 456 RELEASE_AND_CLEAR(streamConfig); | 459 RELEASE_AND_CLEAR(streamConfig); |
| 457 RELEASE_AND_CLEAR(outputCapturePin); | 460 RELEASE_AND_CLEAR(outputCapturePin); |
| 458 RELEASE_AND_CLEAR(captureDevice); | 461 RELEASE_AND_CLEAR(captureDevice); |
| 459 return -1; | 462 return -1; |
| 460 } | 463 } |
| 461 | 464 |
| 462 // Check if the device support formattype == FORMAT_VideoInfo2 and FORMAT_Vi
deoInfo. | 465 // Check if the device support formattype == FORMAT_VideoInfo2 and FORMAT_Vi
deoInfo. |
| 463 // Prefer FORMAT_VideoInfo since some cameras (ZureCam) has been seen having
problem with MJPEG and FORMAT_VideoInfo2 | 466 // Prefer FORMAT_VideoInfo since some cameras (ZureCam) has been seen having
problem with MJPEG and FORMAT_VideoInfo2 |
| 464 // Interlace flag is only supported in FORMAT_VideoInfo2 | 467 // Interlace flag is only supported in FORMAT_VideoInfo2 |
| 465 bool supportFORMAT_VideoInfo2 = false; | 468 bool supportFORMAT_VideoInfo2 = false; |
| 466 bool supportFORMAT_VideoInfo = false; | 469 bool supportFORMAT_VideoInfo = false; |
| 467 bool foundInterlacedFormat = false; | 470 bool foundInterlacedFormat = false; |
| 468 GUID preferedVideoFormat = FORMAT_VideoInfo; | 471 GUID preferedVideoFormat = FORMAT_VideoInfo; |
| 469 for (int32_t tmp = 0; tmp < count; ++tmp) | 472 for (int32_t tmp = 0; tmp < count; ++tmp) |
| 470 { | 473 { |
| 471 hr = streamConfig->GetStreamCaps(tmp, &pmt, | 474 hr = streamConfig->GetStreamCaps(tmp, &pmt, |
| 472 reinterpret_cast<BYTE*> (&caps)); | 475 reinterpret_cast<BYTE*> (&caps)); |
| 473 if (!FAILED(hr)) | 476 if (!FAILED(hr)) |
| 474 { | 477 { |
| 475 if (pmt->majortype == MEDIATYPE_Video | 478 if (pmt->majortype == MEDIATYPE_Video |
| 476 && pmt->formattype == FORMAT_VideoInfo2) | 479 && pmt->formattype == FORMAT_VideoInfo2) |
| 477 { | 480 { |
| 478 WEBRTC_TRACE(webrtc::kTraceDebug, webrtc::kTraceVideoCapture, _i
d, | 481 WEBRTC_TRACE(webrtc::kTraceDebug, webrtc::kTraceVideoCapture, 0, |
| 479 " Device support FORMAT_VideoInfo2"); | 482 " Device support FORMAT_VideoInfo2"); |
| 480 supportFORMAT_VideoInfo2 = true; | 483 supportFORMAT_VideoInfo2 = true; |
| 481 VIDEOINFOHEADER2* h = | 484 VIDEOINFOHEADER2* h = |
| 482 reinterpret_cast<VIDEOINFOHEADER2*> (pmt->pbFormat); | 485 reinterpret_cast<VIDEOINFOHEADER2*> (pmt->pbFormat); |
| 483 assert(h); | 486 assert(h); |
| 484 foundInterlacedFormat |= h->dwInterlaceFlags | 487 foundInterlacedFormat |= h->dwInterlaceFlags |
| 485 & (AMINTERLACE_IsInterlaced | 488 & (AMINTERLACE_IsInterlaced |
| 486 | AMINTERLACE_DisplayModeBobOnly); | 489 | AMINTERLACE_DisplayModeBobOnly); |
| 487 } | 490 } |
| 488 if (pmt->majortype == MEDIATYPE_Video | 491 if (pmt->majortype == MEDIATYPE_Video |
| 489 && pmt->formattype == FORMAT_VideoInfo) | 492 && pmt->formattype == FORMAT_VideoInfo) |
| 490 { | 493 { |
| 491 WEBRTC_TRACE(webrtc::kTraceDebug, webrtc::kTraceVideoCapture, _i
d, | 494 WEBRTC_TRACE(webrtc::kTraceDebug, webrtc::kTraceVideoCapture, 0, |
| 492 " Device support FORMAT_VideoInfo2"); | 495 " Device support FORMAT_VideoInfo2"); |
| 493 supportFORMAT_VideoInfo = true; | 496 supportFORMAT_VideoInfo = true; |
| 494 } | 497 } |
| 495 } | 498 } |
| 496 } | 499 } |
| 497 if (supportFORMAT_VideoInfo2) | 500 if (supportFORMAT_VideoInfo2) |
| 498 { | 501 { |
| 499 if (supportFORMAT_VideoInfo && !foundInterlacedFormat) | 502 if (supportFORMAT_VideoInfo && !foundInterlacedFormat) |
| 500 { | 503 { |
| 501 preferedVideoFormat = FORMAT_VideoInfo; | 504 preferedVideoFormat = FORMAT_VideoInfo; |
| 502 } | 505 } |
| 503 else | 506 else |
| 504 { | 507 { |
| 505 preferedVideoFormat = FORMAT_VideoInfo2; | 508 preferedVideoFormat = FORMAT_VideoInfo2; |
| 506 } | 509 } |
| 507 } | 510 } |
| 508 | 511 |
| 509 for (int32_t tmp = 0; tmp < count; ++tmp) | 512 for (int32_t tmp = 0; tmp < count; ++tmp) |
| 510 { | 513 { |
| 511 hr = streamConfig->GetStreamCaps(tmp, &pmt, | 514 hr = streamConfig->GetStreamCaps(tmp, &pmt, |
| 512 reinterpret_cast<BYTE*> (&caps)); | 515 reinterpret_cast<BYTE*> (&caps)); |
| 513 if (FAILED(hr)) | 516 if (FAILED(hr)) |
| 514 { | 517 { |
| 515 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideoCapture, _id, | 518 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideoCapture, 0, |
| 516 "Failed to GetStreamCaps"); | 519 "Failed to GetStreamCaps"); |
| 517 RELEASE_AND_CLEAR(videoControlConfig); | 520 RELEASE_AND_CLEAR(videoControlConfig); |
| 518 RELEASE_AND_CLEAR(streamConfig); | 521 RELEASE_AND_CLEAR(streamConfig); |
| 519 RELEASE_AND_CLEAR(outputCapturePin); | 522 RELEASE_AND_CLEAR(outputCapturePin); |
| 520 RELEASE_AND_CLEAR(captureDevice); | 523 RELEASE_AND_CLEAR(captureDevice); |
| 521 return -1; | 524 return -1; |
| 522 } | 525 } |
| 523 | 526 |
| 524 if (pmt->majortype == MEDIATYPE_Video | 527 if (pmt->majortype == MEDIATYPE_Video |
| 525 && pmt->formattype == preferedVideoFormat) | 528 && pmt->formattype == preferedVideoFormat) |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 577 0 != (maxFPS = GetMaxOfFrameArray(frameDurationList, | 580 0 != (maxFPS = GetMaxOfFrameArray(frameDurationList, |
| 578 listSize))) | 581 listSize))) |
| 579 { | 582 { |
| 580 capability.maxFPS = static_cast<int> (10000000 | 583 capability.maxFPS = static_cast<int> (10000000 |
| 581 / maxFPS); | 584 / maxFPS); |
| 582 capability.supportFrameRateControl = true; | 585 capability.supportFrameRateControl = true; |
| 583 } | 586 } |
| 584 else // use existing method | 587 else // use existing method |
| 585 { | 588 { |
| 586 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideoCapture
, | 589 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideoCapture
, |
| 587 _id, | 590 0, |
| 588 "GetMaxAvailableFrameRate NOT SUPPORTED"); | 591 "GetMaxAvailableFrameRate NOT SUPPORTED"); |
| 589 if (avgTimePerFrame > 0) | 592 if (avgTimePerFrame > 0) |
| 590 capability.maxFPS = static_cast<int> (10000000 | 593 capability.maxFPS = static_cast<int> (10000000 |
| 591 / avgTimePerFrame
); | 594 / avgTimePerFrame
); |
| 592 else | 595 else |
| 593 capability.maxFPS = 0; | 596 capability.maxFPS = 0; |
| 594 } | 597 } |
| 595 } | 598 } |
| 596 else // use existing method in case IAMVideoControl is not supported | 599 else // use existing method in case IAMVideoControl is not supported |
| 597 { | 600 { |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 632 || pmt->subtype == MEDIASUBTYPE_dvhd) // If this is an exter
nal DV camera | 635 || pmt->subtype == MEDIASUBTYPE_dvhd) // If this is an exter
nal DV camera |
| 633 { | 636 { |
| 634 capability.rawType = kVideoYUY2;// MS DV filter seems to create
this type | 637 capability.rawType = kVideoYUY2;// MS DV filter seems to create
this type |
| 635 } | 638 } |
| 636 else if (pmt->subtype == MEDIASUBTYPE_UYVY) // Seen used by Declink
capture cards | 639 else if (pmt->subtype == MEDIASUBTYPE_UYVY) // Seen used by Declink
capture cards |
| 637 { | 640 { |
| 638 capability.rawType = kVideoUYVY; | 641 capability.rawType = kVideoUYVY; |
| 639 } | 642 } |
| 640 else if (pmt->subtype == MEDIASUBTYPE_HDYC) // Seen used by Declink
capture cards. Uses BT. 709 color. Not entiry correct to use UYVY. http://en.wik
ipedia.org/wiki/YCbCr | 643 else if (pmt->subtype == MEDIASUBTYPE_HDYC) // Seen used by Declink
capture cards. Uses BT. 709 color. Not entiry correct to use UYVY. http://en.wik
ipedia.org/wiki/YCbCr |
| 641 { | 644 { |
| 642 WEBRTC_TRACE(webrtc::kTraceWarning, webrtc::kTraceVideoCapture,
_id, | 645 WEBRTC_TRACE(webrtc::kTraceWarning, |
| 646 webrtc::kTraceVideoCapture, 0, |
| 643 "Device support HDYC."); | 647 "Device support HDYC."); |
| 644 capability.rawType = kVideoUYVY; | 648 capability.rawType = kVideoUYVY; |
| 645 } | 649 } |
| 646 else | 650 else |
| 647 { | 651 { |
| 648 WCHAR strGuid[39]; | 652 WCHAR strGuid[39]; |
| 649 StringFromGUID2(pmt->subtype, strGuid, 39); | 653 StringFromGUID2(pmt->subtype, strGuid, 39); |
| 650 WEBRTC_TRACE( webrtc::kTraceWarning, | 654 WEBRTC_TRACE( webrtc::kTraceWarning, |
| 651 webrtc::kTraceVideoCapture, _id, | 655 webrtc::kTraceVideoCapture, 0, |
| 652 "Device support unknown media type %ls, width %d, h
eight %d", | 656 "Device support unknown media type %ls, width %d, h
eight %d", |
| 653 strGuid); | 657 strGuid); |
| 654 continue; | 658 continue; |
| 655 } | 659 } |
| 656 | 660 |
| 657 // Get the expected capture delay from the static list | 661 // Get the expected capture delay from the static list |
| 658 capability.expectedCaptureDelay | 662 capability.expectedCaptureDelay |
| 659 = GetExpectedCaptureDelay(WindowsCaptureDelays, | 663 = GetExpectedCaptureDelay(WindowsCaptureDelays, |
| 660 NoWindowsCaptureDelays, | 664 NoWindowsCaptureDelays, |
| 661 productId, | 665 productId, |
| 662 capability.width, | 666 capability.width, |
| 663 capability.height); | 667 capability.height); |
| 664 _captureCapabilities.push_back(capability); | 668 _captureCapabilities.push_back(capability); |
| 665 _captureCapabilitiesWindows.push_back(capability); | 669 _captureCapabilitiesWindows.push_back(capability); |
| 666 WEBRTC_TRACE( webrtc::kTraceInfo, webrtc::kTraceVideoCapture, _id, | 670 WEBRTC_TRACE( webrtc::kTraceInfo, webrtc::kTraceVideoCapture, 0, |
| 667 "Camera capability, width:%d height:%d type:%d fps:%d", | 671 "Camera capability, width:%d height:%d type:%d fps:%d", |
| 668 capability.width, capability.height, | 672 capability.width, capability.height, |
| 669 capability.rawType, capability.maxFPS); | 673 capability.rawType, capability.maxFPS); |
| 670 } | 674 } |
| 671 DeleteMediaType(pmt); | 675 DeleteMediaType(pmt); |
| 672 pmt = NULL; | 676 pmt = NULL; |
| 673 } | 677 } |
| 674 RELEASE_AND_CLEAR(streamConfig); | 678 RELEASE_AND_CLEAR(streamConfig); |
| 675 RELEASE_AND_CLEAR(videoControlConfig); | 679 RELEASE_AND_CLEAR(videoControlConfig); |
| 676 RELEASE_AND_CLEAR(outputCapturePin); | 680 RELEASE_AND_CLEAR(outputCapturePin); |
| 677 RELEASE_AND_CLEAR(captureDevice); // Release the capture device | 681 RELEASE_AND_CLEAR(captureDevice); // Release the capture device |
| 678 | 682 |
| 679 // Store the new used device name | 683 // Store the new used device name |
| 680 _lastUsedDeviceNameLength = deviceUniqueIdUTF8Length; | 684 _lastUsedDeviceNameLength = deviceUniqueIdUTF8Length; |
| 681 _lastUsedDeviceName = (char*) realloc(_lastUsedDeviceName, | 685 _lastUsedDeviceName = (char*) realloc(_lastUsedDeviceName, |
| 682 _lastUsedDeviceNameLength | 686 _lastUsedDeviceNameLength |
| 683 + 1); | 687 + 1); |
| 684 memcpy(_lastUsedDeviceName, deviceUniqueIdUTF8, _lastUsedDeviceNameLength+ 1
); | 688 memcpy(_lastUsedDeviceName, deviceUniqueIdUTF8, _lastUsedDeviceNameLength+ 1
); |
| 685 WEBRTC_TRACE(webrtc::kTraceInfo, webrtc::kTraceVideoCapture, _id, | 689 WEBRTC_TRACE(webrtc::kTraceInfo, webrtc::kTraceVideoCapture, 0, |
| 686 "CreateCapabilityMap %d", _captureCapabilities.size()); | 690 "CreateCapabilityMap %d", _captureCapabilities.size()); |
| 687 | 691 |
| 688 return static_cast<int32_t>(_captureCapabilities.size()); | 692 return static_cast<int32_t>(_captureCapabilities.size()); |
| 689 } | 693 } |
| 690 | 694 |
| 691 /* Constructs a product ID from the Windows DevicePath. on a USB device the devi
cePath contains product id and vendor id. | 695 /* Constructs a product ID from the Windows DevicePath. on a USB device the devi
cePath contains product id and vendor id. |
| 692 This seems to work for firewire as well | 696 This seems to work for firewire as well |
| 693 /* Example of device path | 697 /* Example of device path |
| 694 "\\?\usb#vid_0408&pid_2010&mi_00#7&258e7aaf&0&0000#{65e8773d-8f56-11d0-a3b9-00a
0c9223196}\global" | 698 "\\?\usb#vid_0408&pid_2010&mi_00#7&258e7aaf&0&0000#{65e8773d-8f56-11d0-a3b9-00a
0c9223196}\global" |
| 695 "\\?\avc#sony&dv-vcr&camcorder&dv#65b2d50301460008#{65e8773d-8f56-11d0-a3b9-00a
0c9223196}\global" | 699 "\\?\avc#sony&dv-vcr&camcorder&dv#65b2d50301460008#{65e8773d-8f56-11d0-a3b9-00a
0c9223196}\global" |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 788 // Release memory. | 792 // Release memory. |
| 789 if (uuid.pElems) | 793 if (uuid.pElems) |
| 790 { | 794 { |
| 791 CoTaskMemFree(uuid.pElems); | 795 CoTaskMemFree(uuid.pElems); |
| 792 } | 796 } |
| 793 filter->Release(); | 797 filter->Release(); |
| 794 return 0; | 798 return 0; |
| 795 } | 799 } |
| 796 } // namespace videocapturemodule | 800 } // namespace videocapturemodule |
| 797 } // namespace webrtc | 801 } // namespace webrtc |
| OLD | NEW |