向自定义 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);
.
.
}
我已经实现了接口函数(QueryInterface
、AddRef
和 Release
)。接口和过滤器 class 都在同一个头文件中。问题是添加接口部分后,实例创建本身就失败了。将过滤器添加到应用程序时进行的调用顺序是
- 构造函数
- AddRef
- 析构函数
调用析构函数后发生崩溃。相同的应用程序在没有界面的情况下工作。
关于过滤器和界面有什么问题有什么建议吗?如果我应该分享更多信息,请告诉我。
感谢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);
}
}
我正在为 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);
.
.
}
我已经实现了接口函数(QueryInterface
、AddRef
和 Release
)。接口和过滤器 class 都在同一个头文件中。问题是添加接口部分后,实例创建本身就失败了。将过滤器添加到应用程序时进行的调用顺序是
- 构造函数
- AddRef
- 析构函数
调用析构函数后发生崩溃。相同的应用程序在没有界面的情况下工作。
关于过滤器和界面有什么问题有什么建议吗?如果我应该分享更多信息,请告诉我。
感谢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);
}
}