Filter的连接
Filter上的连接其实就是Filter上Pin的连接,而Pin上的连接其实就是OutputPin于InputPin它们俩之间商量着怎么采用连接时媒体类型的问题。这是一个协商的过程。(为了我们能够学好,学通DirectShow)下面我们来分析一下SDK基类的源代码。
在分析SDK基类的源代码之前让我们来看看一下实际连接的过程。
注意:Pin也是一种COM接口,那么怎么让它工作呢,呵呵前辈已经为我们做好了,每个Pin上现在都实现了IPin接口,我们就可以象一个平常的类指针一样调用它了。
好了,大家来看看连接的大体步骤:
1. Filter Graph Manager 调用输出Pin上的IPin::Cinnect
2. 如果输出的那边同意,那Filter Graph Manager就调用输入的IPin::ReceiveConnection
3. 如果输入的也同意那么连接就成功了.
总结一下: Filter Graph Manager就是中介,而输入,输出IPin就是一个租房子,一个找房子.中介结合双方的意见,调节.看看能不能达成共识.它赚得中介费.其实就这样!
STDMETHODIMP CBasePin::Connect(IPin * pReceivePin,const AM_MEDIA_TYPE *pmt ) { CheckPointer(pReceivePin,E_POINTER);//检查合法性信息 ValidateReadPtr(pReceivePin,sizeof(IPin)); CAutoLock cObjectLock(m_pLock); DisplayPinInfo(pReceivePin); if (m_Connected) {//如果已经连接了,返回已经连接标记 DbgLog((LOG_TRACE, CONNECT_TRACE_LEVEL, TEXT("Already connected"))); return VFW_E_ALREADY_CONNECTED; } //注意你只有停止的状态才可以进行连接 if (!IsStopped() && !m_bCanReconnectWhenActive) { return VFW_E_NOT_STOPPED; } //ptype指针指向传入的类型 const CMediaType * ptype = (CMediaType*)pmt; HRESULT hr = AgreeMediaType(pReceivePin, ptype);//注意AgreeMediaType函数 if (FAILED(hr)) { DbgLog((LOG_TRACE, CONNECT_TRACE_LEVEL, TEXT("Failed to agree type"))); EXECUTE_ASSERT( SUCCEEDED( BreakConnect() ) ); return hr; } DbgLog((LOG_TRACE, CONNECT_TRACE_LEVEL, TEXT("Connection succeeded"))); return NOERROR; }
HRESULT CBasePin::AgreeMediaType(IPin *pReceivePin, const CMediaType *pmt) { ASSERT(pReceivePin);//断言表达式 IEnumMediaTypes *pEnumMediaTypes = NULL;//媒体类型 // 看看媒体类型是不是完全指定的 (例如我想要好房子) if ( (pmt != NULL) && (!pmt->IsPartiallySpecified())) { //是的话就尝试连接,不行就放弃了 (有的话就租到了) return AttemptConnection(pReceivePin, pmt); } //试试别的类型?找间房子真不容易 HRESULT hrFailure = VFW_E_NO_ACCEPTABLE_TYPES; for (int i = 0; i < 2; i++) { HRESULT hr; //成员变量m_bTryMyTypesFirst初始为FALSE if (i = = (int)m_bTryMyTypesFirst) { //注意看下面的代码为了尝试输出媒体类型的试连接 hr = pReceivePin->EnumMediaTypes(&pEnumMediaTypes); } else { //注意看下面的代码为了尝试输入媒体类型的试连接 hr = EnumMediaTypes(&pEnumMediaTypes); } if (SUCCEEDED(hr)) { ASSERT(pEnumMediaTypes);//真正的试连接 hr = TryMediaTypes(pReceivePin,pmt,pEnumMediaTypes); pEnumMediaTypes->Release(); if (SUCCEEDED(hr)) { return NOERROR;//连接成功了heihie J } else { // 连接不成功返回错误 if ((hr != E_FAIL) && (hr != E_INVALIDARG) && (hr != VFW_E_TYPE_NOT_ACCEPTED)) { hrFailure = hr; } } } } return hrFailure; }