DirectShow 学习(二):CBasePin类、CBaseOutputPin类和CBaseInputPin类源代码解析
1. IPin接口
IPin : public IUnknown
{
public:
// 连接两个Pin,主动连接InputPin
virtual HRESULT STDMETHODCALLTYPE Connect(
/* [in] */ IPin *pReceivePin,
/* [in] */ const AM_MEDIA_TYPE *pmt) = 0;
// 连接两个Pin,被动连接
virtual HRESULT STDMETHODCALLTYPE ReceiveConnection(
/* [in] */ IPin *pConnector,
/* [in] */ const AM_MEDIA_TYPE *pmt) = 0;
// 断开连接,只能在Stop状态下断开
virtual HRESULT STDMETHODCALLTYPE Disconnect( void) = 0;
// 得到连接的Pin的接口,成功返回连接的Pin被调用AddRef
virtual HRESULT STDMETHODCALLTYPE ConnectedTo(
/* [out] */ IPin **pPin) = 0;
// 得到连接状态下的MediaType
virtual HRESULT STDMETHODCALLTYPE ConnectionMediaType(
/* [out] */ AM_MEDIA_TYPE *pmt) = 0;
// 得到Pin的信息,填充PIN_INFO结构
virtual HRESULT STDMETHODCALLTYPE QueryPinInfo(
/* [out] */ PIN_INFO *pInfo) = 0;
// 得到Pin的连接方向
virtual HRESULT STDMETHODCALLTYPE QueryDirection(
/* [out] */ PIN_DIRECTION *pPinDir) = 0;
// 得到ID - 其实是Pin中的name
virtual HRESULT STDMETHODCALLTYPE QueryId(
/* [out] */ LPWSTR *Id) = 0;
// Determines whether the pin accepts a specified media type.
virtual HRESULT STDMETHODCALLTYPE QueryAccept(
/* [in] */ const AM_MEDIA_TYPE *pmt) = 0;
// Enumerates the pin's preferred media types.
virtual HRESULT STDMETHODCALLTYPE EnumMediaTypes(
/* [out] */ IEnumMediaTypes **ppEnum) = 0;
// Retrieves the pins that are connected internally to this pin (within the filter).
virtual HRESULT STDMETHODCALLTYPE QueryInternalConnections(
/* [out] */ IPin **apPin,
/* [out][in] */ ULONG *nPin) = 0;
// Notifies the pin that no additional data is expected
virtual HRESULT STDMETHODCALLTYPE EndOfStream( void) = 0;
// Begins / End a flush operation.
virtual HRESULT STDMETHODCALLTYPE BeginFlush( void) = 0;
virtual HRESULT STDMETHODCALLTYPE EndFlush( void) = 0;
// Notifies the pin that media samples received after this call are grouped as a segment.
virtual HRESULT STDMETHODCALLTYPE NewSegment(
/* [in] */ REFERENCE_TIME tStart,
/* [in] */ REFERENCE_TIME tStop,
/* [in] */ double dRate) = 0;
};
2. IQualityControl接口
IQualityControl : public IUnknown
{
public:
// Notifies the recipient that a quality change is requested.
virtual HRESULT STDMETHODCALLTYPE Notify(
/* [in] */ IBaseFilter *pSelf,
/* [in] */ Quality q) = 0;
virtual HRESULT STDMETHODCALLTYPE SetSink(
/* [in] */ IQualityControl *piqc) = 0;
};
3. CBasePin类[amfilter.h/amfilter.cpp]
o 派生自 CUnknown, IPin, IQualityControl
成员变量:
WCHAR * m_pName; // This pin's name
IPin *m_Connected; // Pin we have connected to
PIN_DIRECTION m_dir; // Direction of this pin
CCritSec *m_pLock; // Object we use for locking
bool m_bRunTimeError; // Run time error generated
bool m_bCanReconnectWhenActive; // OK to reconnect when active
bool m_bTryMyTypesFirst; // When connecting enumerate
CBaseFilter *m_pFilter; // Filter we were created by
IQualityControl *m_pQSink; // Target for Quality messages
LONG m_TypeVersion; // Holds current type version
CMediaType m_mt; // Media type of connection
CRefTime m_tStart; // time from NewSegment call
CRefTime m_tStop; // time from NewSegment
double m_dRate; // rate from NewSegment
其中m_bRunTimeError默认为FALSE,m_pQSink默认为NULL,m_TypeVersion默认为1,m_tStart为空,m_tStop为MAX_TIME,m_bCanReconnectWhenActive和m_bTryMyTypesFirst都为FALSE,m_dRate为1.0。
o Constructor:
CBasePin(
TCHAR *pObjectName, // Object description
CBaseFilter *pFilter, // Owning filter who knows about pins
CCritSec *pLock, // Object who implements the lock
HRESULT *phr, // General OLE return code
LPCWSTR pName, // Pin name for us
PIN_DIRECTION dir); // Either PINDIR_INPUT or PINDIR_OUTPUT
m_pFilter由pFilter初始化,m_pLock由pLock初始化,m_dir由dir初始化。
o Pin之间的链接过程[详细Code讲解见陆其明《DirectShow开发指南》第二章的讲解],通过调用IPin的Connect->AgreeMediaType(CBasePin的Protected函数)->TryMediaTypes(CBasePin的Protected函数)->AttempConnect(CBasePin的Protected函数)。
其中AttempConnect函数会首先调用CheckConnect(CBasePin的Virtual函数),然后调用CheckMediaType(CBasePin的Virtual函数),如果MediaType接受,则调用Receive Pin上的ReceiveConnection(IPin接口函数)函数,如果成功则调用CompleteConnection(CBasePin的virtual函数),否则调用BreakConnect(CBasePin上的virtual函数)。
o CBasePin中的新增加virtual函数和解释以及虚拟代码:
virtual LONG GetMediaTypeVersion();{return m_TypeVersion;}
// switch the pin to active (paused or running) mode not an error to call this if already active,
virtual HRESULT Active(void);{return NOERROR;}
// switch the pin to inactive state - may already be inactive
virtual HRESULT Inactive(void);{ return NOERROR; }
// Notify of Run() from filter,
virtual HRESULT Run(REFERENCE_TIME tStart);{ return NOERROR; }
// check if the pin can support this specific proposed type and forma
virtual HRESULT CheckMediaType(const CMediaType *) PURE; 必须Override
// set the connection to use this format (previously agreed)
virtual HRESULT SetMediaType(const CMediaType *);{ HRESULT hr = m_mt.Set(*pmt);}
// check that the connection is ok before verifying it can be overridden eg to check what interfaces will be supported.
virtual HRESULT CheckConnect(IPin *);
{CBasePin中只检查了Pin的方向和当前方向是否一致}
// Set and release resources required for a connection
virtual HRESULT BreakConnect();{return NOERROR;}
virtual HRESULT CompleteConnect(IPin *pReceivePin); {return NOERROR;}
// returns the preferred formats for a pin
virtual HRESULT GetMediaType(int iPosition,CMediaType *pMediaType); 必须Override
o CBasePin实现IPin的函数
QueryAccept - 直接调用CheckMediaType,并将结果返回
EnumMediaTypes - 通过辅助类CEnumMediaTypes实现MediaType的Enum.
NewSegment – 只是简单设置参数后直接返回NOERROR
Disconnect – 调用函数 DisconnectInternal
Connect/ReceiveConnection – 见上面条目。
其它的简单接口函数 ConnectionMediaType、QueryPinInfo、QueryDirection等略。
o CBasePin中未实现IPin/IQualityControl的函数
直接设置为NOERROR的部分函数:
EndOfStream
直接设置为IMPL错误码的部分函数:
QueryInternalConnections
Notify[IQualityControl接口]
完全没有实现的部分函数:
BeginFlush
EndFlush