分享
 
 
 

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

王朝other·作者佚名  2006-01-09
窄屏简体版  字體: |||超大  

预备知识 CMediaType[mtype.h/mtype.cpp]

CMediaType从_AMMediaType继承,是一个在DirectShow中非常有用的Helper Class。它提供了一些常用的辅助函数来操作AMMediaType结构。另外,还提供了几个很常用的全局函数CreateMediaType、DeleteMediaType、CopyMediaType和FreeMediaType以及CreateAudioMediaType。

CBasePin类[amfilter.h/amfilter.cpp]

BasePin继承了接口IPin, 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;

};

CBasePin同时继承了接口IQualityControl, 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;

};

CBasePin类的具体实现伪代码

派生自 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。

构造函数部分:

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

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函数)。

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);

// returns the preferred formats for a pin

virtual HRESULT GetMediaType(int iPosition,CMediaType *pMediaType); 必须Override

CBasePin实现IPin的函数

QueryAccept - 直接调用CheckMediaType,并将结果返回

EnumMediaTypes - 通过辅助类CEnumMediaTypes实现MediaType的Enum.

NewSegment – 只是简单设置参数后直接返回NOERROR

Disconnect – 调用函数 DisconnectInternal

Connect/ReceiveConnection – 见上面条目。

其它的简单接口函数 ConnectionMediaType、QueryPinInfo、QueryDirection等。

CBasePin中未实现IPin/IQualityControl的函数

直接设置为NOERROR的部分函数:

EndOfStream

直接设置为IMPL错误码的部分函数:

QueryInternalConnections

Notify[IQualityControl接口]

完全没有实现的部分函数:

BeginFlush

EndFlush

CBaseOutputPin 类[amfilter.h/amfilter.cpp]

CBaseOutputPin具体实现伪代码

派生自 CBasePin

变量部分(均初始化为NULL):

IMemAllocator *m_pAllocator; // Memory allocator

IMemInputPin *m_pInputPin; // interface on the downstreaminput pin

新增加的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(…);}

继承的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);

IMemInput接口函数:

// 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;

CBaseInputPin类[amfilter.h/amfilter.cpp]

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(…)

}

新增的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 }

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}

继承的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说明未实现}

学习三将侧重于Filter的代码分析

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有