分享
 
 
 

DirectShow 学习(六) CTransfromFilter及相关联Pin类的源代码解析

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

DirectShow 学习(六): CTransfromFilter及相关联Pin类的源代码解析

1. CTransformInputPin类

派生自CBaseInputPin。

a) 成员变量

CTransformFilter *m_pTransformFilter;

b) IPin的接口函数:

STDMETHODIMP QueryId(LPWSTR * Id){ return AMGetWideString(L"In", Id); }

// provide EndOfStream that passes straight downstream

STDMETHODIMP EndOfStream(void);

{

CAutoLock lck(&m_pTransformFilter->m_csReceive);

HRESULT hr = CheckStreaming();

if (S_OK == hr) {

hr = m_pTransformFilter->EndOfStream();}

return hr;

}

// passes it to CTransformFilter::BeginFlush

STDMETHODIMP BeginFlush(void);

{

CAutoLock lck(&m_pTransformFilter->m_csFilter);

if (!IsConnected() ||

!m_pTransformFilter->m_pOutput->IsConnected()) {

return VFW_E_NOT_CONNECTED;}

HRESULT hr = CBaseInputPin::BeginFlush();

return m_pTransformFilter->BeginFlush();

}

// passes it to CTransformFilter::EndFlush

STDMETHODIMP EndFlush(void);

{

CAutoLock lck(&m_pTransformFilter->m_csFilter);

if (!IsConnected() ||

!m_pTransformFilter->m_pOutput->IsConnected()) {

return VFW_E_NOT_CONNECTED;}

HRESULT hr = m_pTransformFilter->EndFlush();

return CBaseInputPin::EndFlush();

}

STDMETHODIMP NewSegment(

REFERENCE_TIME tStart,

REFERENCE_TIME tStop,

double dRate);

{

// Save the values in the pin

CBasePin::NewSegment(tStart, tStop, dRate);

return m_pTransformFilter->NewSegment(tStart, tStop, dRate);

}

c) IMemInputPin的接口函数

// here's the next block of data from the stream.

// AddRef it yourself if you need to hold it beyond the end

// of this call.

STDMETHODIMP Receive(IMediaSample * pSample);

{

CAutoLock lck(&m_pTransformFilter->m_csReceive);

// check all is well with the base class

hr = CBaseInputPin::Receive(pSample);

if (S_OK == hr) { hr = m_pTransformFilter->Receive(pSample);}

return hr;

}

d) 从CBasePin和CBaseInputPin继承的函数:

HRESULT CheckConnect(IPin *pPin);

{

HRESULT hr = m_pTransformFilter->CheckConnect(PINDIR_INPUT,pPin);

return CBaseInputPin::CheckConnect(pPin);

}

HRESULT

BreakConnect();

{

m_pTransformFilter->

BreakConnect(PINDIR_INPUT);

return CBaseInputPin::

BreakConnect();

}

HRESULT CompleteConnect(IPin *pReceivePin);

{

HRESULT hr = m_pTransformFilter->CompleteConnect(PINDIR_INPUT,pReceivePin);

return CBaseInputPin::CompleteConnect(pReceivePin);

}

HRESULT CheckMediaType(const CMediaType* mtIn);

{

HRESULT hr = m_pTransformFilter->CheckInputType(pmt);

// if the output pin is still connected, then we have

// to check the transform not just the input format

if ((m_pTransformFilter->m_pOutput != NULL) &&

(m_pTransformFilter->m_pOutput->IsConnected())) {

return m_pTransformFilter->CheckTransform(

pmt,

&m_pTransformFilter->m_pOutput->CurrentMediaType());

} else {return hr;}

}

// set the connection media type

HRESULT SetMediaType(const CMediaType* mt);

{

// Set the base class media type (should always succeed)

HRESULT hr = CBasePin::SetMediaType(mtIn);

// check the transform can be done (should always succeed)

ASSERT(SUCCEEDED(m_pTransformFilter->CheckInputType(mtIn)));

return m_pTransformFilter->SetMediaType(PINDIR_INPUT,mtIn);

}

// Check if it's OK to process samples

virtual HRESULT CheckStreaming();

{

// 类似于CBaseInputPin的CheckStreaming函数,只是增加了先检查

// Transform Filter的Output Pin是否连接

}

2. CTransformOutputPin类

派生自CBaseOutputPin。

a) 成员变量:

CTransformFilter *m_pTransformFilter;

// implement IMediaPosition by passing upstream

IUnknown * m_pPosition;

b) NonDelegatingQueryInterface函数

STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, void **ppv)

{

if (riid == IID_IMediaPosition || riid == IID_IMediaSeeking) {

// we should have an input pin by now

if (m_pPosition == NULL) {

HRESULT hr = CreatePosPassThru(

GetOwner(),FALSE, (IPin *)m_pTransformFilter->m_pInput, &m_pPosition);

return m_pPosition->QueryInterface(riid, ppv);

} else {

return CBaseOutputPin::NonDelegatingQueryInterface(riid, ppv);}

}

STDAPI CreatePosPassThru(LPUNKNOWN pAgg, BOOL

bRenderer, IPin *pPin,

IUnknown **ppPassThru )

{

HRESULT hr = CoCreateInstance(CLSID_SeekingPassThru,

pAgg, CLSCTX_INPROC_SERVER, IID_IUnknown, (void **)&pUnkSeek );

ISeekingPassThru *pPassThru;

hr = pUnkSeek->QueryInterface(IID_ISeekingPassThru, (void**)&pPassThru);

hr = pPassThru->Init(

bRenderer, pPin);

pPassThru->Release();

*ppPassThru = pUnkSeek;

}

c) IPin的接口函数

STDMETHODIMP QueryId(LPWSTR * Id){ return AMGetWideString(L"Out", Id);}

d) IQualityControl的接口函数

STDMETHODIMP Notify(IBaseFilter * pSender, Quality q);

{

// First see if we want to handle this ourselves

HRESULT hr = m_pTransformFilter->AlterQuality(q);

if (hr!=S_FALSE) { return hr; // either S_OK or a failure }

return m_pTransformFilter->m_pInput->PassNotify(q);

}

e) 从CBasePin和CBaseInputPin继承的函数:

HRESULT CheckConnect(IPin *pPin);

{

if ((m_pTransformFilter->m_pInput->IsConnected() == FALSE)) {

return E_UNEXPECTED;

}

HRESULT hr = m_pTransformFilter->CheckConnect(PINDIR_OUTPUT,pPin);

return CBaseOutputPin::CheckConnect(pPin);

}

HRESULT

BreakConnect();

{

m_pTransformFilter->

BreakConnect(PINDIR_OUTPUT);

return CBaseOutputPin::

BreakConnect();

}

HRESULT CompleteConnect(IPin *pReceivePin);

{

HRESULT hr = m_pTransformFilter->CompleteConnect(PINDIR_OUTPUT,pReceivePin);

return CBaseOutputPin::CompleteConnect(pReceivePin);

}

// check that we can support this output type

HRESULT CheckMediaType(const CMediaType* mtOut);

{

if ((m_pTransformFilter->m_pInput->IsConnected() == FALSE))

{ return E_INVALIDARG;}

return m_pTransformFilter->CheckTransform(

&m_pTransformFilter->m_pInput->CurrentMediaType(),pmtOut);

}

// set the connection media type, called after we have agreed a media type to

// actually set it in which case we run the CheckTransform function to get the

// output format type again

HRESULT SetMediaType(const CMediaType *pmt);

{

hr = CBasePin::SetMediaType(pmtOut);

return m_pTransformFilter->SetMediaType(PINDIR_OUTPUT,pmtOut);

}

// called from CBaseOutputPin during connection to ask for

// the count and size of buffers we need.

HRESULT DecideBufferSize(

IMemAllocator * pAlloc,

ALLOCATOR_PROPERTIES *pProp);

{

return m_pTransformFilter->DecideBufferSize(pAllocator, pProp);

}

// returns the preferred formats for a pin

HRESULT GetMediaType(int iPosition,CMediaType *pMediaType);

{

if (m_pTransformFilter->m_pInput->IsConnected()) {

return m_pTransformFilter->GetMediaType(iPosition,pMediaType);

} else {

return VFW_S_NO_MORE_ITEMS;

}

}

3. CTransformFilter类

派生自CBaseFilter

a) 成员变量

BOOL m_bEOSDelivered; // have we sent EndOfStream

BOOL m_bSampleSkipped; // Did we just skip a frame

BOOL m_bQualityChanged; // Have we degraded?

// critical section protecting filter state.

CCritSec m_csFilter;

// critical section stopping state changes (ie Stop) while we're

// processing a sample. This critical section is held when processing

// events that occur on the receive thread - Receive() and EndOfStream().

// If you want to hold both m_csReceive and m_csFilter then grab

// m_csFilter FIRST - like CTransformFilter::Stop() does.

CCritSec m_csReceive;

// these hold our input and output pins

CTransformInputPin *m_pInput;

CTransformOutputPin *m_pOutput;

b) 新增的virtual 函数:

// Transform,必须override

virtual HRESULT Transform(IMediaSample * pIn, IMediaSample *pOut);

// check if you can support mtIn,必须override

virtual HRESULT CheckInputType(const CMediaType* mtIn) PURE;

// check if you can support the transform from this input to this output,必须override

virtual HRESULT CheckTransform(const CMediaType* mtIn, const CMediaType* mtOut) PURE;

// call the SetProperties function with appropriate arguments,必须override

virtual HRESULT DecideBufferSize(

IMemAllocator * pAllocator,

ALLOCATOR_PROPERTIES *pprop) PURE;

// override to suggest OUTPUT pin media types,必须override

virtual HRESULT GetMediaType(int iPosition, CMediaType *pMediaType) PURE;

// you can also override these if you want to know about streaming

virtual HRESULT StartStreaming();{return NOERROR; }

virtual HRESULT StopStreaming();{return NOERROR;}

// override if you can do anything constructive with quality notifications

virtual HRESULT AlterQuality(Quality q);

{

// Return S_FALSE to mean "pass the note on upstream"

// Return NOERROR (Same as S_OK)

// to mean "I've done something about it, don't pass it on"

return S_FALSE;

}

// override this to know when the media type is actually set

virtual HRESULT SetMediaType(PIN_DIRECTION direction,const CMediaType *pmt);

{ return NOERROR;}

// chance to grab extra interfaces on connection

virtual HRESULT CheckConnect(PIN_DIRECTION dir,IPin *pPin);{ return NOERROR;}

virtual HRESULT

BreakConnect(PIN_DIRECTION dir);{ return NOERROR;}

virtual HRESULT CompleteConnect(PIN_DIRECTION direction,IPin *pReceivePin);

{ return NOERROR;}

// chance to customize the transform process

virtual HRESULT Receive(IMediaSample *pSample);

{

/* Check for other streams and pass them on */

AM_SAMPLE2_PROPERTIES * const pProps = m_pInput->SampleProps();

if (pProps->dwStreamId != AM_STREAM_MEDIA) {

return m_pOutput->m_pInputPin->Receive(pSample);

}

IMediaSample * pOutSample;

// Set up the output sample

hr = InitializeOutputSample(pSample, &pOutSample);

// have the derived class transform the data

hr = Transform(pSample, pOutSample);

// the Transform() function can return S_FALSE to indicate that the

// sample should not be delivered; we only deliver the sample if it's

// really S_OK (same as NOERROR, of course.)

if (hr == NOERROR) {

hr = m_pOutput->m_pInputPin->Receive(pOutSample);

m_bSampleSkipped = FALSE; // last thing no longer dropped

} else {

// S_FALSE returned from Transform is a PRIVATE agreement

// We should return NOERROR from Receive() in this cause because

// returning S_FALSE from Receive() means that this is the end of

// the stream and no more data should be sent.

if (S_FALSE == hr) {

// Release the sample before calling notify to avoid

// deadlocks if the sample holds a lock on the system

// such as DirectDraw buffers do

pOutSample->Release();

m_bSampleSkipped = TRUE;

if (!m_bQualityChanged) {

NotifyEvent(EC_QUALITY_CHANGE,0,0);

m_bQualityChanged = TRUE;

}

return NOERROR;

}

}

pOutSample->Release();

}

// if you override Receive, you may need to override these three too

virtual HRESULT EndOfStream(void);

{

hr = m_pOutput->DeliverEndOfStream();

}

virtual HRESULT BeginFlush(void);

{

hr = m_pOutput->DeliverBeginFlush();

}

virtual HRESULT EndFlush(void);

{

return m_pOutput->DeliverEndFlush();

}

virtual HRESULT NewSegment(

REFERENCE_TIME tStart,

REFERENCE_TIME tStop,

double dRate);

{

return m_pOutput->DeliverNewSegment(tStart, tStop, dRate);

}

c) 继承CBaseFilter的函数:

virtual int GetPinCount();{return 2; }

virtual CBasePin * GetPin(int n);

{

// Create an input pin if necessary

if (m_pInput == NULL) {

m_pInput = new CTransformInputPin(NAME("Transform input pin"),

this, // Owner filter

&hr, // Result code

L"XForm In"); // Pin name

m_pOutput = (CTransformOutputPin *)

new CTransformOutputPin(NAME("Transform output pin"),

this, // Owner filter

&hr, // Result code

L"XForm Out"); // Pin name

}

// Return the appropriate pin

if (n == 0) { return m_pInput;}

else if (n == 1) { return m_pOutput;}

else { return NULL;}

}

STDMETHODIMP FindPin(LPCWSTR Id, IPin **ppPin);

{

if (0==lstrcmpW(Id,L"In")) { *ppPin = GetPin(0);}

else if (0==lstrcmpW(Id,L"Out")) { *ppPin = GetPin(1); }

if (*ppPin) { (*ppPin)->AddRef();}

}

STDMETHODIMP Stop();

{

CAutoLock lck1(&m_csFilter);

if (m_State == State_Stopped) { return NOERROR; }

if (m_pInput == NULL || m_pInput->IsConnected() == FALSE ||

m_pOutput->IsConnected() == FALSE) {

m_State = State_Stopped;

m_bEOSDelivered = FALSE;

return NOERROR;

}

// decommit the input pin before locking or we can deadlock

m_pInput->Inactive();

// synchronize with Receive calls

CAutoLock lck2(&m_csReceive);

m_pOutput->Inactive();

// allow a class derived from CTransformFilter

// to know about starting and stopping streaming

HRESULT hr = StopStreaming();

if (SUCCEEDED(hr)) {

// complete the state transition

m_State = State_Stopped;

m_bEOSDelivered = FALSE;

}

}

STDMETHODIMP Pause();

{

CAutoLock lck(&m_csFilter);

if (m_State == State_Paused) {}

else if (m_pInput == NULL || m_pInput->IsConnected() == FALSE) {

if (m_pOutput && m_bEOSDelivered == FALSE) {

m_pOutput->DeliverEndOfStream();

m_bEOSDelivered = TRUE;

}

m_State = State_Paused; }

else if (m_pOutput->IsConnected() == FALSE) {

m_State = State_Paused;}

else {

if (m_State == State_Stopped) {

CAutoLock lck2(&m_csReceive);

hr = StartStreaming();}

if (SUCCEEDED(hr)) { hr = CBaseFilter::Pause();}

}

m_bSampleSkipped = FALSE;

m_bQualityChanged = FALSE;

}

d) 其他函数

// Standard setup for output sample

HRESULT InitializeOutputSample(IMediaSample *pSample, IMediaSample **ppOutSample);

{

IMediaSample *pOutSample;

AM_SAMPLE2_PROPERTIES * const pProps = m_pInput->SampleProps();

DWORD dwFlags = m_bSampleSkipped ? AM_GBF_PREVFRAMESKIPPED : 0;

if (!(pProps->dwSampleFlags & AM_SAMPLE_SPLICEPOINT)) {

dwFlags |= AM_GBF_NOTASYNCPOINT; }

HRESULT hr = m_pOutput->m_pAllocator->GetBuffer(

&pOutSample

, pProps->dwSampleFlags & AM_SAMPLE_TIMEVALID ? &pProps->tStart : NULL

, pProps->dwSampleFlags & AM_SAMPLE_STOPVALID ? &pProps->tStop : NULL

, dwFlags

);

*ppOutSample = pOutSample;

// 如果支持IMediaSample2接口,则调用该接口来设置属性,否则调用IMediaSample来设置

}

前一篇:学习(五) CSource类和其一个具体实现例子的源代码分析

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
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- 王朝網路 版權所有