原创 DirectShow学习(二)CBasePin类、CBaseOutputPin类和CBaseInputPin类源代码解析收藏

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默认为FALSEm_pQSink默认为NULLm_TypeVersion默认为1m_tStart为空,m_tStopMAX_TIMEm_bCanReconnectWhenActivem_bTryMyTypesFirst都为FALSEm_dRate1.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_pFilterpFilter初始化,m_pLockpLock初始化,m_dirdir初始化。

o        Pin之间的链接过程[详细Code讲解见陆其明《DirectShow开发指南》第二章的讲解],通过调用IPinConnect>AgreeMediaType(CBasePinProtected函数)->TryMediaTypes(CBasePinProtected函数)->AttempConnect(CBasePinProtected函数)
其中AttempConnect函数会首先调用CheckConnect(CBasePinVirtual函数),然后调用CheckMediaType(CBasePinVirtual函数),如果MediaType接受,则调用Receive Pin上的ReceiveConnection(IPin接口函数)函数,如果成功则调用CompleteConnection(CBasePinvirtual函数),否则调用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实现MediaTypeEnum.
NewSegment
只是简单设置参数后直接返回NOERROR
Disconnect
调用函数 DisconnectInternal
Connect/ReceiveConnection
见上面条目。
其它的简单接口函数 ConnectionMediaTypeQueryPinInfoQueryDirection等略。

o        CBasePin中未实现IPin/IQualityControl的函数
直接设置为NOERROR的部分函数:
EndOfStream
直接设置为IMPL错误码的部分函数:
QueryInternalConnections
Notify[IQualityControl
接口]
完全没有实现的部分函数:
BeginFlush
EndFlush

4.      CBaseOutputPin [amfilter.h/amfilter.cpp]

o        CBaseOutputPin具体实现伪代码
派生自 CBasePin
变量部分(均初始化为NULL)
IMemAllocator *m_pAllocator; // Memory allocator
IMemInputPin *m_pInputPin;  // interface on the downstreaminput pin

o        新增加的virtual函数:
// negotiate the allocator and its buffer size/count and other properties
// Calls
DecideBufferSize to set properties
virtual HRESULT DecideAllocator(IMemInputPin * pPin, IMemAllocator ** pAlloc);
{
//
调用 pPin->GetAllocatorRequirements. 得到Input PinProp.
//
调用 pPin->GetAllocator判断pPin是否以及存在Allocator
//
否则自己创建并初始化(InitAlloc)并调用 DecideBufferSize 来得到需要的大小
//
调用 pPin->NotifyAllocatorInput Pin得到更新的Allocator
}
// override this to set the buffer size and count. Return an error
virtual HRESULT DecideBufferSize(
    IMemAllocator * pAlloc,
    ALLOCATOR_PROPERTIES * ppropInputRequest
) PURE;
// returns an empty sample buffer from the allocator
virtual HRESULT GetDeliveryBuffer(IMediaSample ** ppSample,
                                  REFERENCE_TIME * pStartTime,
                                  REFERENCE_TIME * pEndTime,
                                  DWORD dwFlags);
{
调用 m_pAllocator->GetBuffer(…) }
// deliver a filled-in sample to the connected input pin
// note - you need to release it after calling this. The receiving
virtual HRESULT Deliver(IMediaSample *);{ m_pInputPin->Receive(pSample); }
// override this to control the connection
virtual HRESULT InitAllocator(IMemAllocator **ppAlloc);{ CreateMemoryAllocator(ppAlloc); }
// called from elsewhere in our filter to pass EOS downstream to our connected input pin
virtual HRESULT DeliverEndOfStream(void);{ m_Connected->EndOfStream(); }
virtual HRESULT DeliverBeginFlush(void);{ m_Connected->BeginFlush(); }
virtual HRESULT DeliverEndFlush(void);{ m_Connected->EndFlush(); }
virtual HRESULT DeliverNewSegment(
                    REFERENCE_TIME tStart,
                    REFERENCE_TIME tStop,
                    double dRate);{ m_Connected->NewSegment(…);}

o        继承的virtual函数或者IPin接口函数:
// Complete connection
virtual HRESULT CompleteConnect(IPin *pReceivePin); { DecideAllocator() }
// Check connection
HRESULT CheckConnect(IPin *pPin);
{
增加检查输入Pin是否支持IMemInputPin接口,m_pInputPin在这里赋值}
// Break connection
HRESULT BreakConnect();
{
//
调用m_pAllocator->Decommit()释放m_pAllocator并置为空,
//
释放m_pInputPin并置为空
}
HRESULT Active(void);{ m_pAllocator->Commit(); }
HRESULT Inactive(void); { m_pAllocator->Decommit();}
以下三个函数直接返回E_UNEXPECTED
STDMETHODIMP EndOfStream(void);
STDMETHODIMP BeginFlush(void);
STDMETHODIMP EndFlush(void);

5.      IMemInputPin接口函数:
IMemInputPin : public IUnknown
{

     // Retrieves the memory allocator proposed by this pin.
     virtual HRESULT STDMETHODCALLTYPE GetAllocator(
         /* [out] */ IMemAllocator **ppAllocator) = 0;
     // Specifies an allocator for the connection.
    
virtual HRESULT STDMETHODCALLTYPE NotifyAllocator(
         /* [in] */ IMemAllocator *pAllocator,
         /* [in] */ BOOL bReadOnly) = 0;
     // Retrieves allocator properties that are requested by the input pin.
    
virtual HRESULT STDMETHODCALLTYPE GetAllocatorRequirements(
         /* [out] */ ALLOCATOR_PROPERTIES *pProps) = 0;
     // Receives the next media sample in the stream.
    
virtual HRESULT STDMETHODCALLTYPE Receive(
         /* [in] */ IMediaSample *pSample) = 0;
     // Receives multiple samples in the stream.
    
virtual HRESULT STDMETHODCALLTYPE ReceiveMultiple(
         /* [size_is][in] */ IMediaSample **pSamples,
         /* [in] */ long nSamples,
         /* [out] */ long *nSamplesProcessed) = 0;
     // Determines whether calls to the Recive method might block.
    
virtual HRESULT STDMETHODCALLTYPE ReceiveCanBlock( void) = 0;
}

6.      CBaseInputPin[amfilter.h/amfilter.cpp]

o        CBaseInputPin具体实现伪代码:
派生自 CBasePin, IMemInputPin
变量部分:
IMemAllocator *m_pAllocator;    // Default memory allocator
// Allocator is read only or not

BYTE m_bReadOnly;
// in flushing state (between BeginFlush and EndFlush)
// if TRUE, all Receives are returned with S_FALSE

BYTE m_bFlushing;
// Sample properties - initalized in Receive
AM_SAMPLE2_PROPERTIES m_SampleProps;
INonDelegationUnknown
的接口函数:
//
重写该函数是为了支持IMemInputPin接口
STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, void **ppv);
具体实现函数:
HRESULT PassNotify(Quality& q);
{
//
如果m_pQSink不为空,直接调用m_pQSink->Notify(…)
//
否则查询Connect Pin上的IQualityControl借口,对其调用Notify(…)
}

o        新增的virtual函数
//  Override this for checking whether it's OK to process samples
//  Also call this from EndOfStream.
virtual HRESULT CheckStreaming();
{
分别判断IsStoppedm_bFlushingm_bRunTimeError }

o        IMemInputPin接口函数:
// return the allocator interface that this input pin
// would like the output pin to use
STDMETHODIMP GetAllocator(IMemAllocator ** ppAllocator);
{
//
如果m_pAllocator为空,则CreateMemoryAllocator
//
调用m_pAllocator->AddRef,返回m_pAllocator
}
// tell the input pin which allocator the output pin is actually going to use.
STDMETHODIMP NotifyAllocator(
                IMemAllocator * pAllocator,
                BOOL bReadOnly);
{
//
释放当前m_pAllocator,设置m_pAllocator = pAllocator
//
调用m_pAllocator->AddRef
}
// do something with this media sample
STDMETHODIMP Receive(IMediaSample *pSample);
{
//
首先调用CheckStreaming
//
得出pSample的属性,即填充成员m_SampleProps
//
如果Sample属性未发生变化(!(m_SampleProps.dwSampleFlags & AM_SAMPLE_TYPECHANGED))
// 则直接返回NOERROR,否则调用CheckMediaType检查是否接受新的MediaType,如果接受
//
返回NOERROR,否则调用EndOfStream,设置RuntimeError,并通知Filter
// m_pFilter->NotifyEvent(EC_ERRORABORT,VFW_E_TYPE_NOT_ACCEPTED,0);
}
// do something with these media samples
STDMETHODIMP ReceiveMultiple (
    IMediaSample **pSamples,
    long nSamples,
    long *nSamplesProcessed);
{
//
对每个Sample分别调用Receive函数。
}
// See if Receive() blocks
STDMETHODIMP ReceiveCanBlock();
{
//
如果当前Filter上没有Output Pin,则返回S_OK
//
否则遍历当前Filter上每个Output Pin,得出它们的Connected Input Pin,判断这些
// Connected Input Pin
是否支持Block,只要有一个支持,则为S_OK
//
以上条件全不满足时,返回S_FALSE
}
// default implementation returns E_NOTIMPL. Override if you have
// specific alignment or prefix needs, but could use an upstream allocator
STDMETHODIMP GetAllocatorRequirements(ALLOCATOR_PROPERTIES*pProps);{E_IMPL}

o        继承的virtual函数实现
STDMETHODIMP BeginFlush(void);
{
仅仅设置m_bFlushingTRUE.}
STDMETHODIMP EndFlush(void);
{
仅仅设置m_bFlushingFALSE,同时清除m_bRuntimeError}
HRESULT BreakConnect();
{
//
如果m_pAllocator非空,调用m_pAllocator->Decommit()
//
释放m_pAllocator->Release并置为空
}
virtual HRESULT Inactive(void);
{
//
清理m_bRunTimeErrorm_bFlushing,返回m_pAllocator->Decommit().
}
STDMETHODIMP Notify(IBaseFilter * pSender, Quality q);
{
这是IQualityControl的接口函数,CBaseInputPin只是简单报错DbgBreak说明未实现}


前一篇:(一)COM实现部分和部分辅助源码浅读

发表于 @ 2005年01月10日 15:37:00|评论(loading...)|收藏

新一篇: DirectShow 学习(三) CBaseFilter类源代码解析 | 旧一篇: DirectShow 学习(一) COM实现部分和部分辅助源码浅读

用户操作
[即时聊天] [发私信] [加为好友]
Alva Chien
订阅我的博客
XML聚合  FeedSky
Alva Chien的公告
You will go through tough times, it's about coming through that.
- Adidas advertisement

Skills:
C# (.Net Platform)
C++(MFC/STL/COM)
T-SQL(SQL Server 2000+)
ABAP(SAP Platform)
Leave your comment: Here
www.flickr.com
This is a Flickr badge showing public photos from Alva Chien. Make your own badge here.
文章分类
收藏
    Alva Chien's Websites
    Alva Chien's Photos
    Write Time Down, Aligning With Heart - an Alva Chien's Blog
    IT名人堂
    Charles Petzold's Personal Website (Author of [Programming Windows])
    Martin Fowler's Personal WebSite (Author of [Refactor])
    潘爱民的专栏 (个人非常尊敬的一位大师,他翻的书让我可以不读原版, 现已加盟Microsoft)
    芮祥麟的专栏(SAP Labs China的老大)
    MFC/.Net网站荟萃
    CodeGuru
    CodeProject
    GotDotNet - The Microsoft .NET Framework Community
    MSDN
    SQL Server Compact Edition
    The Official Microsoft ASP.Net Site
    The Synchronizer
    WindowsClient.net: Windows Forms, Windows Presentation Foundation
    顶尖IT公司
    Accenture
    BearingPoint Inc.
    HP
    IBM
    Intel
    Microsoft Corp.
    SAP AG
    中国著名大学
    上海交通大学
    中国科学技术大学
    北京大学
    南京大学
    南开大学
    同济大学
    复旦大学
    浙江大学
    清华大学
    存档
    Csdn Blog version 3.1a
    Copyright © Alva Chien