2 * Implements IBaseFilter for transform filters. (internal)
4 * hidenori@a2.ctktv.ne.jp
20 #include "debugtools.h"
21 DEFAULT_DEBUG_CHANNEL(quartz);
23 #include "quartz_private.h"
28 static const WCHAR XFORM_DefInName[] =
29 {'X','F','o','r','m',' ','I','n',0};
30 static const WCHAR XFORM_DefOutName[] =
31 {'X','F','o','r','m',' ','O','u','t',0};
33 /***************************************************************************
35 * CTransformBaseImpl methods
39 static HRESULT CTransformBaseImpl_OnActive( CBaseFilterImpl* pImpl )
41 CTransformBaseImpl_THIS(pImpl,basefilter);
43 TRACE( "(%p)\n", This );
48 static HRESULT CTransformBaseImpl_OnInactive( CBaseFilterImpl* pImpl )
50 CTransformBaseImpl_THIS(pImpl,basefilter);
52 IMemAllocator* pAllocator;
54 TRACE( "(%p)\n", This );
56 if ( This->pInPin->pin.pPinConnectedTo == NULL ||
57 This->pOutPin->pin.pPinConnectedTo == NULL )
60 EnterCriticalSection( &This->csFilter );
62 pAllocator = This->m_pOutPinAllocator;
63 if ( pAllocator != NULL &&
64 This->pInPin->meminput.pAllocator != pAllocator )
66 hr = IMemAllocator_Commit( pAllocator );
71 if ( !This->m_bFiltering )
73 hr = This->m_pHandler->pBeginTransform( This, This->pInPin->pin.pmtConn, This->pOutPin->pin.pmtConn, This->m_bReuseSample );
76 This->m_bFiltering = TRUE;
81 LeaveCriticalSection( &This->csFilter );
86 static HRESULT CTransformBaseImpl_OnStop( CBaseFilterImpl* pImpl )
88 CTransformBaseImpl_THIS(pImpl,basefilter);
89 IMemAllocator* pAllocator;
91 TRACE( "(%p)\n", This );
93 EnterCriticalSection( &This->csFilter );
95 if ( This->m_bFiltering )
97 This->m_pHandler->pEndTransform( This );
98 This->m_bFiltering = FALSE;
100 if ( This->m_pSample != NULL )
102 IMediaSample_Release( This->m_pSample );
103 This->m_pSample = NULL;
106 pAllocator = This->m_pOutPinAllocator;
107 if ( pAllocator != NULL &&
108 This->pInPin->meminput.pAllocator != pAllocator )
110 IMemAllocator_Decommit( pAllocator );
113 LeaveCriticalSection( &This->csFilter );
118 static const CBaseFilterHandlers filterhandlers =
120 CTransformBaseImpl_OnActive, /* pOnActive */
121 CTransformBaseImpl_OnInactive, /* pOnInactive */
122 CTransformBaseImpl_OnStop, /* pOnStop */
125 /***************************************************************************
127 * CTransformBaseInPinImpl methods
131 static HRESULT CTransformBaseInPinImpl_OnPostConnect( CPinBaseImpl* pImpl, IPin* pPin )
133 CTransformBaseInPinImpl_THIS(pImpl,pin);
136 TRACE( "(%p,%p)\n", This, pPin );
138 EnterCriticalSection( &This->pFilter->csFilter );
139 hr = This->pFilter->m_pHandler->pGetOutputTypes( This->pFilter, This->pFilter->pInPin->pin.pmtConn, &This->pFilter->pOutPin->pin.pmtAcceptTypes, &This->pFilter->pOutPin->pin.cAcceptTypes );
145 LeaveCriticalSection( &This->pFilter->csFilter );
150 static HRESULT CTransformBaseInPinImpl_OnDisconnect( CPinBaseImpl* pImpl )
152 CTransformBaseInPinImpl_THIS(pImpl,pin);
154 TRACE( "(%p)\n", This );
156 if ( This->meminput.pAllocator != NULL )
158 IMemAllocator_Decommit(This->meminput.pAllocator);
159 IMemAllocator_Release(This->meminput.pAllocator);
160 This->meminput.pAllocator = NULL;
166 static HRESULT CTransformBaseInPinImpl_CheckMediaType( CPinBaseImpl* pImpl, const AM_MEDIA_TYPE* pmt )
168 CTransformBaseInPinImpl_THIS(pImpl,pin);
171 TRACE( "(%p,%p)\n", This, pmt );
173 EnterCriticalSection( &This->pFilter->csFilter );
174 hr = This->pFilter->m_pHandler->pCheckMediaType( This->pFilter, pmt, (This->pFilter->pOutPin->pin.pPinConnectedTo != NULL) ? This->pFilter->pOutPin->pin.pmtConn : NULL );
175 LeaveCriticalSection( &This->pFilter->csFilter );
180 static HRESULT CTransformBaseInPinImpl_Receive( CPinBaseImpl* pImpl, IMediaSample* pSample )
182 CTransformBaseInPinImpl_THIS(pImpl,pin);
185 TRACE( "(%p,%p)\n", This, pSample );
187 if ( This->pin.pPinConnectedTo == NULL ||
188 This->pFilter->pOutPin->pin.pPinConnectedTo == NULL )
191 if ( !This->pFilter->m_bFiltering )
194 if ( This->pFilter->m_bInFlush )
197 if ( This->meminput.pAllocator != This->pFilter->m_pOutPinAllocator )
199 if ( This->pFilter->m_pSample == NULL )
201 hr = IMemAllocator_GetBuffer( This->pFilter->m_pOutPinAllocator, &This->pFilter->m_pSample, NULL, NULL, 0 );
205 hr = QUARTZ_IMediaSample_Copy(
206 This->pFilter->m_pSample, pSample, This->pFilter->m_bPreCopy );
211 if ( This->pFilter->m_bPreCopy )
212 hr = This->pFilter->m_pHandler->pTransform( This->pFilter, This->pFilter->m_pSample, NULL );
214 hr = This->pFilter->m_pHandler->pTransform( This->pFilter, pSample, This->pFilter->m_pSample );
221 hr = CPinBaseImpl_SendSample(&This->pFilter->pOutPin->pin,This->pFilter->m_pSample);
228 if ( !This->pFilter->m_bReuseSample )
230 if ( This->pFilter->m_pSample != NULL )
232 IMediaSample_Release( This->pFilter->m_pSample );
233 This->pFilter->m_pSample = NULL;
245 static HRESULT CTransformBaseInPinImpl_ReceiveCanBlock( CPinBaseImpl* pImpl )
247 CTransformBaseInPinImpl_THIS(pImpl,pin);
249 TRACE( "(%p)\n", This );
251 if ( This->pin.pPinConnectedTo == NULL ||
252 This->pFilter->pOutPin->pin.pPinConnectedTo == NULL )
255 return CPinBaseImpl_SendReceiveCanBlock( &This->pFilter->pOutPin->pin );
258 static HRESULT CTransformBaseInPinImpl_EndOfStream( CPinBaseImpl* pImpl )
260 CTransformBaseInPinImpl_THIS(pImpl,pin);
262 TRACE( "(%p)\n", This );
264 if ( This->pin.pPinConnectedTo == NULL ||
265 This->pFilter->pOutPin->pin.pPinConnectedTo == NULL )
268 return CPinBaseImpl_SendEndOfStream( &This->pFilter->pOutPin->pin );
271 static HRESULT CTransformBaseInPinImpl_BeginFlush( CPinBaseImpl* pImpl )
273 CTransformBaseInPinImpl_THIS(pImpl,pin);
275 TRACE( "(%p)\n", This );
277 if ( This->pin.pPinConnectedTo == NULL ||
278 This->pFilter->pOutPin->pin.pPinConnectedTo == NULL )
281 This->pFilter->m_bInFlush = TRUE;
283 return CPinBaseImpl_SendBeginFlush( &This->pFilter->pOutPin->pin );
286 static HRESULT CTransformBaseInPinImpl_EndFlush( CPinBaseImpl* pImpl )
288 CTransformBaseInPinImpl_THIS(pImpl,pin);
290 TRACE( "(%p)\n", This );
292 if ( This->pin.pPinConnectedTo == NULL ||
293 This->pFilter->pOutPin->pin.pPinConnectedTo == NULL )
296 This->pFilter->m_bInFlush = FALSE;
298 return CPinBaseImpl_SendEndFlush( &This->pFilter->pOutPin->pin );
301 static HRESULT CTransformBaseInPinImpl_NewSegment( CPinBaseImpl* pImpl, REFERENCE_TIME rtStart, REFERENCE_TIME rtStop, double rate )
303 CTransformBaseInPinImpl_THIS(pImpl,pin);
305 FIXME( "(%p)\n", This );
307 if ( This->pin.pPinConnectedTo == NULL ||
308 This->pFilter->pOutPin->pin.pPinConnectedTo == NULL )
311 return CPinBaseImpl_SendNewSegment( &This->pFilter->pOutPin->pin,
312 rtStart, rtStop, rate );
315 static const CBasePinHandlers inputpinhandlers =
317 NULL, /* pOnPreConnect */
318 CTransformBaseInPinImpl_OnPostConnect, /* pOnPostConnect */
319 CTransformBaseInPinImpl_OnDisconnect, /* pOnDisconnect */
320 CTransformBaseInPinImpl_CheckMediaType, /* pCheckMediaType */
321 NULL, /* pQualityNotify */
322 CTransformBaseInPinImpl_Receive, /* pReceive */
323 CTransformBaseInPinImpl_ReceiveCanBlock, /* pReceiveCanBlock */
324 CTransformBaseInPinImpl_EndOfStream, /* pEndOfStream */
325 CTransformBaseInPinImpl_BeginFlush, /* pBeginFlush */
326 CTransformBaseInPinImpl_EndFlush, /* pEndFlush */
327 CTransformBaseInPinImpl_NewSegment, /* pNewSegment */
330 /***************************************************************************
332 * CTransformBaseOutPinImpl methods
336 static HRESULT CTransformBaseOutPinImpl_OnPostConnect( CPinBaseImpl* pImpl, IPin* pPin )
338 CTransformBaseOutPinImpl_THIS(pImpl,pin);
340 ALLOCATOR_PROPERTIES propReqThis;
341 ALLOCATOR_PROPERTIES propReqPeer;
342 ALLOCATOR_PROPERTIES propActual;
343 BOOL bTransInPlace = FALSE;
344 BOOL bTryToReUseSample = FALSE;
345 BOOL bOutReadonly = FALSE;
346 IMemAllocator* pAllocator;
348 FIXME( "(%p,%p)\n", This, pPin );
350 if ( This->pFilter->pInPin->pin.pPinConnectedTo == NULL )
352 if ( This->pin.pMemInputPinConnectedTo == NULL )
355 ZeroMemory( &propReqThis, sizeof(ALLOCATOR_PROPERTIES) );
356 ZeroMemory( &propReqPeer, sizeof(ALLOCATOR_PROPERTIES) );
357 ZeroMemory( &propActual, sizeof(ALLOCATOR_PROPERTIES) );
359 hr = This->pFilter->m_pHandler->pGetAllocProp( This->pFilter, This->pFilter->pInPin->pin.pmtConn, This->pin.pmtConn, &propReqThis, &bTransInPlace, &bTryToReUseSample );
363 if ( propReqThis.cbAlign == 0 )
364 propReqThis.cbAlign = 1;
368 ZeroMemory( &propReqPeer, sizeof(ALLOCATOR_PROPERTIES) );
369 hr = IMemInputPin_GetAllocatorRequirements(
370 This->pin.pMemInputPinConnectedTo, &propReqPeer );
371 if ( propReqPeer.cbAlign != 0 && propReqPeer.cbAlign != 1 )
372 bTransInPlace = FALSE;
373 if ( propReqPeer.cbPrefix != 0 )
374 bTransInPlace = FALSE;
376 bOutReadonly = FALSE;
377 if ( bTransInPlace && This->pFilter->pInPin->meminput.bReadonly )
380 pAllocator = This->pFilter->pInPin->meminput.pAllocator;
382 hr = IMemInputPin_NotifyAllocator(
383 This->pin.pMemInputPinConnectedTo,
384 pAllocator, bOutReadonly );
387 This->pFilter->m_pOutPinAllocator = pAllocator;
388 IMemAllocator_AddRef(pAllocator);
389 bTryToReUseSample = FALSE;
394 hr = IMemInputPin_GetAllocator(
395 This->pin.pMemInputPinConnectedTo, &pAllocator );
398 hr = IMemAllocator_SetProperties( pAllocator, &propReqThis, &propActual );
401 TRACE("cBuffers = %ld / cbBuffer = %ld\n",propActual.cBuffers,propActual.cbBuffer);
402 hr = IMemInputPin_NotifyAllocator(
403 This->pin.pMemInputPinConnectedTo, pAllocator,
408 IMemAllocator_Release(pAllocator);
411 This->pFilter->m_pOutPinAllocator = pAllocator;
415 This->pFilter->m_bPreCopy = FALSE;
416 This->pFilter->m_bReuseSample = FALSE;
419 This->pFilter->m_bPreCopy = bTransInPlace && (This->pFilter->pInPin->meminput.pAllocator != This->pFilter->m_pOutPinAllocator);
420 This->pFilter->m_bReuseSample = bTryToReUseSample;
426 static HRESULT CTransformBaseOutPinImpl_OnDisconnect( CPinBaseImpl* pImpl )
428 CTransformBaseOutPinImpl_THIS(pImpl,pin);
430 FIXME( "(%p)\n", This );
432 if ( This->pFilter->m_pOutPinAllocator != NULL )
434 IMemAllocator_Decommit(This->pFilter->m_pOutPinAllocator);
435 IMemAllocator_Release(This->pFilter->m_pOutPinAllocator);
436 This->pFilter->m_pOutPinAllocator = NULL;
442 static HRESULT CTransformBaseOutPinImpl_CheckMediaType( CPinBaseImpl* pImpl, const AM_MEDIA_TYPE* pmt )
444 CTransformBaseOutPinImpl_THIS(pImpl,pin);
447 TRACE( "(%p,%p)\n", This, pmt );
449 if ( This->pFilter->pInPin->pin.pPinConnectedTo == NULL )
452 EnterCriticalSection( &This->pFilter->csFilter );
453 hr = This->pFilter->m_pHandler->pCheckMediaType( This->pFilter, This->pFilter->pInPin->pin.pmtConn, pmt );
454 LeaveCriticalSection( &This->pFilter->csFilter );
459 static const CBasePinHandlers outputpinhandlers =
461 NULL, /* pOnPreConnect */
462 CTransformBaseOutPinImpl_OnPostConnect, /* pOnPostConnect */
463 CTransformBaseOutPinImpl_OnDisconnect, /* pOnDisconnect */
464 CTransformBaseOutPinImpl_CheckMediaType, /* pCheckMediaType */
465 NULL, /* pQualityNotify */
466 OutputPinSync_Receive, /* pReceive */
467 OutputPinSync_ReceiveCanBlock, /* pReceiveCanBlock */
468 OutputPinSync_EndOfStream, /* pEndOfStream */
469 OutputPinSync_BeginFlush, /* pBeginFlush */
470 OutputPinSync_EndFlush, /* pEndFlush */
471 OutputPinSync_NewSegment, /* pNewSegment */
475 /***************************************************************************
477 * new/delete CTransformBaseImpl
481 /* can I use offsetof safely? - FIXME? */
482 static QUARTZ_IFEntry FilterIFEntries[] =
484 { &IID_IPersist, offsetof(CTransformBaseImpl,basefilter)-offsetof(CTransformBaseImpl,unk) },
485 { &IID_IMediaFilter, offsetof(CTransformBaseImpl,basefilter)-offsetof(CTransformBaseImpl,unk) },
486 { &IID_IBaseFilter, offsetof(CTransformBaseImpl,basefilter)-offsetof(CTransformBaseImpl,unk) },
489 static void QUARTZ_DestroyTransformBase(IUnknown* punk)
491 CTransformBaseImpl_THIS(punk,unk);
493 TRACE( "(%p)\n", This );
495 This->m_pHandler->pCleanup(This);
497 if ( This->pInPin != NULL )
499 IUnknown_Release(This->pInPin->unk.punkControl);
502 if ( This->pOutPin != NULL )
504 IUnknown_Release(This->pOutPin->unk.punkControl);
505 This->pOutPin = NULL;
507 if ( This->pSeekPass != NULL )
509 IUnknown_Release((IUnknown*)&This->pSeekPass->unk);
510 This->pSeekPass = NULL;
513 CBaseFilterImpl_UninitIBaseFilter(&This->basefilter);
515 DeleteCriticalSection( &This->csFilter );
518 HRESULT QUARTZ_CreateTransformBase(
519 IUnknown* punkOuter,void** ppobj,
520 const CLSID* pclsidTransformBase,
521 LPCWSTR pwszTransformBaseName,
522 LPCWSTR pwszInPinName,
523 LPCWSTR pwszOutPinName,
524 const TransformBaseHandlers* pHandler )
526 CTransformBaseImpl* This = NULL;
529 TRACE("(%p,%p)\n",punkOuter,ppobj);
531 if ( pwszInPinName == NULL )
532 pwszInPinName = XFORM_DefInName;
533 if ( pwszOutPinName == NULL )
534 pwszOutPinName = XFORM_DefOutName;
536 This = (CTransformBaseImpl*)
537 QUARTZ_AllocObj( sizeof(CTransformBaseImpl) );
539 return E_OUTOFMEMORY;
542 This->pOutPin = NULL;
543 This->pSeekPass = NULL;
544 This->m_pOutPinAllocator = NULL;
545 This->m_bPreCopy = FALSE; /* sample must be copied */
546 This->m_bReuseSample = FALSE; /* sample must be reused */
547 This->m_bInFlush = FALSE;
548 This->m_pSample = NULL;
549 This->m_bFiltering = FALSE;
550 This->m_pHandler = pHandler;
551 This->m_pUserData = NULL;
553 QUARTZ_IUnkInit( &This->unk, punkOuter );
555 hr = CBaseFilterImpl_InitIBaseFilter(
557 This->unk.punkControl,
559 pwszTransformBaseName,
563 /* construct this class. */
564 hr = This->m_pHandler->pInit( This );
567 CBaseFilterImpl_UninitIBaseFilter(&This->basefilter);
573 QUARTZ_FreeObj(This);
577 This->unk.pEntries = FilterIFEntries;
578 This->unk.dwEntries = sizeof(FilterIFEntries)/sizeof(FilterIFEntries[0]);
579 This->unk.pOnFinalRelease = QUARTZ_DestroyTransformBase;
580 InitializeCriticalSection( &This->csFilter );
583 hr = QUARTZ_CreateTransformBaseInPin(
584 This, &This->csFilter,
585 &This->pInPin, pwszInPinName );
587 hr = QUARTZ_CompList_AddComp(
588 This->basefilter.pInPins,
589 (IUnknown*)&(This->pInPin->pin),
592 hr = QUARTZ_CreateTransformBaseOutPin(
593 This, &This->csFilter,
594 &This->pOutPin, pwszOutPinName );
596 hr = QUARTZ_CompList_AddComp(
597 This->basefilter.pOutPins,
598 (IUnknown*)&(This->pOutPin->pin),
603 hr = QUARTZ_CreateSeekingPassThruInternal(
604 (IUnknown*)&(This->pOutPin->unk), &This->pSeekPass,
605 FALSE, (IPin*)&(This->pInPin->pin) );
610 IUnknown_Release( This->unk.punkControl );
614 *ppobj = (void*)&(This->unk);
619 /***************************************************************************
621 * new/delete CTransformBaseInPinImpl
625 /* can I use offsetof safely? - FIXME? */
626 static QUARTZ_IFEntry InPinIFEntries[] =
628 { &IID_IPin, offsetof(CTransformBaseInPinImpl,pin)-offsetof(CTransformBaseInPinImpl,unk) },
629 { &IID_IMemInputPin, offsetof(CTransformBaseInPinImpl,meminput)-offsetof(CTransformBaseInPinImpl,unk) },
632 static void QUARTZ_DestroyTransformBaseInPin(IUnknown* punk)
634 CTransformBaseInPinImpl_THIS(punk,unk);
636 TRACE( "(%p)\n", This );
638 CPinBaseImpl_UninitIPin( &This->pin );
639 CMemInputPinBaseImpl_UninitIMemInputPin( &This->meminput );
642 HRESULT QUARTZ_CreateTransformBaseInPin(
643 CTransformBaseImpl* pFilter,
644 CRITICAL_SECTION* pcsPin,
645 CTransformBaseInPinImpl** ppPin,
646 LPCWSTR pwszPinName )
648 CTransformBaseInPinImpl* This = NULL;
651 TRACE("(%p,%p,%p)\n",pFilter,pcsPin,ppPin);
653 This = (CTransformBaseInPinImpl*)
654 QUARTZ_AllocObj( sizeof(CTransformBaseInPinImpl) );
656 return E_OUTOFMEMORY;
658 QUARTZ_IUnkInit( &This->unk, NULL );
659 This->pFilter = pFilter;
661 hr = CPinBaseImpl_InitIPin(
663 This->unk.punkControl,
665 &pFilter->basefilter,
672 hr = CMemInputPinBaseImpl_InitIMemInputPin(
674 This->unk.punkControl,
678 CPinBaseImpl_UninitIPin( &This->pin );
684 QUARTZ_FreeObj(This);
688 This->unk.pEntries = InPinIFEntries;
689 This->unk.dwEntries = sizeof(InPinIFEntries)/sizeof(InPinIFEntries[0]);
690 This->unk.pOnFinalRelease = QUARTZ_DestroyTransformBaseInPin;
694 TRACE("returned successfully.\n");
700 /***************************************************************************
702 * new/delete CTransformBaseOutPinImpl
706 /* can I use offsetof safely? - FIXME? */
707 static QUARTZ_IFEntry OutPinIFEntries[] =
709 { &IID_IPin, offsetof(CTransformBaseOutPinImpl,pin)-offsetof(CTransformBaseOutPinImpl,unk) },
710 { &IID_IQualityControl, offsetof(CTransformBaseOutPinImpl,qcontrol)-offsetof(CTransformBaseOutPinImpl,unk) },
713 static HRESULT CTransformBaseOutPinImpl_OnQueryInterface(
714 IUnknown* punk, const IID* piid, void** ppobj )
716 CTransformBaseOutPinImpl_THIS(punk,unk);
718 if ( This->pFilter == NULL || This->pFilter->pSeekPass == NULL )
719 return E_NOINTERFACE;
721 if ( IsEqualGUID( &IID_IMediaPosition, piid ) ||
722 IsEqualGUID( &IID_IMediaSeeking, piid ) )
724 TRACE( "IMediaSeeking(or IMediaPosition) is queried\n" );
725 return IUnknown_QueryInterface( (IUnknown*)(&This->pFilter->pSeekPass->unk), piid, ppobj );
728 return E_NOINTERFACE;
731 static void QUARTZ_DestroyTransformBaseOutPin(IUnknown* punk)
733 CTransformBaseOutPinImpl_THIS(punk,unk);
735 TRACE( "(%p)\n", This );
737 CPinBaseImpl_UninitIPin( &This->pin );
738 CQualityControlPassThruImpl_UninitIQualityControl( &This->qcontrol );
741 HRESULT QUARTZ_CreateTransformBaseOutPin(
742 CTransformBaseImpl* pFilter,
743 CRITICAL_SECTION* pcsPin,
744 CTransformBaseOutPinImpl** ppPin,
745 LPCWSTR pwszPinName )
747 CTransformBaseOutPinImpl* This = NULL;
750 TRACE("(%p,%p,%p)\n",pFilter,pcsPin,ppPin);
752 This = (CTransformBaseOutPinImpl*)
753 QUARTZ_AllocObj( sizeof(CTransformBaseOutPinImpl) );
755 return E_OUTOFMEMORY;
757 QUARTZ_IUnkInit( &This->unk, NULL );
758 This->qiext.pNext = NULL;
759 This->qiext.pOnQueryInterface = &CTransformBaseOutPinImpl_OnQueryInterface;
760 QUARTZ_IUnkAddDelegation( &This->unk, &This->qiext );
762 This->pFilter = pFilter;
764 hr = CPinBaseImpl_InitIPin(
766 This->unk.punkControl,
768 &pFilter->basefilter,
771 &outputpinhandlers );
775 hr = CQualityControlPassThruImpl_InitIQualityControl(
777 This->unk.punkControl,
781 CPinBaseImpl_UninitIPin( &This->pin );
787 QUARTZ_FreeObj(This);
791 This->unk.pEntries = OutPinIFEntries;
792 This->unk.dwEntries = sizeof(OutPinIFEntries)/sizeof(OutPinIFEntries[0]);
793 This->unk.pOnFinalRelease = QUARTZ_DestroyTransformBaseOutPin;
797 TRACE("returned successfully.\n");