分享
 
 
 

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

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

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

1. CTransInPlaceInputPin类[transip.h/transip.cpp]

派生自CTransformInputPin。

a) 成员变量:

CTransInPlaceFilter * const m_pTIPFilter; // our filter

BOOL m_bReadOnly; // incoming stream is read only

m_bReadOnly初始化为FALSE。

b) IMemInputPin接口函数

// Return our upstream allocator

// If the downstream filter has one then offer that (even if our own output pin is not using it yet.

// If the upstream filter chooses it then we will tell our output pin to ReceiveAllocator).

// Else if our output pin is using an allocator then offer that.

// ( This could mean offering the upstream filter his own allocator, it could mean offerring our own

// ) or it could mean offering the one from downstream

// Else fail to offer any allocator at all.

STDMETHODIMP GetAllocator(IMemAllocator ** ppAllocator);

{

CAutoLock cObjectLock(m_pLock);

if ( m_pTIPFilter->m_pOutput->IsConnected() ) {

// Store the allocator we got

hr = m_pTIPFilter->OutputPin()->ConnectedIMemInputPin()

->GetAllocator( ppAllocator );

if (SUCCEEDED(hr))

{ m_pTIPFilter->OutputPin()->SetAllocator( *ppAllocator ); }

}

else {hr = CTransformInputPin::GetAllocator( ppAllocator );}

}

// get told which allocator the upstream output pin is actually going to use.

STDMETHODIMP NotifyAllocator(IMemAllocator * pAllocator, BOOL

bReadOnly);

{

CAutoLock cObjectLock(m_pLock);

m_bReadOnly =

bReadOnly;

// If we modify data then don't accept the allocator if it's the same as the output pin's allocator

// If our output is not connected just accept the allocator

// We're never going to use this allocator because when our

// output pin is connected we'll reconnect this pin

if (!m_pTIPFilter->OutputPin()->IsConnected()) {

return CTransformInputPin::NotifyAllocator(pAllocator,

bReadOnly);}

// If the allocator is read-only and we're modifying data

// and the allocator is the same as the output pin's then reject

if (

bReadOnly && m_pTIPFilter->m_bModifiesData) {

IMemAllocator *pOutputAllocator =

m_pTIPFilter->OutputPin()->PeekAllocator();

// Make sure we have an output allocator

if (pOutputAllocator == NULL) {

hr = m_pTIPFilter->OutputPin()->ConnectedIMemInputPin()->

GetAllocator(&pOutputAllocator);

if(FAILED(hr)) {hr = CreateMemoryAllocator(&pOutputAllocator);}

if (SUCCEEDED(hr)) {

m_pTIPFilter->OutputPin()->SetAllocator(pOutputAllocator);

pOutputAllocator->Release(); }

}

if (pAllocator == pOutputAllocator) {hr = E_FAIL;}

else if(SUCCEEDED(hr)) {

// Must copy so set the allocator properties on the output

ALLOCATOR_PROPERTIES Props, Actual;

hr = pAllocator->GetProperties(&Props);

if (SUCCEEDED(hr)) {

hr = pOutputAllocator->SetProperties(&Props, &Actual);}

if (SUCCEEDED(hr)) {

if ( (Props.cBuffers > Actual.cBuffers)

|| (Props.cbBuffer > Actual.cbBuffer)

|| (Props.cbAlign > Actual.cbAlign)

) {hr = E_FAIL;}

}

// Set the allocator on the output pin

if (SUCCEEDED(hr)) {

hr = m_pTIPFilter->OutputPin()->ConnectedIMemInputPin()

->NotifyAllocator( pOutputAllocator, FALSE ); }

}

} else {

hr = m_pTIPFilter->OutputPin()->ConnectedIMemInputPin()

->NotifyAllocator( pAllocator,

bReadOnly );

if (SUCCEEDED(hr)) {

m_pTIPFilter->OutputPin()->SetAllocator( pAllocator );}

}

if (SUCCEEDED(hr)) {

// It's possible that the old and the new are the same thing.

// AddRef before release ensures that we don't unload it.

pAllocator->AddRef();

if( m_pAllocator != NULL ) m_pAllocator->Release();

m_pAllocator = pAllocator; // We have an allocator for the input pin

}

}

// Pass this on downstream if it ever gets called.

STDMETHODIMP GetAllocatorRequirements(ALLOCATOR_PROPERTIES *pProps);

{

if( m_pTIPFilter->m_pOutput->IsConnected() )

return m_pTIPFilter->OutputPin()

->ConnectedIMemInputPin()->GetAllocatorRequirements( pProps );

else return E_NOTIMPL;

}

c) IPin接口函数以及CBasePin、CBaseInputPin继承函数

// Provide an enumerator for media types by getting one from downstream

STDMETHODIMP EnumMediaTypes( IEnumMediaTypes **ppEnum );

{

// Can only pass through if connected

if( !m_pTIPFilter->m_pOutput->IsConnected() )

return VFW_E_NOT_CONNECTED;

return m_pTIPFilter->m_pOutput->GetConnected()->EnumMediaTypes( ppEnum );

}

// Say whether media type is acceptable. - agree to anything if not connected,

// otherwise pass through to the downstream filter.

// This assumes that the filter does not change the media type.

HRESULT CheckMediaType(const CMediaType* pmt);

{

HRESULT hr = m_pTIPFilter->CheckInputType(pmt);

if( m_pTIPFilter->m_pOutput->IsConnected() )

return m_pTIPFilter->m_pOutput->GetConnected()->QueryAccept( pmt );

else return S_OK;

}

HRESULT CompleteConnect(IPin *pReceivePin);

{

HRESULT hr = CBaseInputPin::CompleteConnect(pReceivePin);

return m_pTransformFilter->CompleteConnect(PINDIR_INPUT,pReceivePin);

}

d) 其他函数

// Allow the filter to see what allocator we have N.B. This does NOT AddRef

IMemAllocator * PeekAllocator() const{ return m_pAllocator; }

inline const BOOL ReadOnly() { return m_bReadOnly ; }

2. CTransInPlaceOutputPin类[transip.h/transip.cpp]

a) 成员变量

CTransInPlaceFilter * const m_pTIPFilter;

b) IPin接口函数,CBaseOutputPin函数

// Provide a media type enumerator. Get it from upstream.

STDMETHODIMP EnumMediaTypes( IEnumMediaTypes **ppEnum );

{

if( ! m_pTIPFilter->m_pInput->IsConnected() )

return VFW_E_NOT_CONNECTED;

return m_pTIPFilter->m_pInput->GetConnected()->EnumMediaTypes( ppEnum );

}

// Say whether media type is acceptable. - agree to anything if not connected,

// otherwise pass through to the upstream filter.

HRESULT CheckMediaType(const CMediaType* pmt);

{

if (m_pTIPFilter->UsingDifferentAllocators() && !m_pFilter->IsStopped()) {

if (*pmt == m_mt) {return S_OK;}

else {return VFW_E_TYPE_NOT_ACCEPTED;}

}

HRESULT hr = m_pTIPFilter->CheckInputType(pmt);

if( m_pTIPFilter->m_pInput->IsConnected() )

return m_pTIPFilter->m_pInput->GetConnected()->QueryAccept( pmt );

else return S_OK;

}

HRESULT CompleteConnect(IPin *pReceivePin);

{

HRESULT hr = CBaseOutputPin::CompleteConnect(pReceivePin);

return m_pTransformFilter->CompleteConnect(PINDIR_OUTPUT,pReceivePin);

}

c) 其他函数

// This just saves the allocator being used on the output pin

// Also called by input pin's GetAllocator()

void SetAllocator(IMemAllocator * pAllocator);

{

pAllocator->AddRef();

if (m_pAllocator) {m_pAllocator->Release();}

m_pAllocator = pAllocator;

}

IMemInputPin * ConnectedIMemInputPin(){ return m_pInputPin; }

IMemAllocator * PeekAllocator() const{ return m_pAllocator; }

3. CTransInPlaceFilter类[transip.h/transip.cpp]

a) 成员变量

bool m_bModifiesData; // Does this filter change the data?

m_bModifiesData被Constructor中bModifiesData初始化。

b) 新增加的virtual函数

virtual HRESULT Transform(IMediaSample *pSample) PURE;

c) 继承的IBaseFilter、CBaseFilter和CTransformFilter函数

// 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->Deliver(pSample);}

if (UsingDifferentAllocators()) {

pSample = Copy(pSample);}

// have the derived class transform the data

hr = Transform(pSample);

hr = m_pOutput->Deliver(pSample);

if (UsingDifferentAllocators()) {pSample->Release();}

}

HRESULT CompleteConnect(PIN_DIRECTION dir,IPin *pReceivePin);

{

if (dir == PINDIR_OUTPUT) {

if( m_pInput->IsConnected() ) {

return ReconnectPin( m_pInput, &m_pOutput->CurrentMediaType() );}

return NOERROR;

}

if( m_pOutput->IsConnected() ) {

if ( m_pInput->CurrentMediaType()

!= m_pOutput->CurrentMediaType()

) {

return ReconnectPin( m_pOutput, &m_pInput->CurrentMediaType() );

}

}

}

// 必须override

HRESULT GetMediaType(int iPosition, CMediaType *pMediaType)

// This is called when we actually have to provide out own allocator.

HRESULT DecideBufferSize(IMemAllocator*, ALLOCATOR_PROPERTIES *);

{

// If we are connected upstream, get his views

if (m_pInput->IsConnected()) {

hr = InputPin()->PeekAllocator()->GetProperties(&Request); }

// 填充 ALLOCATOR_PROPERTIES,并调用pAlloc->SetProperties(pProperties, &Actual);

}

// 必须override

HRESULT CheckTransform(const CMediaType *mtIn, const CMediaType *mtOut)

virtual CBasePin *GetPin(int n);

{

// Create an input pin if not already done

if (m_pInput == NULL) {

m_pInput = new CTransInPlaceInputPin( NAME("TransInPlace input pin")

, this // Owner filter

, &hr // Result code

, L"Input" // Pin name

);

if (m_pInput!=NULL && m_pOutput == NULL) {

m_pOutput = new CTransInPlaceOutputPin( NAME("TransInPlace output pin")

, this // Owner filter

, &hr // Result code

, L"Output" // Pin name

);

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

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

else {return NULL;}

}

d) 其他函数

IMediaSample * CTransInPlaceFilter::Copy(IMediaSample *pSource);

{复制两个Sample}

CTransInPlaceInputPin *InputPin() const{return (CTransInPlaceInputPin *)m_pInput;}

CTransInPlaceOutputPin *OutputPin() const

{return (CTransInPlaceOutputPin *)m_pOutput;}

// Helper to see if the input and output types match

BOOL TypesMatch()

{return InputPin()->CurrentMediaType() ==OutputPin()->CurrentMediaType();}

// Are the input and output allocators different?

BOOL UsingDifferentAllocators() const

{return InputPin()->PeekAllocator() != OutputPin()->PeekAllocator();}

附上CTransInPlaceFilter的中的设计思路注释,这几个类应该是Base Classes中注释最多,最容易读的类了。

// How allocators are decided.

// An in-place transform tries to do its work in someone else's buffers. It tries to persuade

// the filters on either side to use the same allocator (and for that matter the same media type).

// In desperation, if the downstream filter refuses to supply an allocator and the upstream filter

// offers only a read-only one then it will provide an allocator. if the upstream filter insists

// on a read-only allocator then the transform filter will (reluctantly) copy the data before

// transforming it

// In order to pass an allocator through it needs to remember the one it got from the first

// connection to pass it on to the second one.

// It is good if we can avoid insisting on a particular order of connection (There is a precedent

// for insisting on the input being connected first. Insisting on the output being connected

// first is not allowed. That would break RenderFile.)

// The base pin classes (CBaseOutputPin and CBaseInputPin) both have a m_pAllocator member which

// is used in places like CBaseOutputPin::GetDeliveryBuffer and CBaseInputPin::Inactive.

// To avoid lots of extra overriding, we should keep these happy by using these pointers.

// When each pin is connected, it will set the corresponding m_pAllocator and will have a single

// ref-count on that allocator Refcounts are acquired by GetAllocator calls which return AddReffed

// allocators and are released in one of:

// CBaseInputPin::Disconnect

// CBaseOutputPin::BreakConect

// In each case m_pAllocator is set to NULL after the release, so this is the last chance to ever

// release it. If there should ever be multiple refcounts associated with the same pointer, this

// had better be cleared up before that happens. To avoid such problems, we'll stick with one

// per pointer.

// RECONNECTING and STATE CHANGES

// Each pin could be disconnected, connected with a read-only allocator, connected with an upstream

// read/write allocator, connected with an allocator from downstream or connected with its own

// allocator. Five states for each pin gives a data space of 25 states.

// Notation:

// R/W == read/write

// R-O == read-only

// <input pin state> <output pin state> <comments>

//

// 00 means an unconnected pin.

// <- means using a R/W allocator from the upstream filter

// <= means using a R-O allocator from an upstream filter

// || means using our own (R/W) allocator.

// -> means using a R/W allocator from a downstream filter

// (a R-O allocator from downstream is nonsense, it can't ever work).

//

// That makes 25 possible states. Some states are nonsense (two different

// allocators from the same place). These are just an artifact of the notation.

// <= <- Nonsense.

// <- <= Nonsense

// Some states are illegal (the output pin never accepts a R-O allocator):

// 00 <= !! Error !!

// <= <= !! Error !!

// || <= !! Error !!

// -> <= !! Error !!

// Three states appears to be inaccessible:

// -> || Inaccessible

// || -> Inaccessible

// || <- Inaccessible

// Some states only ever occur as intermediates with a pending reconnect which

// is guaranteed to finish in another state.

// -> 00 ?? unstable goes to || 00

// 00 <- ?? unstable goes to 00 ||

// -> <- ?? unstable goes to -> ->

// <- || ?? unstable goes to <- <-

// <- -> ?? unstable goes to <- <-

// And that leaves 11 possible resting states:

// 1 00 00 Nothing connected.

// 2 <- 00 Input pin connected.

// 3 <= 00 Input pin connected using R-O allocator.

// 4 || 00 Needs several state changes to get here.

// 5 00 || Output pin connected using our allocator

// 6 00 -> Downstream only connected

// 7 || || Undesirable but can be forced upon us.

// 8 <= || Copy forced. <= -> is preferable

// 9 <= -> OK - forced to copy.

// 10 <- <- Transform in place (ideal)

// 11 -> -> Transform in place (ideal)

//

// The object of the exercise is to ensure that we finish up in states 10 or 11 whenever possible.

// State 10 is only possible if the upstream filter has a R/W allocator (the AVI splitter

// notoriously doesn't) and state 11 is only possible if the downstream filter does offer an

// allocator.

// The transition table (entries marked * go via a reconnect)

// There are 8 possible transitions:

// A: Connect upstream to filter with R-O allocator that insists on using it.

// B: Connect upstream to filter with R-O allocator but chooses not to use it.

// C: Connect upstream to filter with R/W allocator and insists on using it.

// D: Connect upstream to filter with R/W allocator but chooses not to use it.

// E: Connect downstream to a filter that offers an allocator

// F: Connect downstream to a filter that does not offer an allocator

// G: disconnect upstream

// H: Disconnect downstream

//

// A B C D E F G H

// ---------------------------------------------------------

// 00 00 1 | 3 3 2 2 6 5 . . |1 00 00

// <- 00 2 | . . . . *10/11 10 1 . |2 <- 00

// <= 00 3 | . . . . *9/11 *7/8 1 . |3 <= 00

// || 00 4 | . . . . *8 *7 1 . |4 || 00

// 00 || 5 | 8 7 *10 7 . . . 1 |5 00 ||

// 00 -> 6 | 9 11 *10 11 . . . 1 |6 00 ->

// || || 7 | . . . . . . 5 4 |7 || ||

// <= || 8 | . . . . . . 5 3 |8 <= ||

// <= -> 9 | . . . . . . 6 3 |9 <= ->

// <- <- 10| . . . . . . *5/6 2 |10 <- <-

// -> -> 11| . . . . . . 6 *2/3 |11 -> ->

// ---------------------------------------------------------

// A B C D E F G H

//

// All these states are accessible without requiring any filter to change its behaviour but not

// all transitions are accessible, // for instance a transition from state 4 to anywhere other

// than state 8 requires that the upstream filter first offer a R-O allocator and then changes

// its mind and offer R/W. This is NOT allowable - it leads to things like the output pin

// getting a R/W allocator from upstream and then the input pin being told it can only have a

// R-O one.

// Note that you CAN change (say) the upstream filter for a different one, but only as a disconnect // connect, not as a Reconnect. (Exercise for the reader is to see how you get into state 4).

//

// The reconnection stuff goes as follows (some of the cases shown here as "no reconnect" may

// get one to finalise media type - an old story). If there is a reconnect where it says "no

// reconnect" here then the reconnection must not change the allocator choice.

// state 2: <- 00 transition E <- <- case C <- <- (no change)

// case D -> <- and then to -> ->

//

// state 2: <- 00 transition F <- <- (no reconnect)

//

// state 3: <= 00 transition E <= -> case A <= -> (no change)

// case B -> ->

// transition F <= || case A <= || (no change)

// case B || ||

//

// state 4: || 00 transition E || || case B -> || and then all cases to -> ->

// F || || case B || || (no change)

//

// state 5: 00 || transition A <= || (no reconnect)

// B || || (no reconnect)

// C <- || all cases <- <-

// D || || (unfortunate, but upstream's choice)

//

// state 6: 00 -> transition A <= -> (no reconnect)

// B -> -> (no reconnect)

// C <- -> all cases <- <-

// D -> -> (no reconnect)

//

// state 10:<- <- transition G 00 <- case E 00 ->

// case F 00 ||

//

// state 11:-> -> transition H -> 00 case A <= 00 (schizo)

// case B <= 00

// case C <- 00 (schizo)

// case D <- 00

//

// The Rules:

// To sort out media types:

// The input is reconnected

// if the input pin is connected and the output pin connects

// The output is reconnected

// If the output pin is connected

// and the input pin connects to a different media type

//

// To sort out allocators:

// The input is reconnected

// if the output disconnects and the input was using a downstream allocator

// The output pin calls SetAllocator to pass on a new allocator

// if the output is connected and

// if the input disconnects and the output was using an upstream allocator

// if the input acquires an allocator different from the output one

// and that new allocator is not R-O

//

// Data is copied (i.e. call getbuffer and copy the data before transforming it)

// if the two allocators are different.

// CHAINS of filters:

// We sit between two filters (call them A and Z). We should finish up with the same allocator

// on both of our pins and that should be the same one that A and Z would have agreed on if we

// hadn't been in the way. Furthermore, it should not matter how many in-place transforms

// are in the way. Let B, C, D... be in-place transforms ("us").

// Here's how it goes:

//

// 1.

// A connects to B. They agree on A's allocator.

// A-a->B

//

// 2.

// B connects to C. Same story. There is no point in a reconnect, but

// B will request an input reconnect anyway.

// A-a->B-a->C

//

// 3.

// C connects to Z.

// C insists on using A's allocator, but compromises by requesting a reconnect.

// of C's input.

// A-a->B-?->C-a->Z

//

// We now have pending reconnects on both A--->B and B--->C

//

// 4.

// The A--->B link is reconnected.

// A asks B for an allocator. B sees that it has a downstream connection so asks its downstream

// input pin i.e. C's input pin for an allocator. C sees that it too has a downstream connection

// so asks Z for an allocator.

//

// Even though Z's input pin is connected, it is being asked for an allocator.

// It could refuse, in which case the chain is done and will use A's allocator

// Alternatively, Z may supply one. A chooses either Z's or A's own one.

// B's input pin gets NotifyAllocator called to tell it the decision and it

// propagates this downstream by calling ReceiveAllocator on its output pin

// which calls NotifyAllocator on the next input pin downstream etc.

// If the choice is Z then it goes:

// A-z->B-a->C-a->Z

// A-z->B-z->C-a->Z

// A-z->B-z->C-z->Z

//

// And that's IT!! Any further (essentially spurious) reconnects peter out with no change in

// the chain.

前一篇:(六) CTransfromFilter及相关联Pin类的源代码解析

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