向自定义 directshow 转换过滤器添加接口

Adding interface to custom directshow transform filter

我正在为 CTransformFilter 编写自定义 DirectShow 过滤器。 基本过滤器工作正常。我在向过滤器添加接口时遇到问题。工作正常的过滤器代码如下所示:

interface CVideoDecoder : public CTransformFilter, public IVideoDecoderProp
{
public:
    static CUnknown* WINAPI
  CreateInstance(LPUNKNOWN pUnknown, HRESULT* pHresult);

public:
 // Constructor
 CVideoDecoder(TCHAR*    FilterName, LPUNKNOWN pUnknown, HRESULT   *pHr);

 //Destructor
 ~CVideoDecoder(void);

 /* CTransformFilter's methods overidden by this class */
 HRESULT Transform(IMediaSample* pSourceMediaSample, IMediaSample* pDestMediaSample);

 HRESULT CheckInputType(const CMediaType* pInMediaType);

 HRESULT CheckTransform(const CMediaType* pInMediaType, const CMediaType* pOutMediaType);

 HRESULT GetMediaType(int Position, CMediaType* pMediaType);

 HRESULT DecideBufferSize(IMemAllocator* pAlloc, ALLOCATOR_PROPERTIES* pProperties);

 HRESULT BreakConnect(PIN_DIRECTION PinDirection);

 HRESULT SetMediaType(PIN_DIRECTION direction,
  const CMediaType *pmt);

 HRESULT allocBuffer(UWORD32 bufferSize, void** buffer);

 HRESULT freeBuffer(UWORD32 bufferSize, void* buffer);
 HRESULT CacheInvalidateBuffer(void* buffer, UWORD32 bufferSize);

 HRESULT CheckMediaType(const CMediaType *pmt);

#if SUPPORT_BEGIN_FLUSH
 /* Overriding the CTransform Filter's Begin Flush */
 HRESULT BeginFlush();
#endif

#if SUPPORT_EOS
 HRESULT EndOfStream(void);
#endif
 //HRESULT StopStreaming();
#if QUALITY_CONTROL
 HRESULT AlterQuality(Quality q);
#endif

protected:
private:
}

添加接口后的代码如下所示:

EXTERN_C const IID IID_IVideoDecoderProp;

#if defined(__cplusplus) && !defined(CINTERFACE)
MIDL_INTERFACE("11c4bb72-1df3-4bf3-a158-f23aa886e53b")
IVideoDecoderProp : public IUnknown
{
public:
    virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, __deref_out void **ppv);
    virtual ULONG STDMETHODCALLTYPE AddRef();
    virtual ULONG STDMETHODCALLTYPE Release();
    virtual HRESULT STDMETHODCALLTYPE PrintSomething() = 0;
};
#endif

interface CVideoDecoder : public CTransformFilter, public IVideoDecoderProp
{
public:

    HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, __deref_out void **ppv);
    ULONG STDMETHODCALLTYPE AddRef();
    ULONG STDMETHODCALLTYPE Release();
    // function for testing interface implementation
    HRESULT STDMETHODCALLTYPE PrintSomething();

    static CUnknown* WINAPI
  CreateInstance(LPUNKNOWN pUnknown, HRESULT* pHresult);

public:
 // moved to videodecoder.cpp
 // Constructor
 CVideoDecoder(TCHAR*    FilterName, LPUNKNOWN pUnknown, HRESULT   *pHr);

 //Destructor
 ~CVideoDecoder(void);

 /* CTransformFilter's methods overidden by this class */
 HRESULT Transform(IMediaSample* pSourceMediaSample, IMediaSample* pDestMediaSample);

.
.
}

我已经实现了接口函数(QueryInterfaceAddRefRelease)。接口和过滤器 class 都在同一个头文件中。问题是添加接口部分后,实例创建本身就失败了。将过滤器添加到应用程序时进行的调用顺序是

  1. 构造函数
  2. AddRef
  3. 析构函数

调用析构函数后发生崩溃。相同的应用程序在没有界面的情况下工作。

关于过滤器和界面有什么问题有什么建议吗?如果我应该分享更多信息,请告诉我。

感谢Roman R的建议。现在开始工作了。下面是界面变化。

    DEFINE_GUID(IID_IVideoDecoderProperty,
            0x11c4bb72, 0x1df3, 0x4bf3, 0xa1, 0x58, 0xf2, 0x3a, 0xa8, 0x86, 0xe5, 0x3b);

    DECLARE_INTERFACE_(IVideoDecoderProperty, IUnknown)
    {
        STDMETHOD(MyFilterSetting1) (THIS_ unsigned int) PURE;
        STDMETHOD(MyFilterSetting2) (THIS_ unsigned int) PURE;
    };

class CVideoDecoder : public CTransformFilter, public IVideoDecoderProperty
{
public:

    DECLARE_IUNKNOWN;
    static CUnknown* WINAPI
  CreateInstance(LPUNKNOWN pUnknown, HRESULT* pHresult);

    STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, void ** ppv);
public:
 // moved to videodecoder.cpp
 // Constructor
 CVideoDecoder(TCHAR*    FilterName,
  LPUNKNOWN pUnknown,
  HRESULT   *pHr);

 //Destructor
 ~CVideoDecoder(void);

 /* CTransformFilter's methods overidden by this class */
 HRESULT Transform(IMediaSample* pSourceMediaSample, IMediaSample* pDestMediaSample);

 HRESULT CheckInputType(const CMediaType* pInMediaType);

 HRESULT CheckTransform(const CMediaType* pInMediaType, const CMediaType* pOutMediaType);

 HRESULT GetMediaType(int Position, CMediaType* pMediaType);

 HRESULT DecideBufferSize(IMemAllocator* pAlloc, ALLOCATOR_PROPERTIES* pProperties);

 HRESULT BreakConnect(PIN_DIRECTION PinDirection);

 HRESULT SetMediaType(PIN_DIRECTION direction,
  const CMediaType *pmt);

    // filter property
    STDMETHODIMP MyFilterSetting1(unsigned int);
    STDMETHODIMP MyFilterSetting2(unsigned int);

NonDelegatingQueryInterface实现如下

STDMETHODIMP CVideoDecoder::NonDelegatingQueryInterface(REFIID riid, void **ppv)
{
    CheckPointer(ppv,E_POINTER);

    if (riid == IID_IVideoDecoderProperty) 
    {
        return GetInterface((IVideoDecoderProperty *) this, ppv);
    } 
    else if (riid == IID_ISpecifyPropertyPages) 
    {
        return GetInterface((ISpecifyPropertyPages *) this, ppv);
    } 
    else
    {
        return CTransformFilter::NonDelegatingQueryInterface(riid, ppv);
    }
}