【问题标题】:Problems connecting to the input pins of GMFBridge Sink Filter连接到 GMFBridge 漏极滤波器输入引脚的问题
【发布时间】:2018-09-28 18:34:46
【问题描述】:

我在尝试将 GMFBridge 过滤器与 Euresys UxH264 卡的输出一起使用时遇到了一个奇怪的问题。

我正在尝试将此卡集成到我们的解决方案中,该解决方案依赖 GMFBridge 来处理连续捕获多个文件的能力,执行多路复用和文件拆分,而无需停止捕获图。

此卡从模拟输入捕获视频和音频。它提供了一个 DirectShow 过滤器,同时公开视频输入的原始流和硬件编码的 H.264 流。音频流仅作为未压缩流提供。

当我尝试将 Euresys 源滤波器的任何输出引脚直接连接到 GMFBridge 接收器的输入引脚时,它们都会被拒绝,代码为 VFW_E_NO_ALLOCATOR。 (过去我已经成功地将 H.264 和原始音频流连接到网桥)。

抓住吸管,我在 Euresys 卡式过滤器和桥式接收器过滤器之间插入了一对 SampleGrabber 过滤器,并且 - 就像那样 - 样本采集器和接收器之间的连接被接受。

但是,我在网桥的另一侧(多路复用图)没有收到任何数据包。我使用 GraphStudioNext 检查了正在运行的捕获图,并且以某种方式样本抓取器似乎与我的图分离,即使我在将它们连接到源过滤器时得到了成功的确认!

这是创建图表的源代码。

void EuresysSourceBox::BuildGraph() {
   HRESULT hRes;

   CComPtr<IGraphBuilder> pGraph;
   COM_CALL(pGraph.CoCreateInstance(CLSID_FilterGraph));
   #ifdef REGISTER_IN_ROT
      _rotEntry1 = FilterTools::RegisterGraphInROT(IntPtr(pGraph), "euresys graph");
   #endif

   // [*Video Source*]

   String^ filterName = "Ux H.264 Visual Source";
   Guid category = _GUIDToGuid((GUID)AM_KSCATEGORY_CAPTURE);
   FilterMonikerList^ videoSourceList = FilterTools::GetFilterMonikersByName(category, filterName);
   CComPtr<IBaseFilter> pVideoSource;
   int monikerIndex = config->BoardIndex;  // a filter instance will be retrieved for every installed board
   clr_scoped_ptr<CComPtr<IMoniker>>^ ppVideoSourceMoniker = videoSourceList[monikerIndex];

   COM_CALL((*ppVideoSourceMoniker->get())->BindToObject(NULL, NULL, IID_IBaseFilter, (void**)&pVideoSource));
   COM_CALL(pGraph->AddFilter(pVideoSource, L"VideoSource"));

   // [Video Source]
   //
   // [*Audio Source*]

   filterName = "Ux H.264 Audio Encoder";
   FilterMonikerList^ audioSourceList = FilterTools::GetFilterMonikersByName(category, filterName);
   CComPtr<IBaseFilter> pAudioSource;
   clr_scoped_ptr<CComPtr<IMoniker>>^ ppAudioSourceMoniker = audioSourceList[monikerIndex];
   COM_CALL((*ppAudioSourceMoniker->get())->BindToObject(NULL, NULL, IID_IBaseFilter, (void**)&pAudioSource));
   COM_CALL(pGraph->AddFilter(pAudioSource, L"AudioSource"));

   CComPtr<IPin> pVideoCompressedOutPin(FilterTools::GetPin(pVideoSource, "Encoded"));
   CComPtr<IPin> pAudioOutPin(FilterTools::GetPin(pAudioSource, "Audio"));

   CComPtr<IBaseFilter> pSampleGrabber;
   COM_CALL(pSampleGrabber.CoCreateInstance(CLSID_SampleGrabber));
   COM_CALL(pGraph->AddFilter(pSampleGrabber, L"SampleGrabber"));
   CComPtr<IPin> pSampleGrabberInPin(FilterTools::GetPin(pSampleGrabber, "Input"));
   COM_CALL(pGraph->ConnectDirect(pVideoCompressedOutPin, pSampleGrabberInPin, NULL));    // DOES NOT FAIL!!


   CComPtr<IBaseFilter> pSampleGrabber2;
   COM_CALL(pSampleGrabber2.CoCreateInstance(CLSID_SampleGrabber));
   COM_CALL(pGraph->AddFilter(pSampleGrabber2, L"SampleGrabber2"));
   CComPtr<IPin> pSampleGrabber2InPin(FilterTools::GetPin(pSampleGrabber2, "Input"));
   COM_CALL(pGraph->ConnectDirect(pAudioOutPin, pSampleGrabber2InPin, NULL));             // DOES NOT FAIL!!

   // [Video Source]---
   //                  |-->[*Bridge Sink*]
   // [Audio Source]---


   CComPtr<IPin> pSampleGrabberOutPin(FilterTools::GetPin(pSampleGrabber, "Output"));
   CComPtr<IPin> pSampleGrabber2OutPin(FilterTools::GetPin(pSampleGrabber2, "Output"));

   CreateGraphBridge(
      IntPtr(pGraph),
      IntPtr(pSampleGrabberOutPin),
      IntPtr(pSampleGrabber2OutPin)
   );

   // Root graph to parent object
   _ppCaptureGraph.reset(new CComPtr<IGraphBuilder>(pGraph));
}

COM_CALL 是我的HRESULT 检查宏,如果结果不是S_OK,它将引发托管异常。所以管脚之间的连接成功了,但是运行时图表看起来是这样的:

所以,我有三个问题:

1) 在这种情况下VFW_E_NO_ALLOCATOR 是什么意思?(源过滤器可以成功连接到其他组件,例如 LAV 视频解码器或 ffdshow 视频解码器)。

2) 是否有已知的解决方法来规避VFW_E_NO_ALLOCATOR 问题?

3) 过滤器是否有可能在运行时断开连接,就像我的情况一样?

【问题讨论】:

    标签: c++-cli directshow


    【解决方案1】:

    found a reference by Geraint Davies 给出了 GMFBridge 接收器过滤器可能拒绝连接的原因。

    看起来解析器坚持使用自己的分配器 -- 这在解析器中很常见,其中输出样本只是指向输入样本的指针。但是,桥无法实现 挂起模式不使用自己的分配器,因此需要一个副本。

    有了这些信息,我决定创建一个超简单的 CTransformFilter 过滤器,它只接受桥提供的分配器并将输入样本中的任何内容复制到输出样本。我不是 100% 确定我所做的是正确的,但它现在正在工作。我可以成功地将 Euresys 卡插入到我的捕获基础架构中。

    作为参考,如果有人遇到类似的事情,这里是我创建的过滤器的代码:

    class SampleCopyGeneratorFilter : public CTransformFilter {
    protected:
       HRESULT CheckInputType(const CMediaType* mtIn) override { return S_OK; }
       HRESULT GetMediaType(int iPosition, CMediaType* pMediaType) override;
       HRESULT CheckTransform(const CMediaType *mtIn, const CMediaType *mtOut) override { return S_OK; }
       HRESULT DecideBufferSize(IMemAllocator *pAlloc, ALLOCATOR_PROPERTIES *pProp) override;
       HRESULT Transform(IMediaSample *pSource, IMediaSample *pDest) override;
    public:
       SampleCopyGeneratorFilter();
    };
    
    //--------------------------------------------------------------------------------------------------------------------
    
    SampleCopyGeneratorFilter::SampleCopyGeneratorFilter() 
       : CTransformFilter(NAME("SampleCopyGeneratorFilter"), NULL, GUID_NULL)       
    {
    
    }
    
    
    HRESULT SampleCopyGeneratorFilter::GetMediaType(int iPosition, CMediaType* pMediaType) {
       HRESULT hRes;
       ASSERT(m_pInput->IsConnected());
       if( iPosition < 0 )
          return E_INVALIDARG;
    
       CComPtr<IPin> connectedTo;
       COM_CALL(m_pInput->ConnectedTo(&connectedTo));
    
       CComPtr<IEnumMediaTypes> pMTEnumerator;
       COM_CALL(connectedTo->EnumMediaTypes(&pMTEnumerator));
       AM_MEDIA_TYPE* pIteratedMediaType;
       for( int i = 0; i <= iPosition; i++ ) {
          if( pMTEnumerator->Next(1, &pIteratedMediaType, NULL) != S_OK )
             return VFW_S_NO_MORE_ITEMS;
          if( i == iPosition )
             *pMediaType = *pIteratedMediaType;
          DeleteMediaType(pIteratedMediaType);
       }
       return S_OK;
    }
    
    
    HRESULT SampleCopyGeneratorFilter::DecideBufferSize(IMemAllocator *pAlloc, ALLOCATOR_PROPERTIES *pProp) {
       HRESULT hRes;
       AM_MEDIA_TYPE mt;
       COM_CALL(m_pInput->ConnectionMediaType(&mt));
       try {
          BITMAPINFOHEADER* pBMI = HEADER(mt.pbFormat);
          pProp->cbBuffer = DIBSIZE(*pBMI);   // format is compressed, uncompressed size should be enough
          if( !pProp->cbAlign )
             pProp->cbAlign = 1;
          pProp->cbPrefix = 0;
          pProp->cBuffers = 4;
    
          ALLOCATOR_PROPERTIES actualProperties;
          COM_CALL(pAlloc->SetProperties(pProp, &actualProperties));
          if( pProp->cbBuffer > actualProperties.cbBuffer )
             return E_FAIL;
          return S_OK;
       } finally{
          FreeMediaType(mt);
       }
    }
    
    
    HRESULT SampleCopyGeneratorFilter::Transform(IMediaSample *pSource, IMediaSample *pDest) {
       HRESULT hRes;
       BYTE* pBufferIn;
       BYTE* pBufferOut;
       long destSize = pDest->GetSize();
       long dataLen = pSource->GetActualDataLength();
       if( dataLen > destSize )
          return VFW_E_BUFFER_OVERFLOW;
       COM_CALL(pSource->GetPointer(&pBufferIn));
       COM_CALL(pDest->GetPointer(&pBufferOut));
       memcpy(pBufferOut, pBufferIn, dataLen);
       pDest->SetActualDataLength(dataLen);
       pDest->SetSyncPoint(pSource->IsSyncPoint() == S_OK);
       return S_OK;
    }
    

    这是我在捕获图中插入过滤器的方式:

       CComPtr<IPin> pAACEncoderOutPin(FilterTools::GetPin(pAACEncoder, "XForm Out"));
       CComPtr<IPin> pVideoSourceCompressedOutPin(FilterTools::GetPin(pVideoSource, "Encoded"));
    
       CComPtr<IBaseFilter> pSampleCopier;
       pSampleCopier = new SampleCopyGeneratorFilter();
       COM_CALL(pGraph->AddFilter(pSampleCopier, L"SampleCopier"));
       CComPtr<IPin> pSampleCopierInPin(FilterTools::GetPin(pSampleCopier, "XForm In"));
       COM_CALL(pGraph->ConnectDirect(pVideoSourceCompressedOutPin, pSampleCopierInPin, NULL));
       CComPtr<IPin> pSampleCopierOutPin(FilterTools::GetPin(pSampleCopier, "XForm Out"));
    
    
       CreateGraphBridge(
          IntPtr(pGraph),
          IntPtr(pSampleCopierOutPin),
          IntPtr(pAACEncoderOutPin)
       );
    

    现在,我仍然不知道为什么插入样本采集器不起作用并导致图表分离。我也通过使用 Graphedit Plus 检查图表来证实了这个怪癖。如果有人能给我一个解释,我将非常感激。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-10-29
      • 1970-01-01
      • 2011-07-04
      • 1970-01-01
      • 1970-01-01
      • 2016-04-04
      • 2021-01-20
      相关资源
      最近更新 更多