前言

代码分析
VideoCaptureDS::Init
int32_t VideoCaptureDS::Init(const char* deviceUniqueIdUTF8) {****_outputCapturePin = GetOutputPin(_captureFilter, PIN_CATEGORY_CAPTURE);if (!_outputCapturePin) {RTC_LOG(LS_INFO) << "Failed to get output capture pin";return -1;}// Create the sink filte used for receiving Captured frames.sink_filter_ = new ComRefCount<CaptureSinkFilter>(this);hr = _graphBuilder->AddFilter(sink_filter_, SINK_FILTER_NAME);if (FAILED(hr)) {RTC_LOG(LS_INFO) << "Failed to add the send filter to the graph.";return -1;}_inputSendPin = GetInputPin(sink_filter_);if (!_inputSendPin) {RTC_LOG(LS_INFO) << "Failed to get input send pin";return -1;}****}
实际上在调用graphBuilder->AddFilter(sink_filter, SINK_FILTER_NAME);之后,后面还会去调用CaptureSinkFilter::JoinFilterGraph,去告诉上层已经加入到FilterGraphl .
STDMETHODIMP CaptureSinkFilter::JoinFilterGraph(IFilterGraph* graph,LPCWSTR name) {RTC_DCHECK_RUN_ON(&main_checker_);RTC_DCHECK(IsStopped());// Note, since a reference to the filter is held by the graph manager,// filters must not hold a reference to the graph. If they would, we'd have// a circular reference. Instead, a pointer to the graph can be held without// reference. See documentation for IBaseFilter::JoinFilterGraph for more.info_.pGraph = graph; // No AddRef().sink_ = nullptr;if (info_.pGraph) {// make sure we don't hold on to the reference we may receive.// Note that this assumes the same object identity, but so be it.// 当filter有事件发生时,通过sink来通知filtergraphrtc::scoped_refptr<IMediaEventSink> sink;GetComInterface(info_.pGraph, &sink);sink_ = sink.get();}info_.achName[0] = L'\0';if (name)lstrcpynW(info_.achName, name, arraysize(info_.achName));return S_OK;}
—》 inputSendPin = GetInputPin(sink_filter);
GetInputPin
IPin* GetInputPin(IBaseFilter* filter) {HRESULT hr;IPin* pin = NULL;IEnumPins* pPinEnum = NULL;filter->EnumPins(&pPinEnum);if (pPinEnum == NULL) {return NULL;}// get first unconnected pin// 引用计数设置为0,从第一个pin开始hr = pPinEnum->Reset(); // set to first pinwhile (S_OK == pPinEnum->Next(1, &pin, NULL)) {PIN_DIRECTION pPinDir;pin->QueryDirection(&pPinDir);if (PINDIR_INPUT == pPinDir) // This is an input pin{IPin* tempPin = NULL;if (S_OK != pin->ConnectedTo(&tempPin)) // The pint is not connected{pPinEnum->Release();return pin;}}pin->Release();}pPinEnum->Release();return NULL;}
1、 filter->EnumPins(&pPinEnum); 的定义如下
STDMETHODIMP CaptureSinkFilter::EnumPins(IEnumPins** pins) {RTC_DCHECK_RUN_ON(&main_checker_);*pins = new ComRefCount<class EnumPins>(input_pin_.get());(*pins)->AddRef();return S_OK;}
2、 hr = pPinEnum->Reset();
STDMETHOD(Reset)() {pos_ = 0;return S_OK;}
3、while (S_OK == pPinEnum->Next(1, &pin, NULL)) {
STDMETHOD(Next)(ULONG count, IPin** pins, ULONG* fetched) {RTC_DCHECK(count > 0);RTC_DCHECK(pins);// fetched may be NULL.if (pos_ > 0) { // 正常不会大于0if (fetched)*fetched = 0;return S_FALSE;}++pos_;pins[0] = pin_.get();pins[0]->AddRef(); // 引用计数的增加if (fetched)*fetched = 1;return count == 1 ? S_OK : S_FALSE;}
4、pin->QueryDirection(&pPinDir);
STDMETHODIMP CaptureInputPin::QueryDirection(PIN_DIRECTION* pin_dir) {RTC_DCHECK_RUN_ON(&main_checker_);*pin_dir = info_.dir;return S_OK;}
5、 if (S_OK != pin->ConnectedTo(&tempPin)) // The pint is not connected
判断当前引脚是否已经和其他引脚连接,正常不连接
STDMETHODIMP CaptureInputPin::ConnectedTo(IPin** pin) {RTC_DCHECK_RUN_ON(&main_checker_);if (!receive_pin_)return VFW_E_NOT_CONNECTED; //正常返回这个*pin = receive_pin_.get();receive_pin_->AddRef();return S_OK;}
