前言
CaptureFilter就是用dshow采集视频数据,然后添加到filter graph中,获取数据后调用filter来处理。
代码分析
h:\webrtc-20210315\webrtc-20210315\webrtc\webrtc-checkout\src\modules\video_capture\windows\video_capture_ds.cc
VideoCaptureDS::Init
int32_t VideoCaptureDS::Init(const char* deviceUniqueIdUTF8) {***_captureFilter = _dsInfo.GetDeviceFilter(deviceUniqueIdUTF8);if (!_captureFilter) {RTC_LOG(LS_INFO) << "Failed to create capture filter.";return -1;}// Get the interface for DirectShow's GraphBuilderHRESULT hr = CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER,IID_IGraphBuilder, (void**)&_graphBuilder);if (FAILED(hr)) {RTC_LOG(LS_INFO) << "Failed to create graph builder.";return -1;}hr = _graphBuilder->QueryInterface(IID_IMediaControl, (void**)&_mediaControl);if (FAILED(hr)) {RTC_LOG(LS_INFO) << "Failed to create media control builder.";return -1;}hr = _graphBuilder->AddFilter(_captureFilter, CAPTURE_FILTER_NAME);if (FAILED(hr)) {RTC_LOG(LS_INFO) << "Failed to add the capture device to the graph.";return -1;}_outputCapturePin = GetOutputPin(_captureFilter, PIN_CATEGORY_CAPTURE);if (!_outputCapturePin) {RTC_LOG(LS_INFO) << "Failed to get output capture pin";return -1;}***}
—》 _captureFilter = _dsInfo.GetDeviceFilter(deviceUniqueIdUTF8);
DeviceInfoDS::GetDeviceFilter
IBaseFilter* DeviceInfoDS::GetDeviceFilter(const char* deviceUniqueIdUTF8,char* productUniqueIdUTF8,uint32_t productUniqueIdUTF8Length) {***// enumerate all video capture devicesRELEASE_AND_CLEAR(_dsMonikerDevEnum);// 遍历获取视频输入设备HRESULT hr = _dsDevEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory,&_dsMonikerDevEnum, 0);if (hr != NOERROR) {RTC_LOG(LS_INFO) << "Failed to enumerate CLSID_SystemDeviceEnum, error 0x"<< rtc::ToHex(hr) << ". No webcam exist?";return 0;}_dsMonikerDevEnum->Reset();ULONG cFetched;IMoniker* pM;IBaseFilter* captureFilter = NULL;bool deviceFound = false;// 遍历每个设备,这里只找到一个可用的设备就退出循环了while (S_OK == _dsMonikerDevEnum->Next(1, &pM, &cFetched) && !deviceFound) {IPropertyBag* pBag;// 获取IID_IPropertyBag接口属性hr = pM->BindToStorage(0, 0, IID_IPropertyBag, (void**)&pBag);if (S_OK == hr) {// Find the description or friendly name.VARIANT varName;VariantInit(&varName);if (deviceUniqueIdUTF8Length > 0) {hr = pBag->Read(L"DevicePath", &varName, 0);if (FAILED(hr)) {hr = pBag->Read(L"Description", &varName, 0);if (FAILED(hr)) {hr = pBag->Read(L"FriendlyName", &varName, 0);}}if (SUCCEEDED(hr)) {char tempDevicePathUTF8[256];tempDevicePathUTF8[0] = 0;WideCharToMultiByte(CP_UTF8, 0, varName.bstrVal, -1,tempDevicePathUTF8, sizeof(tempDevicePathUTF8),NULL, NULL);if (strncmp(tempDevicePathUTF8, (const char*)deviceUniqueIdUTF8,deviceUniqueIdUTF8Length) == 0) {// We have found the requested devicedeviceFound = true; //找到了可用设备// 找到获取数据的filterhr =pM->BindToObject(0, 0, IID_IBaseFilter, (void**)&captureFilter);ifFAILED(hr) {RTC_LOG(LS_ERROR) << "Failed to bind to the selected ""capture device "<< hr;}if (productUniqueIdUTF8 &&productUniqueIdUTF8Length > 0) // Get the device name{GetProductId(deviceUniqueIdUTF8, productUniqueIdUTF8,productUniqueIdUTF8Length);}}}}VariantClear(&varName);pBag->Release();}pM->Release();}return captureFilter;}
