1b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org/* 2b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. 3b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * 4b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * Use of this source code is governed by a BSD-style license 5b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * that can be found in the LICENSE file in the root of the source 6b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * tree. An additional intellectual property rights grant can be found 7b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * in the file PATENTS. All contributing project authors may 8b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * be found in the AUTHORS file in the root of the source tree. 9b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org */ 10b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1187c29b570711208c5f74bf9eaffbea549de866c7pbos@webrtc.org#include "webrtc/modules/video_capture/windows/video_capture_ds.h" 12b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1387c29b570711208c5f74bf9eaffbea549de866c7pbos@webrtc.org#include "webrtc/modules/video_capture/video_capture_config.h" 1487c29b570711208c5f74bf9eaffbea549de866c7pbos@webrtc.org#include "webrtc/modules/video_capture/windows/help_functions_ds.h" 1587c29b570711208c5f74bf9eaffbea549de866c7pbos@webrtc.org#include "webrtc/modules/video_capture/windows/sink_filter_ds.h" 1687c29b570711208c5f74bf9eaffbea549de866c7pbos@webrtc.org#include "webrtc/system_wrappers/interface/critical_section_wrapper.h" 1787c29b570711208c5f74bf9eaffbea549de866c7pbos@webrtc.org#include "webrtc/system_wrappers/interface/trace.h" 18b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 19b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#include <Dvdmedia.h> // VIDEOINFOHEADER2 20b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 21b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgnamespace webrtc 22b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 23b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgnamespace videocapturemodule 24b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 25f7e44d647cd0f893a185dfbe043cb313cab29fd0pbos@webrtc.orgVideoCaptureDS::VideoCaptureDS(const int32_t id) 26b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org : VideoCaptureImpl(id), _dsInfo(id), _captureFilter(NULL), 27b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _graphBuilder(NULL), _mediaControl(NULL), _sinkFilter(NULL), 28b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _inputSendPin(NULL), _outputCapturePin(NULL), _dvFilter(NULL), 29b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _inputDvPin(NULL), _outputDvPin(NULL) 30b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 31b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 32b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 33b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgVideoCaptureDS::~VideoCaptureDS() 34b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 35b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (_mediaControl) 36b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 37b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _mediaControl->Stop(); 38b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 39b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (_graphBuilder) 40b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 41b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (_sinkFilter) 42b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _graphBuilder->RemoveFilter(_sinkFilter); 43b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (_captureFilter) 44b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _graphBuilder->RemoveFilter(_captureFilter); 45b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (_dvFilter) 46b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _graphBuilder->RemoveFilter(_dvFilter); 47b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 48b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org RELEASE_AND_CLEAR(_captureFilter); // release the capture device 49b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org RELEASE_AND_CLEAR(_sinkFilter); 50b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org RELEASE_AND_CLEAR(_dvFilter); 51b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 52b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org RELEASE_AND_CLEAR(_mediaControl); 53b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org RELEASE_AND_CLEAR(_inputSendPin); 54b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org RELEASE_AND_CLEAR(_outputCapturePin); 55b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 56b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org RELEASE_AND_CLEAR(_inputDvPin); 57b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org RELEASE_AND_CLEAR(_outputDvPin); 58b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 59b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org RELEASE_AND_CLEAR(_graphBuilder); 60b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 61b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 62f7e44d647cd0f893a185dfbe043cb313cab29fd0pbos@webrtc.orgint32_t VideoCaptureDS::Init(const int32_t id, const char* deviceUniqueIdUTF8) 63b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 64f7e44d647cd0f893a185dfbe043cb313cab29fd0pbos@webrtc.org const int32_t nameLength = 65f7e44d647cd0f893a185dfbe043cb313cab29fd0pbos@webrtc.org (int32_t) strlen((char*) deviceUniqueIdUTF8); 66b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (nameLength > kVideoCaptureUniqueNameLength) 67b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 68b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 69b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Store the device name 70b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _deviceUniqueId = new (std::nothrow) char[nameLength + 1]; 71b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org memcpy(_deviceUniqueId, deviceUniqueIdUTF8, nameLength + 1); 72b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 73b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (_dsInfo.Init() != 0) 74b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 75b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 76b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _captureFilter = _dsInfo.GetDeviceFilter(deviceUniqueIdUTF8); 77b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (!_captureFilter) 78b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 79b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideoCapture, _id, 80b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org "Failed to create capture filter."); 81b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 82b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 83b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 84b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Get the interface for DirectShow's GraphBuilder 85b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org HRESULT hr = CoCreateInstance(CLSID_FilterGraph, NULL, 86b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org CLSCTX_INPROC_SERVER, IID_IGraphBuilder, 87b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org (void **) &_graphBuilder); 88b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (FAILED(hr)) 89b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 90b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideoCapture, _id, 91b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org "Failed to create graph builder."); 92b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 93b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 94b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 95b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org hr = _graphBuilder->QueryInterface(IID_IMediaControl, 96b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org (void **) &_mediaControl); 97b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (FAILED(hr)) 98b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 99b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideoCapture, _id, 100b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org "Failed to create media control builder."); 101b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 102b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 103b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org hr = _graphBuilder->AddFilter(_captureFilter, CAPTURE_FILTER_NAME); 104b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (FAILED(hr)) 105b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 106b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideoCapture, _id, 107b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org "Failed to add the capture device to the graph."); 108b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 109b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 110b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 111b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _outputCapturePin = GetOutputPin(_captureFilter, PIN_CATEGORY_CAPTURE); 112b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 113b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Create the sink filte used for receiving Captured frames. 114b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _sinkFilter = new CaptureSinkFilter(SINK_FILTER_NAME, NULL, &hr, 115b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *this, _id); 116b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (hr != S_OK) 117b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 118b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideoCapture, _id, 119b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org "Failed to create send filter"); 120b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 121b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 122b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _sinkFilter->AddRef(); 123b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 124b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org hr = _graphBuilder->AddFilter(_sinkFilter, SINK_FILTER_NAME); 125b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (FAILED(hr)) 126b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 127b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideoCapture, _id, 128b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org "Failed to add the send filter to the graph."); 129b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 130b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 131b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _inputSendPin = GetInputPin(_sinkFilter); 132b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 133b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Temporary connect here. 134b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // This is done so that no one else can use the capture device. 135b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (SetCameraOutput(_requestedCapability) != 0) 136b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 137b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 138b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 139b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org hr = _mediaControl->Pause(); 140b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (FAILED(hr)) 141b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 142b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideoCapture, _id, 143b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org "Failed to Pause the Capture device. Is it already occupied? %d.", 144b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org hr); 145b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 146b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 147b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(webrtc::kTraceStateInfo, webrtc::kTraceVideoCapture, _id, 148b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org "Capture device '%s' initialized.", deviceUniqueIdUTF8); 149b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return 0; 150b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 151b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 152f7e44d647cd0f893a185dfbe043cb313cab29fd0pbos@webrtc.orgint32_t VideoCaptureDS::StartCapture( 153b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org const VideoCaptureCapability& capability) 154b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 155b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org CriticalSectionScoped cs(&_apiCs); 156b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 157b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (capability != _requestedCapability) 158b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 159b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org DisconnectGraph(); 160b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 161b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (SetCameraOutput(capability) != 0) 162b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 163b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 164b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 165b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 166b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org HRESULT hr = _mediaControl->Run(); 167b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (FAILED(hr)) 168b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 169b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideoCapture, _id, 170b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org "Failed to start the Capture device."); 171b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 172b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 173b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return 0; 174b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 175b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 176f7e44d647cd0f893a185dfbe043cb313cab29fd0pbos@webrtc.orgint32_t VideoCaptureDS::StopCapture() 177b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 178b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org CriticalSectionScoped cs(&_apiCs); 179b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 180b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org HRESULT hr = _mediaControl->Pause(); 181b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (FAILED(hr)) 182b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 183b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideoCapture, _id, 184b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org "Failed to stop the capture graph. %d", hr); 185b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 186b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 187b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return 0; 188b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 189b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgbool VideoCaptureDS::CaptureStarted() 190b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 191b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org OAFilterState state = 0; 192b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org HRESULT hr = _mediaControl->GetState(1000, &state); 193b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (hr != S_OK && hr != VFW_S_CANT_CUE) 194b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 195b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideoCapture, _id, 196b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org "Failed to get the CaptureStarted status"); 197b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 198b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(webrtc::kTraceInfo, webrtc::kTraceVideoCapture, _id, 199b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org "CaptureStarted %d", state); 200b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return state == State_Running; 201b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 202b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 203f7e44d647cd0f893a185dfbe043cb313cab29fd0pbos@webrtc.orgint32_t VideoCaptureDS::CaptureSettings( 204b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org VideoCaptureCapability& settings) 205b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 206b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org settings = _requestedCapability; 207b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return 0; 208b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 209b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 210f7e44d647cd0f893a185dfbe043cb313cab29fd0pbos@webrtc.orgint32_t VideoCaptureDS::SetCameraOutput( 211b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org const VideoCaptureCapability& requestedCapability) 212b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 213b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 214b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Get the best matching capability 215b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org VideoCaptureCapability capability; 216f7e44d647cd0f893a185dfbe043cb313cab29fd0pbos@webrtc.org int32_t capabilityIndex; 217b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 218b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Store the new requested size 219b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _requestedCapability = requestedCapability; 220b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Match the requested capability with the supported. 221b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if ((capabilityIndex = _dsInfo.GetBestMatchedCapability(_deviceUniqueId, 222b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _requestedCapability, 223b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org capability)) < 0) 224b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 225b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 226b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 227b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org //Reduce the frame rate if possible. 228b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (capability.maxFPS > requestedCapability.maxFPS) 229b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 230b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org capability.maxFPS = requestedCapability.maxFPS; 231b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } else if (capability.maxFPS <= 0) 232b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 233b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org capability.maxFPS = 30; 234b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 235b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Store the new expected capture delay 236b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _captureDelay = capability.expectedCaptureDelay; 237b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 238b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Convert it to the windows capability index since they are not nexessary 239b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // the same 240b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org VideoCaptureCapabilityWindows windowsCapability; 241b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (_dsInfo.GetWindowsCapability(capabilityIndex, windowsCapability) != 0) 242b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 243b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 244b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 245b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 246b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org IAMStreamConfig* streamConfig = NULL; 247b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org AM_MEDIA_TYPE *pmt = NULL; 248b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org VIDEO_STREAM_CONFIG_CAPS caps; 249b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 250b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org HRESULT hr = _outputCapturePin->QueryInterface(IID_IAMStreamConfig, 251b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org (void**) &streamConfig); 252b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (hr) 253b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 254b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideoCapture, _id, 255b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org "Can't get the Capture format settings."); 256b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 257b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 258b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 259b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org //Get the windows capability from the capture device 260b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org bool isDVCamera = false; 261b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org hr = streamConfig->GetStreamCaps( 262b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org windowsCapability.directShowCapabilityIndex, 263b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org &pmt, reinterpret_cast<BYTE*> (&caps)); 264b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (!FAILED(hr)) 265b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 266b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (pmt->formattype == FORMAT_VideoInfo2) 267b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 268b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org VIDEOINFOHEADER2* h = 269b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org reinterpret_cast<VIDEOINFOHEADER2*> (pmt->pbFormat); 270b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (capability.maxFPS > 0 271b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org && windowsCapability.supportFrameRateControl) 272b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 273b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org h->AvgTimePerFrame = REFERENCE_TIME(10000000.0 274b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org / capability.maxFPS); 275b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 276b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 277b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org else 278b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 279b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org VIDEOINFOHEADER* h = reinterpret_cast<VIDEOINFOHEADER*> 280b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org (pmt->pbFormat); 281b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (capability.maxFPS > 0 282b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org && windowsCapability.supportFrameRateControl) 283b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 284b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org h->AvgTimePerFrame = REFERENCE_TIME(10000000.0 285b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org / capability.maxFPS); 286b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 287b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 288b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 289b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 290b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Set the sink filter to request this capability 291b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _sinkFilter->SetMatchingMediaType(capability); 292b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org //Order the capture device to use this capability 293b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org hr += streamConfig->SetFormat(pmt); 294b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 295b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org //Check if this is a DV camera and we need to add MS DV Filter 296b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (pmt->subtype == MEDIASUBTYPE_dvsl 297b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org || pmt->subtype == MEDIASUBTYPE_dvsd 298b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org || pmt->subtype == MEDIASUBTYPE_dvhd) 299b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org isDVCamera = true; // This is a DV camera. Use MS DV filter 300b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 301b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org RELEASE_AND_CLEAR(streamConfig); 302b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 303b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (FAILED(hr)) 304b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 305b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideoCapture, _id, 306b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org "Failed to set capture device output format"); 307b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 308b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 309b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 310b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (isDVCamera) 311b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 312b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org hr = ConnectDVCamera(); 313b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 314b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org else 315b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 316b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org hr = _graphBuilder->ConnectDirect(_outputCapturePin, _inputSendPin, 317b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org NULL); 318b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 319b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (hr != S_OK) 320b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 321b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideoCapture, _id, 322b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org "Failed to connect the Capture graph %d", hr); 323b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 324b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 325b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return 0; 326b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 327b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 328f7e44d647cd0f893a185dfbe043cb313cab29fd0pbos@webrtc.orgint32_t VideoCaptureDS::DisconnectGraph() 329b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 330b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org HRESULT hr = _mediaControl->Stop(); 331b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org hr += _graphBuilder->Disconnect(_outputCapturePin); 332b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org hr += _graphBuilder->Disconnect(_inputSendPin); 333b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 334b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org //if the DV camera filter exist 335b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (_dvFilter) 336b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 337b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _graphBuilder->Disconnect(_inputDvPin); 338b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _graphBuilder->Disconnect(_outputDvPin); 339b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 340b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (hr != S_OK) 341b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 342b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE( webrtc::kTraceError, webrtc::kTraceVideoCapture, _id, 343b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org "Failed to Stop the Capture device for reconfiguration %d", 344b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org hr); 345b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 346b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 347b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return 0; 348b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 349b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgHRESULT VideoCaptureDS::ConnectDVCamera() 350b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 351b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org HRESULT hr = S_OK; 352b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 353b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (!_dvFilter) 354b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 355b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org hr = CoCreateInstance(CLSID_DVVideoCodec, NULL, CLSCTX_INPROC, 356b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org IID_IBaseFilter, (void **) &_dvFilter); 357b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (hr != S_OK) 358b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 359b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideoCapture, _id, 360b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org "Failed to create the dv decoder: %x", hr); 361b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return hr; 362b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 363b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org hr = _graphBuilder->AddFilter(_dvFilter, L"VideoDecoderDV"); 364b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (hr != S_OK) 365b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 366b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideoCapture, _id, 367b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org "Failed to add the dv decoder to the graph: %x", hr); 368b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return hr; 369b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 370b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org _inputDvPin = GetInputPin(_dvFilter); 371b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (_inputDvPin == NULL) 372b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 373b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideoCapture, _id, 374b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org "Failed to get input pin from DV decoder"); 375b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 376b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 3770f224ffecd2f1190744b5bc5c97f4ce373ba0adetommi@webrtc.org _outputDvPin = GetOutputPin(_dvFilter, GUID_NULL); 378b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (_outputDvPin == NULL) 379b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 380b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideoCapture, _id, 381b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org "Failed to get output pin from DV decoder"); 382b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 383b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 384b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 385b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org hr = _graphBuilder->ConnectDirect(_outputCapturePin, _inputDvPin, NULL); 386b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (hr != S_OK) 387b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 388b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideoCapture, _id, 389b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org "Failed to connect capture device to the dv devoder: %x", 390b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org hr); 391b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return hr; 392b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 393b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 394b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org hr = _graphBuilder->ConnectDirect(_outputDvPin, _inputSendPin, NULL); 395b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (hr != S_OK) 396b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 397b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (hr == 0x80070004) 398b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 399b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideoCapture, _id, 400b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org "Failed to connect the capture device, busy"); 401b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 402b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org else 403b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 404b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideoCapture, _id, 405b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org "Failed to connect capture device to the send graph: 0x%x", 406b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org hr); 407b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 408b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return hr; 409b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 410b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return hr; 411b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 4123b89e10f31160da35b408fd00cb8f89d2b08862dpbos@webrtc.org} // namespace videocapturemodule 4133b89e10f31160da35b408fd00cb8f89d2b08862dpbos@webrtc.org} // namespace webrtc 414