DirectShow学习(二)CBasePin类、CBaseOutputPin类和CBaseInputPin类源代码解析(转载)

转载 2007年10月14日 09:51:00
转自http://blog.csdn.net/alvachien/archive/2005/01/10/247220.aspx
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 – 见上面条目。
其它的简单接口函数 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 Pin的Prop.
// 调用 pPin->GetAllocator判断pPin是否以及存在Allocator,
// 否则自己创建并初始化(InitAlloc)并调用 DecideBufferSize 来得到需要的大小
// 调用 pPin->NotifyAllocator让Input 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();
{
分别判断IsStopped、m_bFlushing和m_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_bFlushing为TRUE.}
STDMETHODIMP EndFlush(void);
{
仅仅设置m_bFlushing为FALSE,同时清除m_bRuntimeError。}
HRESULT BreakConnect();
{
// 如果m_pAllocator非空,调用m_pAllocator->Decommit()
// 释放m_pAllocator->Release并置为空
}
virtual HRESULT Inactive(void);
{
//
清理m_bRunTimeError和m_bFlushing,返回m_pAllocator->Decommit().
}
STDMETHODIMP Notify(IBaseFilter * pSender, Quality q);
{这是IQualityControl的接口函数,CBaseInputPin只是简单报错DbgBreak说明未实现}

DirectShow 学习笔记

DirectX(简称:DX)是微软推出的一套基于Windows系统的多媒体应用程式接口APIs函式。在开发中,DX分为两个部分,一个是运行库,通过DX编译出来的程式必须要有运行库的支持,另外一个是开发...
  • shishuo365
  • shishuo365
  • 2015年07月16日 23:11
  • 904

Java类加载机制源码分析

Java代码首先要编译成class文件字节码,在运行时通过JIT(即时编译器)编译成本地机器码,最后由ClassLoader将其加载解析成Class对象到内存中。通过ClassLoader的loadC...
  • Zerohuan
  • Zerohuan
  • 2015年09月27日 00:12
  • 1534

JDK源码学习阅读-Integer类中的parseInt方法分析

原文:JDK源码学习阅读-Integer类中的parseInt方法分析 源代码下载地址:http://www.zuidaima.com/share/1828014883720192.htm ...
  • yaerfeng
  • yaerfeng
  • 2016年08月06日 14:46
  • 1235

机器学习常用算法(1)最小二乘和k-means聚类

最近复习算法准备校招,顺便写一写算作补上以前欠的债。 1.最小二乘法 有一堆数据点(Xi,Yi),其中i从0到n,那么我现在用一个超平面去拟合这些数据点,这个超平面的方程形式?whatever...
  • byplane
  • byplane
  • 2016年08月21日 16:28
  • 720

dom4j 学习 -- 封装dom4j工具类+如何使用dom4j解析

今天项目里面用到dom4j解析xml数据,特地整理了一下封装dom4j的工具方法,使用dom4j来解析xml文档. 首先是封装了dom4j的工具类: package myDOM4J; imp...
  • W3Chhhhhh
  • W3Chhhhhh
  • 2016年12月08日 21:44
  • 1965

对运动类 App 的产品分析

原文地址:http://www.jianshu.com/p/00672d3c0972    近些年随着物质条件的改善,人们越来越重视自己的身体,所以也越来越多的人会进行身体锻炼。同时又由...
  • JoshuaJack290
  • JoshuaJack290
  • 2015年04月01日 23:11
  • 1037

c++中string类的源代码

一:回顾 (1)c++中的string类是在面试中和笔试中经常考的题目; (2)c++中的string类和fstream类合起来是处理外部数据的利器; (3)string类经常用到find find_...
  • u010700335
  • u010700335
  • 2014年11月10日 12:20
  • 6915

XML的文件解析类————比较常用

 /// /// Author: jiangxiaoqiang /// public class XmlReader {   //=====================...
  • luoyanqing119
  • luoyanqing119
  • 2015年12月11日 16:16
  • 1030

[ML]聚类之学习向量量化LVQ

LVQ,Learning Vector Quantization,学习向量量化LVQ需要数据样本带有类别标记,学习过程中需要利用这些监督信息来辅助聚类。 接受代标记的数据集D D和原型向量个数k k...
  • only2cyq
  • only2cyq
  • 2017年04月04日 19:51
  • 2244

jdk类库源码分析-String类

从今天开始研究jdk基础类库的源码,从中学习优秀的设计思想,提高自己的能力。至于怎么查看源码,这里不多说,网上很多教程,直接上干货儿,欢迎大家提出宝贵意见,共同学习,一起进步。(这里我研究的是jdk1...
  • u011915230
  • u011915230
  • 2016年11月14日 23:28
  • 786
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:DirectShow学习(二)CBasePin类、CBaseOutputPin类和CBaseInputPin类源代码解析(转载)
举报原因:
原因补充:

(最多只允许输入30个字)