2 * Implements IPin and IMemInputPin. (internal)
4 * hidenori@a2.ctktv.ne.jp
17 #include "debugtools.h"
18 DEFAULT_DEBUG_CHANNEL(quartz
);
20 #include "quartz_private.h"
25 /***************************************************************************
32 CPinBaseImpl_fnQueryInterface(IPin
* iface
,REFIID riid
,void** ppobj
)
34 ICOM_THIS(CPinBaseImpl
,iface
);
36 TRACE("(%p)->()\n",This
);
38 return IUnknown_QueryInterface(This
->punkControl
,riid
,ppobj
);
42 CPinBaseImpl_fnAddRef(IPin
* iface
)
44 ICOM_THIS(CPinBaseImpl
,iface
);
46 TRACE("(%p)->()\n",This
);
48 return IUnknown_AddRef(This
->punkControl
);
52 CPinBaseImpl_fnRelease(IPin
* iface
)
54 ICOM_THIS(CPinBaseImpl
,iface
);
56 TRACE("(%p)->()\n",This
);
58 return IUnknown_Release(This
->punkControl
);
62 CPinBaseImpl_fnConnect(IPin
* iface
,IPin
* pPin
,const AM_MEDIA_TYPE
* pmt
)
64 ICOM_THIS(CPinBaseImpl
,iface
);
65 HRESULT hr
= E_NOTIMPL
;
69 TRACE("(%p)->(%p,%p)\n",This
,pPin
,pmt
);
73 TRACE("Connect() should not be sent to input pins\n");
79 TRACE("try to connect to %p\n",pPin
);
81 EnterCriticalSection( This
->pcsPin
);
83 if ( This
->pPinConnectedTo
!= NULL
)
85 hr
= VFW_E_ALREADY_CONNECTED
;
89 /* return fail if running */
90 hr
= IBaseFilter_GetState((IBaseFilter
*)(This
->pFilter
),0,&fs
);
91 if ( hr
!= S_OK
|| fs
!= State_Stopped
)
93 TRACE("not stopped\n");
94 hr
= VFW_E_NOT_STOPPED
;
98 if ( This
->pHandlers
->pOnPreConnect
!= NULL
)
100 hr
= This
->pHandlers
->pOnPreConnect(This
,pPin
);
103 TRACE("OnPreconnect() failed hr = %08lx\n",hr
);
110 hr
= IPin_QueryAccept(iface
,pmt
);
113 hr
= IPin_ReceiveConnection(pPin
,iface
,pmt
);
119 for ( i
= 0; i
< This
->cAcceptTypes
; i
++ )
121 pmt
= &This
->pmtAcceptTypes
[i
];
122 hr
= IPin_QueryAccept(iface
,pmt
);
125 hr
= IPin_ReceiveConnection(pPin
,iface
,pmt
);
126 TRACE("ReceiveConnection - %08lx\n",hr
);
134 hr
= VFW_E_TYPE_NOT_ACCEPTED
;
139 This
->pmtConn
= QUARTZ_MediaType_Duplicate( pmt
);
140 if ( This
->pmtConn
== NULL
)
143 IPin_Disconnect(pPin
);
147 This
->pPinConnectedTo
= pPin
; IPin_AddRef(pPin
);
148 hr
= IPin_QueryInterface(pPin
,&IID_IMemInputPin
,(void**)&This
->pMemInputPinConnectedTo
);
151 TRACE("no IMemInputPin\n");
152 IPin_Disconnect(pPin
);
156 if ( This
->pHandlers
->pOnPostConnect
!= NULL
)
158 hr
= This
->pHandlers
->pOnPostConnect(This
,pPin
);
161 TRACE("OnPostConnect() failed hr = %08lx\n",hr
);
162 IPin_Disconnect(pPin
);
172 IPin_Disconnect(iface
);
174 LeaveCriticalSection( This
->pcsPin
);
176 TRACE("return %08lx\n",hr
);
181 static HRESULT WINAPI
182 CPinBaseImpl_fnReceiveConnection(IPin
* iface
,IPin
* pPin
,const AM_MEDIA_TYPE
* pmt
)
184 ICOM_THIS(CPinBaseImpl
,iface
);
185 HRESULT hr
= E_NOTIMPL
;
188 TRACE("(%p)->(%p,%p)\n",This
,pPin
,pmt
);
192 TRACE("ReceiveConnection() should not be sent to output pins\n");
195 if ( pPin
== NULL
|| pmt
== NULL
)
198 EnterCriticalSection( This
->pcsPin
);
200 if ( This
->pPinConnectedTo
!= NULL
)
202 hr
= VFW_E_ALREADY_CONNECTED
;
206 /* return fail if running */
207 hr
= IBaseFilter_GetState((IBaseFilter
*)(This
->pFilter
),0,&fs
);
208 if ( hr
!= S_OK
|| fs
!= State_Stopped
)
210 TRACE("not stopped\n");
211 hr
= VFW_E_NOT_STOPPED
;
215 if ( This
->pHandlers
->pOnPreConnect
!= NULL
)
217 hr
= This
->pHandlers
->pOnPreConnect(This
,pPin
);
220 TRACE("OnPreConnect() failed hr = %08lx\n",hr
);
225 hr
= IPin_QueryAccept(iface
,pmt
);
229 This
->pmtConn
= QUARTZ_MediaType_Duplicate( pmt
);
230 if ( This
->pmtConn
== NULL
)
236 if ( This
->pHandlers
->pOnPostConnect
!= NULL
)
238 hr
= This
->pHandlers
->pOnPostConnect(This
,pPin
);
241 TRACE("OnPostConnect() failed hr = %08lx\n",hr
);
247 This
->pPinConnectedTo
= pPin
; IPin_AddRef(pPin
);
251 IPin_Disconnect(iface
);
252 LeaveCriticalSection( This
->pcsPin
);
257 static HRESULT WINAPI
258 CPinBaseImpl_fnDisconnect(IPin
* iface
)
260 ICOM_THIS(CPinBaseImpl
,iface
);
261 HRESULT hr
= NOERROR
;
264 TRACE("(%p)->()\n",This
);
266 EnterCriticalSection( This
->pcsPin
);
268 /* return fail if running */
269 hr
= IBaseFilter_GetState((IBaseFilter
*)(This
->pFilter
),0,&fs
);
270 if ( hr
!= S_OK
|| fs
!= State_Stopped
)
272 TRACE("not stopped\n");
273 hr
= VFW_E_NOT_STOPPED
;
277 if ( This
->pHandlers
->pOnDisconnect
!= NULL
)
278 hr
= This
->pHandlers
->pOnDisconnect(This
);
280 if ( This
->pmtConn
!= NULL
)
282 QUARTZ_MediaType_Destroy( This
->pmtConn
);
283 This
->pmtConn
= NULL
;
285 if ( This
->pMemInputPinConnectedTo
!= NULL
)
287 IMemInputPin_Release(This
->pMemInputPinConnectedTo
);
288 This
->pMemInputPinConnectedTo
= NULL
;
290 if ( This
->pPinConnectedTo
!= NULL
)
292 /* FIXME - cleanup */
294 IPin_Release(This
->pPinConnectedTo
);
295 This
->pPinConnectedTo
= NULL
;
300 hr
= S_FALSE
; /* FIXME - is this correct??? */
304 LeaveCriticalSection( This
->pcsPin
);
309 static HRESULT WINAPI
310 CPinBaseImpl_fnConnectedTo(IPin
* iface
,IPin
** ppPin
)
312 ICOM_THIS(CPinBaseImpl
,iface
);
313 HRESULT hr
= VFW_E_NOT_CONNECTED
;
315 TRACE("(%p)->(%p)\n",This
,ppPin
);
320 EnterCriticalSection( This
->pcsPin
);
322 *ppPin
= This
->pPinConnectedTo
;
323 if ( This
->pPinConnectedTo
!= NULL
)
325 IPin_AddRef(This
->pPinConnectedTo
);
329 LeaveCriticalSection( This
->pcsPin
);
334 static HRESULT WINAPI
335 CPinBaseImpl_fnConnectionMediaType(IPin
* iface
,AM_MEDIA_TYPE
* pmt
)
337 ICOM_THIS(CPinBaseImpl
,iface
);
340 TRACE("(%p)->(%p)\n",This
,pmt
);
345 EnterCriticalSection( This
->pcsPin
);
347 if ( This
->pmtConn
!= NULL
)
349 hr
= QUARTZ_MediaType_Copy( pmt
, This
->pmtConn
);
353 ZeroMemory( pmt
, sizeof(AM_MEDIA_TYPE
) );
354 pmt
->bFixedSizeSamples
= TRUE
;
355 pmt
->lSampleSize
= 1;
356 hr
= VFW_E_NOT_CONNECTED
;
359 LeaveCriticalSection( This
->pcsPin
);
364 static HRESULT WINAPI
365 CPinBaseImpl_fnQueryPinInfo(IPin
* iface
,PIN_INFO
* pinfo
)
367 ICOM_THIS(CPinBaseImpl
,iface
);
369 TRACE("(%p)->(%p)\n",This
,pinfo
);
374 EnterCriticalSection( This
->pcsPin
);
376 ZeroMemory( pinfo
, sizeof(PIN_INFO
) );
377 pinfo
->pFilter
= (IBaseFilter
*)(This
->pFilter
);
378 if ( pinfo
->pFilter
!= NULL
)
379 IBaseFilter_AddRef( pinfo
->pFilter
);
380 pinfo
->dir
= This
->bOutput
? PINDIR_OUTPUT
: PINDIR_INPUT
;
381 if ( This
->cbIdLen
<= sizeof(pinfo
->achName
) )
382 memcpy( pinfo
->achName
, This
->pwszId
, This
->cbIdLen
);
385 memcpy( pinfo
->achName
, This
->pwszId
, sizeof(pinfo
->achName
) );
386 pinfo
->achName
[sizeof(pinfo
->achName
)/sizeof(pinfo
->achName
[0])-1] = 0;
389 LeaveCriticalSection( This
->pcsPin
);
394 static HRESULT WINAPI
395 CPinBaseImpl_fnQueryDirection(IPin
* iface
,PIN_DIRECTION
* pdir
)
397 ICOM_THIS(CPinBaseImpl
,iface
);
399 TRACE("(%p)->(%p)\n",This
,pdir
);
404 *pdir
= This
->bOutput
? PINDIR_OUTPUT
: PINDIR_INPUT
;
409 static HRESULT WINAPI
410 CPinBaseImpl_fnQueryId(IPin
* iface
,LPWSTR
* lpwszId
)
412 ICOM_THIS(CPinBaseImpl
,iface
);
414 TRACE("(%p)->(%p)\n",This
,lpwszId
);
416 if ( lpwszId
== NULL
)
419 *lpwszId
= (WCHAR
*)CoTaskMemAlloc( This
->cbIdLen
);
420 if ( *lpwszId
== NULL
)
421 return E_OUTOFMEMORY
;
422 memcpy( *lpwszId
, This
->pwszId
, This
->cbIdLen
);
427 static HRESULT WINAPI
428 CPinBaseImpl_fnQueryAccept(IPin
* iface
,const AM_MEDIA_TYPE
* pmt
)
430 ICOM_THIS(CPinBaseImpl
,iface
);
433 TRACE("(%p)->(%p)\n",This
,pmt
);
439 EnterCriticalSection( This
->pcsPin
);
440 if ( This
->pHandlers
->pCheckMediaType
!= NULL
)
441 hr
= This
->pHandlers
->pCheckMediaType(This
,pmt
);
442 LeaveCriticalSection( This
->pcsPin
);
447 static HRESULT WINAPI
448 CPinBaseImpl_fnEnumMediaTypes(IPin
* iface
,IEnumMediaTypes
** ppenum
)
450 ICOM_THIS(CPinBaseImpl
,iface
);
453 TRACE("(%p)->(%p)\n",This
,ppenum
);
455 if ( ppenum
== NULL
)
460 EnterCriticalSection( This
->pcsPin
);
461 if ( This
->cAcceptTypes
> 0 )
462 hr
= QUARTZ_CreateEnumMediaTypes(
463 ppenum
, This
->pmtAcceptTypes
, This
->cAcceptTypes
);
464 LeaveCriticalSection( This
->pcsPin
);
469 static HRESULT WINAPI
470 CPinBaseImpl_fnQueryInternalConnections(IPin
* iface
,IPin
** ppPin
,ULONG
* pul
)
472 ICOM_THIS(CPinBaseImpl
,iface
);
474 TRACE("(%p)->(%p,%p)\n",This
,ppPin
,pul
);
476 /* E_NOTIMPL means 'no internal connections'. */
480 static HRESULT WINAPI
481 CPinBaseImpl_fnEndOfStream(IPin
* iface
)
483 ICOM_THIS(CPinBaseImpl
,iface
);
484 HRESULT hr
= E_NOTIMPL
;
486 TRACE("(%p)->()\n",This
);
491 EnterCriticalSection( This
->pcsPin
);
492 if ( This
->pHandlers
->pEndOfStream
!= NULL
)
493 hr
= This
->pHandlers
->pEndOfStream(This
);
494 LeaveCriticalSection( This
->pcsPin
);
499 static HRESULT WINAPI
500 CPinBaseImpl_fnBeginFlush(IPin
* iface
)
502 ICOM_THIS(CPinBaseImpl
,iface
);
503 HRESULT hr
= E_NOTIMPL
;
505 TRACE("(%p)->()\n",This
);
510 EnterCriticalSection( This
->pcsPin
);
511 if ( This
->pHandlers
->pBeginFlush
!= NULL
)
512 hr
= This
->pHandlers
->pBeginFlush(This
);
513 LeaveCriticalSection( This
->pcsPin
);
518 static HRESULT WINAPI
519 CPinBaseImpl_fnEndFlush(IPin
* iface
)
521 ICOM_THIS(CPinBaseImpl
,iface
);
522 HRESULT hr
= E_NOTIMPL
;
524 TRACE("(%p)->()\n",This
);
529 EnterCriticalSection( This
->pcsPin
);
530 if ( This
->pHandlers
->pEndFlush
!= NULL
)
531 hr
= This
->pHandlers
->pEndFlush(This
);
532 LeaveCriticalSection( This
->pcsPin
);
537 static HRESULT WINAPI
538 CPinBaseImpl_fnNewSegment(IPin
* iface
,REFERENCE_TIME rtStart
,REFERENCE_TIME rtStop
,double rate
)
540 ICOM_THIS(CPinBaseImpl
,iface
);
541 HRESULT hr
= E_NOTIMPL
;
543 TRACE("(%p)->()\n",This
);
548 EnterCriticalSection( This
->pcsPin
);
549 if ( This
->pHandlers
->pNewSegment
!= NULL
)
550 hr
= This
->pHandlers
->pNewSegment(This
,rtStart
,rtStop
,rate
);
551 LeaveCriticalSection( This
->pcsPin
);
559 static ICOM_VTABLE(IPin
) ipin
=
561 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
562 /* IUnknown fields */
563 CPinBaseImpl_fnQueryInterface
,
564 CPinBaseImpl_fnAddRef
,
565 CPinBaseImpl_fnRelease
,
567 CPinBaseImpl_fnConnect
,
568 CPinBaseImpl_fnReceiveConnection
,
569 CPinBaseImpl_fnDisconnect
,
570 CPinBaseImpl_fnConnectedTo
,
571 CPinBaseImpl_fnConnectionMediaType
,
572 CPinBaseImpl_fnQueryPinInfo
,
573 CPinBaseImpl_fnQueryDirection
,
574 CPinBaseImpl_fnQueryId
,
575 CPinBaseImpl_fnQueryAccept
,
576 CPinBaseImpl_fnEnumMediaTypes
,
577 CPinBaseImpl_fnQueryInternalConnections
,
578 CPinBaseImpl_fnEndOfStream
,
579 CPinBaseImpl_fnBeginFlush
,
580 CPinBaseImpl_fnEndFlush
,
581 CPinBaseImpl_fnNewSegment
,
585 HRESULT
CPinBaseImpl_InitIPin(
586 CPinBaseImpl
* This
, IUnknown
* punkControl
,
587 CRITICAL_SECTION
* pcsPin
,
588 CBaseFilterImpl
* pFilter
, LPCWSTR pwszId
,
590 const CBasePinHandlers
* pHandlers
)
592 HRESULT hr
= NOERROR
;
594 TRACE("(%p,%p,%p)\n",This
,punkControl
,pFilter
);
596 if ( punkControl
== NULL
)
598 ERR( "punkControl must not be NULL\n" );
602 ICOM_VTBL(This
) = &ipin
;
603 This
->punkControl
= punkControl
;
604 This
->pHandlers
= pHandlers
;
605 This
->cbIdLen
= sizeof(WCHAR
)*(lstrlenW(pwszId
)+1);
607 This
->bOutput
= bOutput
;
608 This
->pmtAcceptTypes
= NULL
;
609 This
->cAcceptTypes
= 0;
610 This
->pcsPin
= pcsPin
;
611 This
->pFilter
= pFilter
;
612 This
->pPinConnectedTo
= NULL
;
613 This
->pMemInputPinConnectedTo
= NULL
;
614 This
->pmtConn
= NULL
;
615 This
->pAsyncOut
= NULL
;
617 This
->pwszId
= (WCHAR
*)QUARTZ_AllocMem( This
->cbIdLen
);
618 if ( This
->pwszId
== NULL
)
623 memcpy( This
->pwszId
, pwszId
, This
->cbIdLen
);
628 CPinBaseImpl_UninitIPin( This
);
632 void CPinBaseImpl_UninitIPin( CPinBaseImpl
* This
)
634 TRACE("(%p)\n",This
);
636 IPin_Disconnect( (IPin
*)(This
) );
638 if ( This
->pwszId
!= NULL
)
640 QUARTZ_FreeMem( This
->pwszId
);
646 /***************************************************************************
648 * CMemInputPinBaseImpl
653 static HRESULT WINAPI
654 CMemInputPinBaseImpl_fnQueryInterface(IMemInputPin
* iface
,REFIID riid
,void** ppobj
)
656 ICOM_THIS(CMemInputPinBaseImpl
,iface
);
658 TRACE("(%p)->()\n",This
);
660 return IUnknown_QueryInterface(This
->punkControl
,riid
,ppobj
);
664 CMemInputPinBaseImpl_fnAddRef(IMemInputPin
* iface
)
666 ICOM_THIS(CMemInputPinBaseImpl
,iface
);
668 TRACE("(%p)->()\n",This
);
670 return IUnknown_AddRef(This
->punkControl
);
674 CMemInputPinBaseImpl_fnRelease(IMemInputPin
* iface
)
676 ICOM_THIS(CMemInputPinBaseImpl
,iface
);
678 TRACE("(%p)->()\n",This
);
680 return IUnknown_Release(This
->punkControl
);
684 static HRESULT WINAPI
685 CMemInputPinBaseImpl_fnGetAllocator(IMemInputPin
* iface
,IMemAllocator
** ppAllocator
)
687 ICOM_THIS(CMemInputPinBaseImpl
,iface
);
688 HRESULT hr
= NOERROR
;
691 TRACE("(%p)->()\n",This
);
693 if ( ppAllocator
== NULL
)
696 EnterCriticalSection( This
->pPin
->pcsPin
);
698 if ( This
->pAllocator
== NULL
)
700 hr
= QUARTZ_CreateMemoryAllocator(NULL
,(void**)&punk
);
703 hr
= IUnknown_QueryInterface(punk
,
704 &IID_IMemAllocator
,(void**)&This
->pAllocator
);
705 IUnknown_Release(punk
);
711 *ppAllocator
= This
->pAllocator
;
712 IMemAllocator_AddRef(This
->pAllocator
);
715 LeaveCriticalSection( This
->pPin
->pcsPin
);
720 static HRESULT WINAPI
721 CMemInputPinBaseImpl_fnNotifyAllocator(IMemInputPin
* iface
,IMemAllocator
* pAllocator
,BOOL bReadonly
)
723 ICOM_THIS(CMemInputPinBaseImpl
,iface
);
725 TRACE("(%p)->()\n",This
);
727 if ( pAllocator
== NULL
)
730 EnterCriticalSection( This
->pPin
->pcsPin
);
732 if ( This
->pAllocator
!= NULL
)
734 IMemAllocator_Release(This
->pAllocator
);
735 This
->pAllocator
= NULL
;
737 This
->pAllocator
= pAllocator
;
738 IMemAllocator_AddRef(This
->pAllocator
);
740 This
->bReadonly
= bReadonly
;
742 LeaveCriticalSection( This
->pPin
->pcsPin
);
747 static HRESULT WINAPI
748 CMemInputPinBaseImpl_fnGetAllocatorRequirements(IMemInputPin
* iface
,ALLOCATOR_PROPERTIES
* pProp
)
750 ICOM_THIS(CMemInputPinBaseImpl
,iface
);
752 TRACE("(%p)->(%p)\n",This
,pProp
);
757 /* E_MOTIMPL means 'no requirements' */
761 static HRESULT WINAPI
762 CMemInputPinBaseImpl_fnReceive(IMemInputPin
* iface
,IMediaSample
* pSample
)
764 ICOM_THIS(CMemInputPinBaseImpl
,iface
);
765 HRESULT hr
= E_NOTIMPL
;
767 TRACE("(%p)->(%p)\n",This
,pSample
);
769 EnterCriticalSection( This
->pPin
->pcsPin
);
770 if ( This
->pPin
->pHandlers
->pReceive
!= NULL
)
771 hr
= This
->pPin
->pHandlers
->pReceive(This
->pPin
,pSample
);
772 LeaveCriticalSection( This
->pPin
->pcsPin
);
777 static HRESULT WINAPI
778 CMemInputPinBaseImpl_fnReceiveMultiple(IMemInputPin
* iface
,IMediaSample
** ppSample
,long nSample
,long* pnSampleProcessed
)
780 ICOM_THIS(CMemInputPinBaseImpl
,iface
);
784 TRACE("(%p)->()\n",This
);
786 if ( ppSample
== NULL
|| pnSampleProcessed
== NULL
)
790 for ( n
= 0; n
< nSample
; n
++ )
792 hr
= IMemInputPin_Receive(iface
,ppSample
[n
]);
797 *pnSampleProcessed
= n
;
801 static HRESULT WINAPI
802 CMemInputPinBaseImpl_fnReceiveCanBlock(IMemInputPin
* iface
)
804 ICOM_THIS(CMemInputPinBaseImpl
,iface
);
805 HRESULT hr
= E_NOTIMPL
;
807 TRACE("(%p)->()\n",This
);
809 EnterCriticalSection( This
->pPin
->pcsPin
);
810 if ( This
->pPin
->pHandlers
->pReceiveCanBlock
!= NULL
)
811 hr
= This
->pPin
->pHandlers
->pReceiveCanBlock(This
->pPin
);
812 LeaveCriticalSection( This
->pPin
->pcsPin
);
818 static ICOM_VTABLE(IMemInputPin
) imeminputpin
=
820 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
821 /* IUnknown fields */
822 CMemInputPinBaseImpl_fnQueryInterface
,
823 CMemInputPinBaseImpl_fnAddRef
,
824 CMemInputPinBaseImpl_fnRelease
,
825 /* IMemInputPin fields */
826 CMemInputPinBaseImpl_fnGetAllocator
,
827 CMemInputPinBaseImpl_fnNotifyAllocator
,
828 CMemInputPinBaseImpl_fnGetAllocatorRequirements
,
829 CMemInputPinBaseImpl_fnReceive
,
830 CMemInputPinBaseImpl_fnReceiveMultiple
,
831 CMemInputPinBaseImpl_fnReceiveCanBlock
,
834 HRESULT
CMemInputPinBaseImpl_InitIMemInputPin(
835 CMemInputPinBaseImpl
* This
, IUnknown
* punkControl
,
838 TRACE("(%p,%p)\n",This
,punkControl
);
840 if ( punkControl
== NULL
)
842 ERR( "punkControl must not be NULL\n" );
846 ICOM_VTBL(This
) = &imeminputpin
;
847 This
->punkControl
= punkControl
;
849 This
->pAllocator
= NULL
;
850 This
->bReadonly
= FALSE
;
855 void CMemInputPinBaseImpl_UninitIMemInputPin(
856 CMemInputPinBaseImpl
* This
)
858 TRACE("(%p)\n",This
);
860 if ( This
->pAllocator
!= NULL
)
862 IMemAllocator_Release(This
->pAllocator
);
863 This
->pAllocator
= NULL
;
867 /***************************************************************************
869 * CQualityControlPassThruImpl
873 static HRESULT WINAPI
874 CQualityControlPassThruImpl_fnQueryInterface(IQualityControl
* iface
,REFIID riid
,void** ppobj
)
876 ICOM_THIS(CQualityControlPassThruImpl
,iface
);
878 TRACE("(%p)->()\n",This
);
880 return IUnknown_QueryInterface(This
->punkControl
,riid
,ppobj
);
884 CQualityControlPassThruImpl_fnAddRef(IQualityControl
* iface
)
886 ICOM_THIS(CQualityControlPassThruImpl
,iface
);
888 TRACE("(%p)->()\n",This
);
890 return IUnknown_AddRef(This
->punkControl
);
894 CQualityControlPassThruImpl_fnRelease(IQualityControl
* iface
)
896 ICOM_THIS(CQualityControlPassThruImpl
,iface
);
898 TRACE("(%p)->()\n",This
);
900 return IUnknown_Release(This
->punkControl
);
904 static HRESULT WINAPI
905 CQualityControlPassThruImpl_fnNotify(IQualityControl
* iface
,IBaseFilter
* pFilter
,Quality q
)
907 ICOM_THIS(CQualityControlPassThruImpl
,iface
);
908 HRESULT hr
= S_FALSE
;
910 TRACE("(%p)->()\n",This
);
912 if ( This
->pControl
!= NULL
)
913 return IQualityControl_Notify( This
->pControl
, pFilter
, q
);
915 EnterCriticalSection( This
->pPin
->pcsPin
);
916 if ( This
->pPin
->pHandlers
->pQualityNotify
!= NULL
)
917 hr
= This
->pPin
->pHandlers
->pQualityNotify(This
->pPin
,pFilter
,q
);
918 LeaveCriticalSection( This
->pPin
->pcsPin
);
923 static HRESULT WINAPI
924 CQualityControlPassThruImpl_fnSetSink(IQualityControl
* iface
,IQualityControl
* pControl
)
926 ICOM_THIS(CQualityControlPassThruImpl
,iface
);
928 TRACE("(%p)->()\n",This
);
930 This
->pControl
= pControl
; /* AddRef() must not be called */
935 static ICOM_VTABLE(IQualityControl
) iqualitycontrol
=
937 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
938 /* IUnknown fields */
939 CQualityControlPassThruImpl_fnQueryInterface
,
940 CQualityControlPassThruImpl_fnAddRef
,
941 CQualityControlPassThruImpl_fnRelease
,
942 /* IQualityControl fields */
943 CQualityControlPassThruImpl_fnNotify
,
944 CQualityControlPassThruImpl_fnSetSink
,
947 HRESULT
CQualityControlPassThruImpl_InitIQualityControl(
948 CQualityControlPassThruImpl
* This
, IUnknown
* punkControl
,
951 TRACE("(%p,%p)\n",This
,punkControl
);
953 if ( punkControl
== NULL
)
955 ERR( "punkControl must not be NULL\n" );
959 ICOM_VTBL(This
) = &iqualitycontrol
;
960 This
->punkControl
= punkControl
;
966 void CQualityControlPassThruImpl_UninitIQualityControl(
967 CQualityControlPassThruImpl
* This
)
971 /***************************************************************************
973 * helper methods for output pins.
977 HRESULT
CPinBaseImpl_SendSample( CPinBaseImpl
* This
, IMediaSample
* pSample
)
979 if ( This
->pHandlers
->pReceive
== NULL
)
982 return This
->pHandlers
->pReceive( This
, pSample
);
985 HRESULT
CPinBaseImpl_SendReceiveCanBlock( CPinBaseImpl
* This
)
987 if ( This
->pHandlers
->pReceiveCanBlock
== NULL
)
990 return This
->pHandlers
->pReceiveCanBlock( This
);
993 HRESULT
CPinBaseImpl_SendEndOfStream( CPinBaseImpl
* This
)
995 if ( This
->pHandlers
->pEndOfStream
== NULL
)
998 return This
->pHandlers
->pEndOfStream( This
);
1001 HRESULT
CPinBaseImpl_SendBeginFlush( CPinBaseImpl
* This
)
1003 if ( This
->pHandlers
->pBeginFlush
== NULL
)
1006 return This
->pHandlers
->pBeginFlush( This
);
1009 HRESULT
CPinBaseImpl_SendEndFlush( CPinBaseImpl
* This
)
1011 if ( This
->pHandlers
->pEndFlush
== NULL
)
1014 return This
->pHandlers
->pEndFlush( This
);
1017 HRESULT
CPinBaseImpl_SendNewSegment( CPinBaseImpl
* This
, REFERENCE_TIME rtStart
, REFERENCE_TIME rtStop
, double rate
)
1019 if ( This
->pHandlers
->pNewSegment
== NULL
)
1022 return This
->pHandlers
->pNewSegment( This
, rtStart
, rtStop
, rate
);
1027 /***************************************************************************
1029 * handlers for output pins.
1033 HRESULT
OutputPinSync_Receive( CPinBaseImpl
* pImpl
, IMediaSample
* pSample
)
1035 if ( pImpl
->pMemInputPinConnectedTo
== NULL
)
1038 return IMemInputPin_Receive(pImpl
->pMemInputPinConnectedTo
,pSample
);
1041 HRESULT
OutputPinSync_ReceiveCanBlock( CPinBaseImpl
* pImpl
)
1043 if ( pImpl
->pMemInputPinConnectedTo
== NULL
)
1046 return IMemInputPin_ReceiveCanBlock(pImpl
->pMemInputPinConnectedTo
);
1049 HRESULT
OutputPinSync_EndOfStream( CPinBaseImpl
* pImpl
)
1051 if ( pImpl
->pPinConnectedTo
== NULL
)
1054 return IPin_EndOfStream(pImpl
->pPinConnectedTo
);
1057 HRESULT
OutputPinSync_BeginFlush( CPinBaseImpl
* pImpl
)
1059 if ( pImpl
->pPinConnectedTo
== NULL
)
1062 return IPin_BeginFlush(pImpl
->pPinConnectedTo
);
1065 HRESULT
OutputPinSync_EndFlush( CPinBaseImpl
* pImpl
)
1067 if ( pImpl
->pPinConnectedTo
== NULL
)
1070 return IPin_EndFlush(pImpl
->pPinConnectedTo
);
1073 HRESULT
OutputPinSync_NewSegment( CPinBaseImpl
* pImpl
, REFERENCE_TIME rtStart
, REFERENCE_TIME rtStop
, double rate
)
1075 if ( pImpl
->pPinConnectedTo
== NULL
)
1078 return IPin_NewSegment(pImpl
->pPinConnectedTo
,rtStart
,rtStop
,rate
);
1081 /***************************************************************************
1083 * handlers for output pins (async).
1087 typedef struct OutputPinTask OutputPinTask
;
1089 enum OutputPinTaskType
1093 OutTask_EndOfStream
,
1099 struct OutputPinTask
1101 OutputPinTask
* pNext
;
1102 enum OutputPinTaskType tasktype
;
1103 IMediaSample
* pSample
;
1104 REFERENCE_TIME rtStart
;
1105 REFERENCE_TIME rtStop
;
1109 struct OutputPinAsyncImpl
1111 HANDLE m_hTaskThread
;
1112 HANDLE m_hTaskEvent
;
1113 IPin
* m_pPin
; /* connected pin */
1114 IMemInputPin
* m_pMemInputPin
; /* connected pin */
1115 CRITICAL_SECTION m_csTasks
;
1116 OutputPinTask
* m_pFirst
;
1117 OutputPinTask
* m_pLast
;
1118 OutputPinTask
* m_pTaskExitThread
;
1121 static OutputPinTask
* OutputPinAsync_AllocTask( enum OutputPinTaskType tasktype
)
1123 OutputPinTask
* pTask
;
1125 pTask
= (OutputPinTask
*)QUARTZ_AllocMem( sizeof(OutputPinTask
) );
1126 pTask
->pNext
= NULL
;
1127 pTask
->tasktype
= tasktype
;
1128 pTask
->pSample
= NULL
;
1133 static void OutputPinAsync_FreeTask( OutputPinTask
* pTask
)
1135 if ( pTask
->pSample
!= NULL
)
1136 IMediaSample_Release( pTask
->pSample
);
1137 QUARTZ_FreeMem( pTask
);
1140 static void OutputPinAsync_AddTask( OutputPinAsyncImpl
* This
, OutputPinTask
* pTask
, BOOL bFirst
)
1142 EnterCriticalSection( &This
->m_csTasks
);
1146 pTask
->pNext
= This
->m_pFirst
;
1147 This
->m_pFirst
= pTask
;
1148 if ( This
->m_pLast
== NULL
)
1149 This
->m_pLast
= pTask
;
1153 if ( This
->m_pLast
!= NULL
)
1154 This
->m_pLast
->pNext
= pTask
;
1156 This
->m_pFirst
= pTask
;
1157 This
->m_pLast
= pTask
;
1160 LeaveCriticalSection( &This
->m_csTasks
);
1162 SetEvent( This
->m_hTaskEvent
);
1165 static OutputPinTask
* OutputPinAsync_GetNextTask( OutputPinAsyncImpl
* This
)
1167 OutputPinTask
* pTask
;
1169 EnterCriticalSection( &This
->m_csTasks
);
1170 pTask
= This
->m_pFirst
;
1171 if ( pTask
!= NULL
)
1173 This
->m_pFirst
= pTask
->pNext
;
1174 if ( This
->m_pFirst
== NULL
)
1175 This
->m_pLast
= NULL
;
1177 SetEvent( This
->m_hTaskEvent
);
1180 LeaveCriticalSection( &This
->m_csTasks
);
1185 static DWORD WINAPI
OutputPinAsync_ThreadEntry( LPVOID pv
)
1187 OutputPinAsyncImpl
* This
= ((CPinBaseImpl
*)pv
)->pAsyncOut
;
1188 OutputPinTask
* pTask
;
1190 BOOL bInFlush
= FALSE
;
1195 WaitForSingleObject( This
->m_hTaskEvent
, INFINITE
);
1196 ResetEvent( This
->m_hTaskEvent
);
1198 pTask
= OutputPinAsync_GetNextTask( This
);
1199 if ( pTask
== NULL
)
1203 switch ( pTask
->tasktype
)
1205 case OutTask_ExitThread
:
1208 case OutTask_Receive
:
1210 hr
= IMemInputPin_Receive( This
->m_pMemInputPin
, pTask
->pSample
);
1212 case OutTask_EndOfStream
:
1213 hr
= IPin_EndOfStream( This
->m_pPin
);
1215 case OutTask_BeginFlush
:
1217 hr
= IPin_BeginFlush( This
->m_pPin
);
1219 case OutTask_EndFlush
:
1221 hr
= IPin_EndFlush( This
->m_pPin
);
1223 case OutTask_NewSegment
:
1224 hr
= IPin_NewSegment( This
->m_pPin
, pTask
->rtStart
, pTask
->rtStop
, pTask
->rate
);
1227 ERR( "unexpected task type %d.\n", pTask
->tasktype
);
1232 OutputPinAsync_FreeTask( pTask
);
1236 ERR( "hresult %08lx\n", hr
);
1244 HRESULT
OutputPinAsync_OnActive( CPinBaseImpl
* pImpl
)
1249 FIXME("(%p)\n",pImpl
);
1251 if ( pImpl
->pMemInputPinConnectedTo
== NULL
)
1254 pImpl
->pAsyncOut
= (OutputPinAsyncImpl
*)
1255 QUARTZ_AllocMem( sizeof( OutputPinAsyncImpl
) );
1256 if ( pImpl
->pAsyncOut
== NULL
)
1257 return E_OUTOFMEMORY
;
1259 InitializeCriticalSection( &pImpl
->pAsyncOut
->m_csTasks
);
1260 pImpl
->pAsyncOut
->m_hTaskThread
= (HANDLE
)NULL
;
1261 pImpl
->pAsyncOut
->m_hTaskEvent
= (HANDLE
)NULL
;
1262 pImpl
->pAsyncOut
->m_pFirst
= NULL
;
1263 pImpl
->pAsyncOut
->m_pLast
= NULL
;
1264 pImpl
->pAsyncOut
->m_pTaskExitThread
= NULL
;
1265 pImpl
->pAsyncOut
->m_pPin
= pImpl
->pPinConnectedTo
;
1266 pImpl
->pAsyncOut
->m_pMemInputPin
= pImpl
->pMemInputPinConnectedTo
;
1268 pImpl
->pAsyncOut
->m_hTaskEvent
=
1269 CreateEventA( NULL
, TRUE
, FALSE
, NULL
);
1270 if ( pImpl
->pAsyncOut
->m_hTaskEvent
== (HANDLE
)NULL
)
1276 pImpl
->pAsyncOut
->m_pTaskExitThread
=
1277 OutputPinAsync_AllocTask( OutTask_ExitThread
);
1278 if ( pImpl
->pAsyncOut
->m_pTaskExitThread
== NULL
)
1284 pImpl
->pAsyncOut
->m_hTaskThread
= CreateThread(
1285 NULL
, 0, OutputPinAsync_ThreadEntry
, pImpl
,
1287 if ( pImpl
->pAsyncOut
->m_hTaskThread
== (HANDLE
)NULL
)
1295 OutputPinAsync_OnInactive( pImpl
);
1299 HRESULT
OutputPinAsync_OnInactive( CPinBaseImpl
* pImpl
)
1301 OutputPinTask
* pTask
;
1303 FIXME("(%p)\n",pImpl
);
1305 if ( pImpl
->pAsyncOut
== NULL
)
1308 if ( pImpl
->pAsyncOut
->m_pTaskExitThread
!= NULL
)
1310 OutputPinAsync_AddTask( pImpl
->pAsyncOut
, pImpl
->pAsyncOut
->m_pTaskExitThread
, TRUE
);
1311 pImpl
->pAsyncOut
->m_pTaskExitThread
= NULL
;
1314 if ( pImpl
->pAsyncOut
->m_hTaskThread
!= (HANDLE
)NULL
)
1316 WaitForSingleObject( pImpl
->pAsyncOut
->m_hTaskThread
, INFINITE
);
1317 CloseHandle( pImpl
->pAsyncOut
->m_hTaskThread
);
1319 if ( pImpl
->pAsyncOut
->m_hTaskEvent
!= (HANDLE
)NULL
)
1320 CloseHandle( pImpl
->pAsyncOut
->m_hTaskEvent
);
1322 /* release all tasks. */
1325 pTask
= OutputPinAsync_GetNextTask( pImpl
->pAsyncOut
);
1326 if ( pTask
== NULL
)
1328 OutputPinAsync_FreeTask( pTask
);
1331 DeleteCriticalSection( &pImpl
->pAsyncOut
->m_csTasks
);
1333 QUARTZ_FreeMem( pImpl
->pAsyncOut
);
1334 pImpl
->pAsyncOut
= NULL
;
1339 HRESULT
OutputPinAsync_Receive( CPinBaseImpl
* pImpl
, IMediaSample
* pSample
)
1341 OutputPinAsyncImpl
* This
= pImpl
->pAsyncOut
;
1342 OutputPinTask
* pTask
;
1344 TRACE("(%p,%p)\n",pImpl
,pSample
);
1349 pTask
= OutputPinAsync_AllocTask( OutTask_Receive
);
1350 if ( pTask
== NULL
)
1351 return E_OUTOFMEMORY
;
1352 pTask
->pSample
= pSample
; IMediaSample_AddRef( pSample
);
1353 OutputPinAsync_AddTask( pImpl
->pAsyncOut
, pTask
, FALSE
);
1358 HRESULT
OutputPinAsync_ReceiveCanBlock( CPinBaseImpl
* pImpl
)
1363 HRESULT
OutputPinAsync_EndOfStream( CPinBaseImpl
* pImpl
)
1365 OutputPinAsyncImpl
* This
= pImpl
->pAsyncOut
;
1366 OutputPinTask
* pTask
;
1368 TRACE("(%p)\n",pImpl
);
1373 pTask
= OutputPinAsync_AllocTask( OutTask_EndOfStream
);
1374 if ( pTask
== NULL
)
1375 return E_OUTOFMEMORY
;
1376 OutputPinAsync_AddTask( pImpl
->pAsyncOut
, pTask
, FALSE
);
1381 HRESULT
OutputPinAsync_BeginFlush( CPinBaseImpl
* pImpl
)
1383 OutputPinAsyncImpl
* This
= pImpl
->pAsyncOut
;
1384 OutputPinTask
* pTask
;
1386 TRACE("(%p)\n",pImpl
);
1391 pTask
= OutputPinAsync_AllocTask( OutTask_BeginFlush
);
1392 if ( pTask
== NULL
)
1393 return E_OUTOFMEMORY
;
1394 OutputPinAsync_AddTask( pImpl
->pAsyncOut
, pTask
, TRUE
);
1399 HRESULT
OutputPinAsync_EndFlush( CPinBaseImpl
* pImpl
)
1401 OutputPinAsyncImpl
* This
= pImpl
->pAsyncOut
;
1402 OutputPinTask
* pTask
;
1404 TRACE("(%p)\n",pImpl
);
1409 pTask
= OutputPinAsync_AllocTask( OutTask_EndFlush
);
1410 if ( pTask
== NULL
)
1411 return E_OUTOFMEMORY
;
1412 OutputPinAsync_AddTask( pImpl
->pAsyncOut
, pTask
, FALSE
);
1417 HRESULT
OutputPinAsync_NewSegment( CPinBaseImpl
* pImpl
, REFERENCE_TIME rtStart
, REFERENCE_TIME rtStop
, double rate
)
1419 OutputPinAsyncImpl
* This
= pImpl
->pAsyncOut
;
1420 OutputPinTask
* pTask
;
1422 TRACE("(%p)\n",pImpl
);
1427 pTask
= OutputPinAsync_AllocTask( OutTask_NewSegment
);
1428 if ( pTask
== NULL
)
1429 return E_OUTOFMEMORY
;
1430 pTask
->rtStart
= rtStart
;
1431 pTask
->rtStop
= rtStop
;
1433 OutputPinAsync_AddTask( pImpl
->pAsyncOut
, pTask
, FALSE
);