前言

image.png

代码分析

VideoCaptureDS::Init

  1. int32_t VideoCaptureDS::Init(const char* deviceUniqueIdUTF8) {
  2. ****
  3. _outputCapturePin = GetOutputPin(_captureFilter, PIN_CATEGORY_CAPTURE);
  4. if (!_outputCapturePin) {
  5. RTC_LOG(LS_INFO) << "Failed to get output capture pin";
  6. return -1;
  7. }
  8. // Create the sink filte used for receiving Captured frames.
  9. sink_filter_ = new ComRefCount<CaptureSinkFilter>(this);
  10. hr = _graphBuilder->AddFilter(sink_filter_, SINK_FILTER_NAME);
  11. if (FAILED(hr)) {
  12. RTC_LOG(LS_INFO) << "Failed to add the send filter to the graph.";
  13. return -1;
  14. }
  15. _inputSendPin = GetInputPin(sink_filter_);
  16. if (!_inputSendPin) {
  17. RTC_LOG(LS_INFO) << "Failed to get input send pin";
  18. return -1;
  19. }
  20. ****
  21. }

实际上在调用graphBuilder->AddFilter(sink_filter, SINK_FILTER_NAME);之后,后面还会去调用CaptureSinkFilter::JoinFilterGraph,去告诉上层已经加入到FilterGraphl .

  1. STDMETHODIMP CaptureSinkFilter::JoinFilterGraph(IFilterGraph* graph,
  2. LPCWSTR name) {
  3. RTC_DCHECK_RUN_ON(&main_checker_);
  4. RTC_DCHECK(IsStopped());
  5. // Note, since a reference to the filter is held by the graph manager,
  6. // filters must not hold a reference to the graph. If they would, we'd have
  7. // a circular reference. Instead, a pointer to the graph can be held without
  8. // reference. See documentation for IBaseFilter::JoinFilterGraph for more.
  9. info_.pGraph = graph; // No AddRef().
  10. sink_ = nullptr;
  11. if (info_.pGraph) {
  12. // make sure we don't hold on to the reference we may receive.
  13. // Note that this assumes the same object identity, but so be it.
  14. // 当filter有事件发生时,通过sink来通知filtergraph
  15. rtc::scoped_refptr<IMediaEventSink> sink;
  16. GetComInterface(info_.pGraph, &sink);
  17. sink_ = sink.get();
  18. }
  19. info_.achName[0] = L'\0';
  20. if (name)
  21. lstrcpynW(info_.achName, name, arraysize(info_.achName));
  22. return S_OK;
  23. }

—》 inputSendPin = GetInputPin(sink_filter);

GetInputPin

  1. IPin* GetInputPin(IBaseFilter* filter) {
  2. HRESULT hr;
  3. IPin* pin = NULL;
  4. IEnumPins* pPinEnum = NULL;
  5. filter->EnumPins(&pPinEnum);
  6. if (pPinEnum == NULL) {
  7. return NULL;
  8. }
  9. // get first unconnected pin
  10. // 引用计数设置为0,从第一个pin开始
  11. hr = pPinEnum->Reset(); // set to first pin
  12. while (S_OK == pPinEnum->Next(1, &pin, NULL)) {
  13. PIN_DIRECTION pPinDir;
  14. pin->QueryDirection(&pPinDir);
  15. if (PINDIR_INPUT == pPinDir) // This is an input pin
  16. {
  17. IPin* tempPin = NULL;
  18. if (S_OK != pin->ConnectedTo(&tempPin)) // The pint is not connected
  19. {
  20. pPinEnum->Release();
  21. return pin;
  22. }
  23. }
  24. pin->Release();
  25. }
  26. pPinEnum->Release();
  27. return NULL;
  28. }

1、 filter->EnumPins(&pPinEnum); 的定义如下

  1. STDMETHODIMP CaptureSinkFilter::EnumPins(IEnumPins** pins) {
  2. RTC_DCHECK_RUN_ON(&main_checker_);
  3. *pins = new ComRefCount<class EnumPins>(input_pin_.get());
  4. (*pins)->AddRef();
  5. return S_OK;
  6. }

2、 hr = pPinEnum->Reset();

  1. STDMETHOD(Reset)() {
  2. pos_ = 0;
  3. return S_OK;
  4. }

3、while (S_OK == pPinEnum->Next(1, &pin, NULL)) {

  1. STDMETHOD(Next)(ULONG count, IPin** pins, ULONG* fetched) {
  2. RTC_DCHECK(count > 0);
  3. RTC_DCHECK(pins);
  4. // fetched may be NULL.
  5. if (pos_ > 0) { // 正常不会大于0
  6. if (fetched)
  7. *fetched = 0;
  8. return S_FALSE;
  9. }
  10. ++pos_;
  11. pins[0] = pin_.get();
  12. pins[0]->AddRef(); // 引用计数的增加
  13. if (fetched)
  14. *fetched = 1;
  15. return count == 1 ? S_OK : S_FALSE;
  16. }

4、pin->QueryDirection(&pPinDir);

  1. STDMETHODIMP CaptureInputPin::QueryDirection(PIN_DIRECTION* pin_dir) {
  2. RTC_DCHECK_RUN_ON(&main_checker_);
  3. *pin_dir = info_.dir;
  4. return S_OK;
  5. }

5、 if (S_OK != pin->ConnectedTo(&tempPin)) // The pint is not connected
判断当前引脚是否已经和其他引脚连接,正常不连接

  1. STDMETHODIMP CaptureInputPin::ConnectedTo(IPin** pin) {
  2. RTC_DCHECK_RUN_ON(&main_checker_);
  3. if (!receive_pin_)
  4. return VFW_E_NOT_CONNECTED; //正常返回这个
  5. *pin = receive_pin_.get();
  6. receive_pin_->AddRef();
  7. return S_OK;
  8. }