Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "media/video/capture/win/video_capture_device_win.h" | 5 #include "media/video/capture/win/video_capture_device_win.h" |
| 6 | 6 |
| 7 #include <ks.h> | 7 #include <ks.h> |
| 8 #include <ksmedia.h> | 8 #include <ksmedia.h> |
| 9 | 9 |
| 10 #include <algorithm> | 10 #include <algorithm> |
| 11 #include <list> | 11 #include <list> |
| 12 | 12 |
| 13 #include "base/strings/string_tokenizer.h" | |
| 13 #include "base/strings/sys_string_conversions.h" | 14 #include "base/strings/sys_string_conversions.h" |
| 14 #include "base/win/scoped_co_mem.h" | 15 #include "base/win/scoped_co_mem.h" |
| 15 #include "base/win/scoped_variant.h" | 16 #include "base/win/scoped_variant.h" |
| 16 #include "media/video/capture/win/video_capture_device_mf_win.h" | 17 #include "media/video/capture/win/video_capture_device_mf_win.h" |
| 17 | 18 |
| 18 using base::win::ScopedCoMem; | 19 using base::win::ScopedCoMem; |
| 19 using base::win::ScopedComPtr; | 20 using base::win::ScopedComPtr; |
| 20 using base::win::ScopedVariant; | 21 using base::win::ScopedVariant; |
| 21 | 22 |
| 22 namespace media { | 23 namespace media { |
| 23 | 24 |
| 24 // Finds and creates a DirectShow Video Capture filter matching the device_name. | 25 // Tries to find a |device_id| of class |device_class_id|. For this, it |
| 26 // enumerates all system devices of the given class and does a string comparison | |
| 27 // of its |property_name| tag. This comparison can be exact or substring-wise | |
| 28 // depending on |exact_name_comparison|. If such a device is found, a moniker | |
| 29 // to it is returned. | |
| 25 // static | 30 // static |
| 26 HRESULT VideoCaptureDeviceWin::GetDeviceFilter(const std::string& device_id, | 31 ScopedComPtr<IMoniker> FindDeviceAndReturnMoniker(const std::string& device_id, |
| 27 IBaseFilter** filter) { | 32 const CLSID device_class_id, |
| 28 DCHECK(filter); | 33 const wchar_t* property_name, |
| 34 bool exact_name_comparison) { | |
| 29 | 35 |
| 36 ScopedComPtr<IMoniker> moniker; | |
| 30 ScopedComPtr<ICreateDevEnum> dev_enum; | 37 ScopedComPtr<ICreateDevEnum> dev_enum; |
| 31 HRESULT hr = dev_enum.CreateInstance(CLSID_SystemDeviceEnum, NULL, | 38 HRESULT hr = dev_enum.CreateInstance(CLSID_SystemDeviceEnum, NULL, |
| 32 CLSCTX_INPROC); | 39 CLSCTX_INPROC); |
| 40 DPLOG_IF(ERROR, FAILED(hr)) << "Create SystemDeviceEnum"; | |
| 33 if (FAILED(hr)) | 41 if (FAILED(hr)) |
| 34 return hr; | 42 return moniker; |
| 35 | 43 |
| 36 ScopedComPtr<IEnumMoniker> enum_moniker; | 44 ScopedComPtr<IEnumMoniker> enum_moniker; |
| 37 hr = dev_enum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory, | 45 hr = dev_enum->CreateClassEnumerator(device_class_id, |
| 38 enum_moniker.Receive(), 0); | 46 enum_moniker.Receive(), 0); |
| 39 // CreateClassEnumerator returns S_FALSE on some Windows OS | 47 // CreateClassEnumerator returns S_FALSE on some Windows OS when no camera |
| 40 // when no camera exist. Therefore the FAILED macro can't be used. | 48 // exist. Therefore the FAILED macro can't be used. |
| 49 DPLOG_IF(ERROR, hr != S_OK) << "CreateClassEnumerator"; | |
| 41 if (hr != S_OK) | 50 if (hr != S_OK) |
| 42 return NULL; | 51 return moniker; |
| 43 | 52 |
| 44 ScopedComPtr<IMoniker> moniker; | |
| 45 ScopedComPtr<IBaseFilter> capture_filter; | |
| 46 DWORD fetched = 0; | 53 DWORD fetched = 0; |
| 47 while (enum_moniker->Next(1, moniker.Receive(), &fetched) == S_OK) { | 54 while (enum_moniker->Next(1, moniker.Receive(), &fetched) == S_OK) { |
| 48 ScopedComPtr<IPropertyBag> prop_bag; | 55 ScopedComPtr<IPropertyBag> prop_bag; |
| 49 hr = moniker->BindToStorage(0, 0, IID_IPropertyBag, prop_bag.ReceiveVoid()); | 56 hr = moniker->BindToStorage(0, 0, IID_IPropertyBag, prop_bag.ReceiveVoid()); |
| 50 if (FAILED(hr)) { | 57 if (FAILED(hr)) { |
| 51 moniker.Release(); | 58 moniker.Release(); |
| 52 continue; | 59 continue; |
| 53 } | 60 } |
| 54 | 61 |
| 55 // Find the device via DevicePath, Description or FriendlyName, whichever is | |
| 56 // available first. | |
| 57 static const wchar_t* kPropertyNames[] = { | |
| 58 L"DevicePath", L"Description", L"FriendlyName" | |
| 59 }; | |
| 60 ScopedVariant name; | 62 ScopedVariant name; |
| 61 for (size_t i = 0; | 63 prop_bag->Read(property_name, name.Receive(), 0); |
| 62 i < arraysize(kPropertyNames) && name.type() != VT_BSTR; ++i) { | 64 |
| 63 prop_bag->Read(kPropertyNames[i], name.Receive(), 0); | |
| 64 } | |
| 65 if (name.type() == VT_BSTR) { | 65 if (name.type() == VT_BSTR) { |
| 66 std::string device_path(base::SysWideToUTF8(V_BSTR(&name))); | 66 std::string device_path(base::SysWideToUTF8(V_BSTR(&name))); |
| 67 if (device_path.compare(device_id) == 0) { | 67 if ((exact_name_comparison && device_path.compare(device_id) == 0) || |
|
perkj_chrome
2014/09/05 15:04:21
device_path == device_id
mcasas
2014/09/08 09:16:30
Done.
| |
| 68 // We have found the requested device | 68 (!exact_name_comparison && (device_path.find(device_id) |
|
perkj_chrome
2014/09/05 15:04:21
nit
(!exact_name_comparison &&
(device_path.fi
mcasas
2014/09/08 09:16:30
Done.
| |
| 69 hr = moniker->BindToObject(0, 0, IID_IBaseFilter, | 69 != std::string::npos))) { |
| 70 capture_filter.ReceiveVoid()); | 70 return moniker; |
| 71 DLOG_IF(ERROR, FAILED(hr)) << "Failed to bind camera filter: " | |
| 72 << logging::SystemErrorCodeToString(hr); | |
| 73 break; | |
| 74 } | 71 } |
| 75 } | 72 } |
| 76 moniker.Release(); | 73 moniker.Release(); |
| 77 } | 74 } |
| 75 return moniker; | |
| 76 } | |
| 78 | 77 |
| 79 *filter = capture_filter.Detach(); | 78 // Finds and creates a DirectShow Video Capture filter matching the device_name. |
| 80 if (!*filter && SUCCEEDED(hr)) | 79 // |class_id| is usually CLSID_VideoInputDeviceCategory for standard DirectShow |
| 81 hr = HRESULT_FROM_WIN32(ERROR_NOT_FOUND); | 80 // device but might also be AM_KSCATEGORY_CAPTURE or AM_KSCATEGORY_CROSSBAR, to |
| 81 // enumerate WDM capture devices or WDM crossbars, respectively. | |
| 82 // static | |
| 83 HRESULT VideoCaptureDeviceWin::GetDeviceFilter(const std::string& device_id, | |
| 84 const CLSID device_class_id, | |
| 85 IBaseFilter** filter) { | |
| 86 DCHECK(filter); | |
| 87 const bool kExactNameComparison = true; | |
| 88 ScopedComPtr<IMoniker> moniker; | |
| 82 | 89 |
| 83 return hr; | 90 static const wchar_t* kPropertyNames[] = { |
| 91 L"DevicePath", L"Description", L"FriendlyName" | |
| 92 }; | |
| 93 for (size_t i = 0; i < arraysize(kPropertyNames); ++i) { | |
| 94 moniker = FindDeviceAndReturnMoniker(device_id, device_class_id, | |
| 95 kPropertyNames[i], kExactNameComparison); | |
| 96 if (!moniker) | |
| 97 continue; | |
| 98 ScopedComPtr<IBaseFilter> capture_filter; | |
| 99 HRESULT hr = moniker->BindToObject(0, 0, IID_IBaseFilter, | |
| 100 capture_filter.ReceiveVoid()); | |
| 101 *filter = capture_filter.Detach(); | |
| 102 return hr && (!*filter ? E_FAIL : S_OK); | |
|
perkj_chrome
2014/09/05 15:04:21
This looks dangerous and hard to read. I don't th
mcasas
2014/09/08 09:16:31
Reverted to previous code.
| |
| 103 } | |
| 104 DLOG(ERROR) << "Failed to find device " << device_id; | |
| 105 return E_FAIL; | |
| 84 } | 106 } |
| 85 | 107 |
| 86 // Check if a Pin matches a category. | 108 // Check if a Pin matches a category. |
| 87 // static | 109 // static |
| 88 bool VideoCaptureDeviceWin::PinMatchesCategory(IPin* pin, REFGUID category) { | 110 bool VideoCaptureDeviceWin::PinMatchesCategory(IPin* pin, REFGUID category) { |
| 89 DCHECK(pin); | 111 DCHECK(pin); |
| 90 bool found = false; | 112 bool found = false; |
| 91 ScopedComPtr<IKsPropertySet> ks_property; | 113 ScopedComPtr<IKsPropertySet> ks_property; |
| 92 HRESULT hr = ks_property.QueryFrom(pin); | 114 HRESULT hr = ks_property.QueryFrom(pin); |
| 93 if (SUCCEEDED(hr)) { | 115 if (SUCCEEDED(hr)) { |
| (...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 211 if (sink_filter_) { | 233 if (sink_filter_) { |
| 212 graph_builder_->RemoveFilter(sink_filter_); | 234 graph_builder_->RemoveFilter(sink_filter_); |
| 213 sink_filter_ = NULL; | 235 sink_filter_ = NULL; |
| 214 } | 236 } |
| 215 | 237 |
| 216 if (capture_filter_) | 238 if (capture_filter_) |
| 217 graph_builder_->RemoveFilter(capture_filter_); | 239 graph_builder_->RemoveFilter(capture_filter_); |
| 218 | 240 |
| 219 if (mjpg_filter_) | 241 if (mjpg_filter_) |
| 220 graph_builder_->RemoveFilter(mjpg_filter_); | 242 graph_builder_->RemoveFilter(mjpg_filter_); |
| 243 | |
| 244 if(crossbar_filter_) | |
| 245 graph_builder_->RemoveFilter(crossbar_filter_); | |
| 221 } | 246 } |
| 222 } | 247 } |
| 223 | 248 |
| 224 bool VideoCaptureDeviceWin::Init() { | 249 bool VideoCaptureDeviceWin::Init() { |
| 225 DCHECK(CalledOnValidThread()); | 250 DCHECK(CalledOnValidThread()); |
| 226 HRESULT hr = GetDeviceFilter(device_name_.id(), capture_filter_.Receive()); | 251 HRESULT hr; |
| 252 | |
| 253 if (device_name_.capture_api_type() == Name::DIRECT_SHOW_WDM_CROSSBAR) { | |
| 254 hr = InstantiateWDMFiltersAndPins(); | |
| 255 } else { | |
| 256 hr = GetDeviceFilter(device_name_.id(), CLSID_VideoInputDeviceCategory, | |
| 257 capture_filter_.Receive()); | |
| 258 } | |
| 227 if (!capture_filter_) { | 259 if (!capture_filter_) { |
| 228 DLOG(ERROR) << "Failed to create capture filter: " | 260 DVLOG(2) << "Failed to create capture filter."; |
| 229 << logging::SystemErrorCodeToString(hr); | |
| 230 return false; | 261 return false; |
| 231 } | 262 } |
| 232 | 263 |
| 233 output_capture_pin_ = | 264 output_capture_pin_ = |
| 234 GetPin(capture_filter_, PINDIR_OUTPUT, PIN_CATEGORY_CAPTURE); | 265 GetPin(capture_filter_, PINDIR_OUTPUT, PIN_CATEGORY_CAPTURE); |
| 235 if (!output_capture_pin_) { | 266 if (!output_capture_pin_) { |
| 236 DLOG(ERROR) << "Failed to get capture output pin"; | 267 DVLOG(2) << "Failed to get capture output pin"; |
| 237 return false; | 268 return false; |
| 238 } | 269 } |
| 239 | 270 |
| 240 // Create the sink filter used for receiving Captured frames. | 271 // Create the sink filter used for receiving Captured frames. |
| 241 sink_filter_ = new SinkFilter(this); | 272 sink_filter_ = new SinkFilter(this); |
| 242 if (sink_filter_ == NULL) { | 273 if (sink_filter_ == NULL) { |
| 243 DLOG(ERROR) << "Failed to create send filter"; | 274 DVLOG(2) << "Failed to create send filter"; |
| 244 return false; | 275 return false; |
| 245 } | 276 } |
| 246 | 277 |
| 247 input_sink_pin_ = sink_filter_->GetPin(0); | 278 input_sink_pin_ = sink_filter_->GetPin(0); |
| 248 | 279 |
| 249 hr = graph_builder_.CreateInstance(CLSID_FilterGraph, NULL, | 280 hr = graph_builder_.CreateInstance(CLSID_FilterGraph, NULL, |
| 250 CLSCTX_INPROC_SERVER); | 281 CLSCTX_INPROC_SERVER); |
| 251 if (FAILED(hr)) { | 282 if (FAILED(hr)) { |
| 252 DLOG(ERROR) << "Failed to create graph builder: " | 283 DVLOG(2) << "Failed to create graph builder."; |
| 253 << logging::SystemErrorCodeToString(hr); | |
| 254 return false; | 284 return false; |
| 255 } | 285 } |
| 256 | 286 |
| 257 hr = graph_builder_.QueryInterface(media_control_.Receive()); | 287 hr = graph_builder_.QueryInterface(media_control_.Receive()); |
| 258 if (FAILED(hr)) { | 288 if (FAILED(hr)) { |
| 259 DLOG(ERROR) << "Failed to create media control builder: " | 289 DVLOG(2) << "Failed to create media control builder."; |
| 260 << logging::SystemErrorCodeToString(hr); | |
| 261 return false; | 290 return false; |
| 262 } | 291 } |
| 263 | 292 |
| 264 hr = graph_builder_->AddFilter(capture_filter_, NULL); | 293 hr = graph_builder_->AddFilter(capture_filter_, NULL); |
| 265 if (FAILED(hr)) { | 294 if (FAILED(hr)) { |
| 266 DLOG(ERROR) << "Failed to add the capture device to the graph: " | 295 DVLOG(2) << "Failed to add the capture device to the graph."; |
| 267 << logging::SystemErrorCodeToString(hr); | 296 return false; |
| 297 } | |
| 298 | |
| 299 if (device_name_.capture_api_type() == Name::DIRECT_SHOW_WDM_CROSSBAR && | |
| 300 FAILED(AddWDMCrossbarFilterToGraphAndConnect())) { | |
| 301 DVLOG(2)<< "Failed to add/connect the WDM Crossbar filter to the graph."; | |
| 268 return false; | 302 return false; |
| 269 } | 303 } |
| 270 | 304 |
| 271 hr = graph_builder_->AddFilter(sink_filter_, NULL); | 305 hr = graph_builder_->AddFilter(sink_filter_, NULL); |
| 272 if (FAILED(hr)) { | 306 if (FAILED(hr)) { |
| 273 DLOG(ERROR) << "Failed to add the send filter to the graph: " | 307 DVLOG(2)<< "Failed to add the send filter to the graph."; |
| 274 << logging::SystemErrorCodeToString(hr); | |
| 275 return false; | 308 return false; |
| 276 } | 309 } |
| 277 | 310 |
| 278 return CreateCapabilityMap(); | 311 return CreateCapabilityMap(); |
| 279 } | 312 } |
| 280 | 313 |
| 281 void VideoCaptureDeviceWin::AllocateAndStart( | 314 void VideoCaptureDeviceWin::AllocateAndStart( |
| 282 const VideoCaptureParams& params, | 315 const VideoCaptureParams& params, |
| 283 scoped_ptr<VideoCaptureDevice::Client> client) { | 316 scoped_ptr<VideoCaptureDevice::Client> client) { |
| 284 DCHECK(CalledOnValidThread()); | 317 DCHECK(CalledOnValidThread()); |
| (...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 416 } | 449 } |
| 417 | 450 |
| 418 graph_builder_->Disconnect(output_capture_pin_); | 451 graph_builder_->Disconnect(output_capture_pin_); |
| 419 graph_builder_->Disconnect(input_sink_pin_); | 452 graph_builder_->Disconnect(input_sink_pin_); |
| 420 | 453 |
| 421 // If the _mjpg filter exist disconnect it even if it has not been used. | 454 // If the _mjpg filter exist disconnect it even if it has not been used. |
| 422 if (mjpg_filter_) { | 455 if (mjpg_filter_) { |
| 423 graph_builder_->Disconnect(input_mjpg_pin_); | 456 graph_builder_->Disconnect(input_mjpg_pin_); |
| 424 graph_builder_->Disconnect(output_mjpg_pin_); | 457 graph_builder_->Disconnect(output_mjpg_pin_); |
| 425 } | 458 } |
| 459 if (crossbar_filter_) { | |
| 460 graph_builder_->Disconnect(analog_video_input_pin_); | |
| 461 graph_builder_->Disconnect(crossbar_video_output_pin_); | |
| 462 } | |
| 426 | 463 |
| 427 if (FAILED(hr)) { | 464 if (FAILED(hr)) { |
| 428 SetErrorState("Failed to Stop the Capture device"); | 465 SetErrorState("Failed to Stop the Capture device"); |
| 429 return; | 466 return; |
| 430 } | 467 } |
| 431 client_.reset(); | 468 client_.reset(); |
| 432 state_ = kIdle; | 469 state_ = kIdle; |
| 433 } | 470 } |
| 434 | 471 |
| 435 // Implements SinkFilterObserver::SinkFilterObserver. | 472 // Implements SinkFilterObserver::SinkFilterObserver. |
| 436 void VideoCaptureDeviceWin::FrameReceived(const uint8* buffer, | 473 void VideoCaptureDeviceWin::FrameReceived(const uint8* buffer, |
| 437 int length) { | 474 int length) { |
| 438 client_->OnIncomingCapturedData( | 475 client_->OnIncomingCapturedData( |
| 439 buffer, length, capture_format_, 0, base::TimeTicks::Now()); | 476 buffer, length, capture_format_, 0, base::TimeTicks::Now()); |
| 440 } | 477 } |
| 441 | 478 |
| 442 bool VideoCaptureDeviceWin::CreateCapabilityMap() { | 479 bool VideoCaptureDeviceWin::CreateCapabilityMap() { |
| 443 DCHECK(CalledOnValidThread()); | 480 DCHECK(CalledOnValidThread()); |
| 444 ScopedComPtr<IAMStreamConfig> stream_config; | 481 ScopedComPtr<IAMStreamConfig> stream_config; |
| 445 HRESULT hr = output_capture_pin_.QueryInterface(stream_config.Receive()); | 482 HRESULT hr = output_capture_pin_.QueryInterface(stream_config.Receive()); |
| 446 if (FAILED(hr)) { | 483 if (FAILED(hr)) { |
| 447 DPLOG(ERROR) << "Failed to get IAMStreamConfig interface from " | 484 DVLOG(2) << "Failed to get IAMStreamConfig interface from " |
| 448 "capture device: " << logging::SystemErrorCodeToString(hr); | 485 "capture device"; |
| 449 return false; | 486 return false; |
| 450 } | 487 } |
| 451 | 488 |
| 452 // Get interface used for getting the frame rate. | 489 // Get interface used for getting the frame rate. |
| 453 ScopedComPtr<IAMVideoControl> video_control; | 490 ScopedComPtr<IAMVideoControl> video_control; |
| 454 hr = capture_filter_.QueryInterface(video_control.Receive()); | 491 hr = capture_filter_.QueryInterface(video_control.Receive()); |
| 455 DLOG_IF(WARNING, FAILED(hr)) << "IAMVideoControl Interface NOT SUPPORTED: " | 492 DVLOG_IF(2, FAILED(hr)) << "IAMVideoControl Interface NOT SUPPORTED"; |
| 456 << logging::SystemErrorCodeToString(hr); | |
| 457 | 493 |
| 458 int count = 0, size = 0; | 494 int count = 0, size = 0; |
| 459 hr = stream_config->GetNumberOfCapabilities(&count, &size); | 495 hr = stream_config->GetNumberOfCapabilities(&count, &size); |
| 460 if (FAILED(hr)) { | 496 if (FAILED(hr)) { |
| 461 DLOG(ERROR) << "Failed to GetNumberOfCapabilities: " | 497 DVLOG(2) << "Failed to GetNumberOfCapabilities"; |
| 462 << logging::SystemErrorCodeToString(hr); | |
| 463 return false; | 498 return false; |
| 464 } | 499 } |
| 465 | 500 |
| 466 scoped_ptr<BYTE[]> caps(new BYTE[size]); | 501 scoped_ptr<BYTE[]> caps(new BYTE[size]); |
| 467 for (int i = 0; i < count; ++i) { | 502 for (int i = 0; i < count; ++i) { |
| 468 ScopedMediaType media_type; | 503 ScopedMediaType media_type; |
| 469 hr = stream_config->GetStreamCaps(i, media_type.Receive(), caps.get()); | 504 hr = stream_config->GetStreamCaps(i, media_type.Receive(), caps.get()); |
| 470 // GetStreamCaps() may return S_FALSE, so don't use FAILED() or SUCCEED() | 505 // GetStreamCaps() may return S_FALSE, so don't use FAILED() or SUCCEED() |
| 471 // macros here since they'll trigger incorrectly. | 506 // macros here since they'll trigger incorrectly. |
| 472 if (hr != S_OK) { | 507 if (hr != S_OK) { |
| 473 DLOG(ERROR) << "Failed to GetStreamCaps: " | 508 DVLOG(2) << "Failed to GetStreamCaps"; |
| 474 << logging::SystemErrorCodeToString(hr); | |
| 475 return false; | 509 return false; |
| 476 } | 510 } |
| 477 | 511 |
| 478 if (media_type->majortype == MEDIATYPE_Video && | 512 if (media_type->majortype == MEDIATYPE_Video && |
| 479 media_type->formattype == FORMAT_VideoInfo) { | 513 media_type->formattype == FORMAT_VideoInfo) { |
| 480 VideoCaptureCapabilityWin capability(i); | 514 VideoCaptureCapabilityWin capability(i); |
| 481 capability.supported_format.pixel_format = | 515 capability.supported_format.pixel_format = |
| 482 TranslateMediaSubtypeToPixelFormat(media_type->subtype); | 516 TranslateMediaSubtypeToPixelFormat(media_type->subtype); |
| 483 if (capability.supported_format.pixel_format == PIXEL_FORMAT_UNKNOWN) | 517 if (capability.supported_format.pixel_format == PIXEL_FORMAT_UNKNOWN) |
| 484 continue; | 518 continue; |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 546 (type_support & KSPROPERTY_SUPPORT_SET)) { | 580 (type_support & KSPROPERTY_SUPPORT_SET)) { |
| 547 KSPROPERTY_VIDEOPROCAMP_S data = {}; | 581 KSPROPERTY_VIDEOPROCAMP_S data = {}; |
| 548 data.Property.Set = PROPSETID_VIDCAP_VIDEOPROCAMP; | 582 data.Property.Set = PROPSETID_VIDCAP_VIDEOPROCAMP; |
| 549 data.Property.Id = KSPROPERTY_VIDEOPROCAMP_POWERLINE_FREQUENCY; | 583 data.Property.Id = KSPROPERTY_VIDEOPROCAMP_POWERLINE_FREQUENCY; |
| 550 data.Property.Flags = KSPROPERTY_TYPE_SET; | 584 data.Property.Flags = KSPROPERTY_TYPE_SET; |
| 551 data.Value = (power_line_frequency == kPowerLine50Hz) ? 1 : 2; | 585 data.Value = (power_line_frequency == kPowerLine50Hz) ? 1 : 2; |
| 552 data.Flags = KSPROPERTY_VIDEOPROCAMP_FLAGS_MANUAL; | 586 data.Flags = KSPROPERTY_VIDEOPROCAMP_FLAGS_MANUAL; |
| 553 hr = ks_propset->Set(PROPSETID_VIDCAP_VIDEOPROCAMP, | 587 hr = ks_propset->Set(PROPSETID_VIDCAP_VIDEOPROCAMP, |
| 554 KSPROPERTY_VIDEOPROCAMP_POWERLINE_FREQUENCY, | 588 KSPROPERTY_VIDEOPROCAMP_POWERLINE_FREQUENCY, |
| 555 &data, sizeof(data), &data, sizeof(data)); | 589 &data, sizeof(data), &data, sizeof(data)); |
| 556 DLOG_IF(ERROR, FAILED(hr)) << "Anti-flicker setting failed: " | 590 DVLOG_IF(ERROR, FAILED(hr)) << "Anti-flicker setting failed."; |
| 557 << logging::SystemErrorCodeToString(hr); | |
| 558 DVLOG_IF(2, SUCCEEDED(hr)) << "Anti-flicker set correctly."; | 591 DVLOG_IF(2, SUCCEEDED(hr)) << "Anti-flicker set correctly."; |
| 559 } else { | 592 } else { |
| 560 DVLOG(2) << "Anti-flicker setting not supported."; | 593 DVLOG(2) << "Anti-flicker setting not supported."; |
| 561 } | 594 } |
| 562 } | 595 } |
| 563 | 596 |
| 597 | |
|
mcasas
2014/09/08 09:16:31
nit: remove extra line.
| |
| 598 // Instantiate a WDM Crossbar Filter and the associated WDM Capture Filter, | |
| 599 // extract the correct pins from each. The necessary pins are device specific | |
|
perkj_chrome
2014/09/05 15:04:21
This is confusing sentence to read and saying that
mcasas
2014/09/08 09:16:30
Rewritten.
| |
| 600 // but, experimentally, they usually are the first Crossbar output pin and the | |
| 601 // first Capture input pin. | |
| 602 HRESULT VideoCaptureDeviceWin::InstantiateWDMFiltersAndPins() { | |
| 603 ScopedComPtr<IMoniker> crossbar_moniker = FindDeviceAndReturnMoniker( | |
| 604 device_name_.name(), AM_KSCATEGORY_CROSSBAR, L"FriendlyName", false); | |
|
perkj_chrome
2014/09/05 15:04:21
Which filter uses the device_name.id() ? Ie, what
mcasas
2014/09/08 09:16:30
You're right, here I should search for the exact d
| |
| 605 if (!crossbar_moniker) | |
| 606 return E_FAIL; | |
| 607 | |
| 608 HRESULT hr = crossbar_moniker->BindToObject(0, 0, IID_IBaseFilter, | |
| 609 crossbar_filter_.ReceiveVoid()); | |
| 610 DPLOG_IF(ERROR, FAILED(hr)) << "Failed to bind crossbar filter"; | |
|
perkj_chrome
2014/09/05 15:04:21
nit: can we remove one of this log lines and only
mcasas
2014/09/08 09:16:30
Done.
| |
| 611 DVLOG_IF(1, SUCCEEDED(hr)) << "Crossbar filter instantiated OK."; | |
| 612 if (FAILED(hr) || !crossbar_filter_) | |
| 613 return E_FAIL; | |
| 614 | |
| 615 // Find Crossbar Video Output Pin: This is usually the first output pin. | |
| 616 crossbar_video_output_pin_ = GetPin( | |
| 617 crossbar_filter_, PINDIR_OUTPUT, GUID_NULL); | |
|
perkj_chrome
2014/09/05 15:04:21
GetPin finds the first output pin right? Isn't the
mcasas
2014/09/08 09:16:31
I'm afraid not. I printed out all Crossbar Pin typ
| |
| 618 DLOG_IF(ERROR, !crossbar_video_output_pin_) | |
| 619 << "Failed to find Crossbar Video Output pin"; | |
| 620 DVLOG_IF(1, crossbar_video_output_pin_) | |
|
perkj_chrome
2014/09/05 15:04:21
dito - please remove one log line.
mcasas
2014/09/08 09:16:31
Done.
| |
| 621 << "Crossbar Video Output pin created OK."; | |
| 622 if (!crossbar_video_output_pin_) | |
| 623 return E_FAIL; | |
| 624 | |
| 625 // Find the WDM capture filter associated to the WDM Crossbar filter. This | |
| 626 // is a fuzzy matching: they have similar names to the naked eye. Empirically, | |
| 627 // use the words of the Crossbar Filter name one by one; they are usually | |
| 628 // Vendor, Chip model etc to search in the WDM Filters list. | |
| 629 base::StringTokenizer t(device_name_.name(), " "); | |
| 630 ScopedComPtr<IMoniker> wdm_source_moniker; | |
| 631 while (!wdm_source_moniker && t.GetNext()) { | |
| 632 wdm_source_moniker = FindDeviceAndReturnMoniker( | |
| 633 t.token(), AM_KSCATEGORY_CAPTURE, L"FriendlyName", false); | |
| 634 } | |
| 635 DLOG_IF(ERROR, wdm_source_moniker) << "Couldn't find WDM device named"; | |
| 636 if (!wdm_source_moniker) | |
| 637 return E_FAIL; | |
| 638 | |
| 639 hr = wdm_source_moniker->BindToObject(0, 0, IID_IBaseFilter, | |
| 640 capture_filter_.ReceiveVoid()); | |
| 641 DPLOG_IF(ERROR, FAILED(hr)) << "Failed to bind WDM filter"; | |
| 642 DVLOG_IF(1, SUCCEEDED(hr)) << "WDM filter instantiated OK."; | |
|
perkj_chrome
2014/09/05 15:04:21
dito
mcasas
2014/09/08 09:16:30
Done.
(Removed all the positive cases' logging).
| |
| 643 if (FAILED(hr) || !capture_filter_) | |
| 644 return E_FAIL; | |
| 645 | |
| 646 // Find the WDM Capture Filter's Analog Video input Pin: usually the first | |
| 647 // input pin. | |
| 648 analog_video_input_pin_ = GetPin(capture_filter_, PINDIR_INPUT, GUID_NULL); | |
| 649 DLOG_IF(ERROR, !analog_video_input_pin_) << "Failed to find WDM Video Input"; | |
| 650 DVLOG_IF(1, analog_video_input_pin_) << "WDM Video Input pin created OK."; | |
| 651 if (!analog_video_input_pin_) | |
| 652 return E_FAIL; | |
| 653 return S_OK; | |
| 654 } | |
| 655 | |
| 656 // Add the WDM Crossbar filter to the Graph and connect the pins previously | |
| 657 // found. | |
| 658 HRESULT VideoCaptureDeviceWin::AddWDMCrossbarFilterToGraphAndConnect() { | |
| 659 HRESULT hr = graph_builder_->AddFilter(crossbar_filter_, NULL); | |
| 660 DPLOG_IF(ERROR, FAILED(hr)) << "Failed to add Crossbar filter to the graph"; | |
| 661 DVPLOG_IF(1, SUCCEEDED(hr)) << "Crossbar filter added OK to the graph"; | |
| 662 if (FAILED(hr)) | |
| 663 return E_FAIL; | |
| 664 | |
| 665 hr = graph_builder_->ConnectDirect( | |
| 666 crossbar_video_output_pin_, analog_video_input_pin_, NULL); | |
| 667 DPLOG_IF(ERROR, FAILED(hr)) << "Failed to plug WDM filters to each other"; | |
| 668 DVPLOG_IF(1, SUCCEEDED(hr)) << "WDM filters plugged OK"; | |
| 669 if (FAILED(hr)) | |
| 670 return E_FAIL; | |
| 671 return S_OK; | |
| 672 } | |
| 673 | |
| 564 void VideoCaptureDeviceWin::SetErrorState(const std::string& reason) { | 674 void VideoCaptureDeviceWin::SetErrorState(const std::string& reason) { |
| 565 DCHECK(CalledOnValidThread()); | 675 DCHECK(CalledOnValidThread()); |
| 676 DVLOG(1) << reason; | |
| 566 state_ = kError; | 677 state_ = kError; |
| 567 client_->OnError(reason); | 678 client_->OnError(reason); |
| 568 } | 679 } |
| 569 } // namespace media | 680 } // namespace media |
| OLD | NEW |