2 * Implements IPin and IMemInputPin. (internal)
4 * hidenori@a2.ctktv.ne.jp
14 #include "wine/obj_base.h"
17 #include "wine/unicode.h"
19 #include "debugtools.h"
20 DEFAULT_DEBUG_CHANNEL(quartz
);
22 #include "quartz_private.h"
27 /***************************************************************************
34 CPinBaseImpl_fnQueryInterface(IPin
* iface
,REFIID riid
,void** ppobj
)
36 ICOM_THIS(CPinBaseImpl
,iface
);
38 TRACE("(%p)->()\n",This
);
40 return IUnknown_QueryInterface(This
->punkControl
,riid
,ppobj
);
44 CPinBaseImpl_fnAddRef(IPin
* iface
)
46 ICOM_THIS(CPinBaseImpl
,iface
);
48 TRACE("(%p)->()\n",This
);
50 return IUnknown_AddRef(This
->punkControl
);
54 CPinBaseImpl_fnRelease(IPin
* iface
)
56 ICOM_THIS(CPinBaseImpl
,iface
);
58 TRACE("(%p)->()\n",This
);
60 return IUnknown_Release(This
->punkControl
);
64 CPinBaseImpl_fnConnect(IPin
* iface
,IPin
* pPin
,const AM_MEDIA_TYPE
* pmt
)
66 ICOM_THIS(CPinBaseImpl
,iface
);
67 HRESULT hr
= E_NOTIMPL
;
70 FIXME("(%p)->(%p,%p) stub!\n",This
,pPin
,pmt
);
77 TRACE("try to connect to %p\n",pPin
);
79 EnterCriticalSection( This
->pcsPin
);
81 if ( This
->pPinConnectedTo
!= NULL
)
83 hr
= VFW_E_ALREADY_CONNECTED
;
87 /* FIXME - return fail if running */
89 if ( This
->pHandlers
->pOnPreConnect
!= NULL
)
91 hr
= This
->pHandlers
->pOnPreConnect(This
,pPin
);
98 hr
= IPin_QueryAccept(iface
,pmt
);
101 hr
= IPin_ReceiveConnection(pPin
,iface
,pmt
);
107 for ( i
= 0; i
< This
->cAcceptTypes
; i
++ )
109 pmt
= &This
->pmtAcceptTypes
[i
];
110 hr
= IPin_QueryAccept(iface
,pmt
);
113 hr
= IPin_ReceiveConnection(pPin
,iface
,pmt
);
121 hr
= VFW_E_TYPE_NOT_ACCEPTED
;
126 This
->pmtConn
= QUARTZ_MediaType_Duplicate( pmt
);
127 if ( This
->pmtConn
== NULL
)
130 IPin_Disconnect(pPin
);
134 This
->pPinConnectedTo
= pPin
; IPin_AddRef(pPin
);
135 hr
= IPin_QueryInterface(pPin
,&IID_IMemInputPin
,(void**)&This
->pMemInputPinConnectedTo
);
138 IPin_Disconnect(pPin
);
142 if ( This
->pHandlers
->pOnPostConnect
!= NULL
)
144 hr
= This
->pHandlers
->pOnPostConnect(This
,pPin
);
147 IPin_Disconnect(pPin
);
157 IPin_Disconnect(iface
);
159 LeaveCriticalSection( This
->pcsPin
);
164 static HRESULT WINAPI
165 CPinBaseImpl_fnReceiveConnection(IPin
* iface
,IPin
* pPin
,const AM_MEDIA_TYPE
* pmt
)
167 ICOM_THIS(CPinBaseImpl
,iface
);
168 HRESULT hr
= E_NOTIMPL
;
170 FIXME("(%p)->(%p,%p) stub!\n",This
,pPin
,pmt
);
174 if ( pPin
== NULL
|| pmt
== NULL
)
177 EnterCriticalSection( This
->pcsPin
);
179 if ( This
->pPinConnectedTo
!= NULL
)
181 hr
= VFW_E_ALREADY_CONNECTED
;
185 /* FIXME - return fail if running */
187 if ( This
->pHandlers
->pOnPreConnect
!= NULL
)
189 hr
= This
->pHandlers
->pOnPreConnect(This
,pPin
);
194 hr
= IPin_QueryAccept(iface
,pmt
);
198 This
->pmtConn
= QUARTZ_MediaType_Duplicate( pmt
);
199 if ( This
->pmtConn
== NULL
)
205 if ( This
->pHandlers
->pOnPostConnect
!= NULL
)
207 hr
= This
->pHandlers
->pOnPostConnect(This
,pPin
);
213 This
->pPinConnectedTo
= pPin
; IPin_AddRef(pPin
);
217 IPin_Disconnect(iface
);
218 LeaveCriticalSection( This
->pcsPin
);
223 static HRESULT WINAPI
224 CPinBaseImpl_fnDisconnect(IPin
* iface
)
226 ICOM_THIS(CPinBaseImpl
,iface
);
227 HRESULT hr
= NOERROR
;
229 FIXME("(%p)->() stub!\n",This
);
231 EnterCriticalSection( This
->pcsPin
);
233 /* FIXME - return fail if running */
235 if ( This
->pHandlers
->pOnDisconnect
!= NULL
)
236 hr
= This
->pHandlers
->pOnDisconnect(This
);
238 if ( This
->pmtConn
!= NULL
)
240 QUARTZ_MediaType_Destroy( This
->pmtConn
);
241 This
->pmtConn
= NULL
;
243 if ( This
->pMemInputPinConnectedTo
!= NULL
)
245 IMemInputPin_Release(This
->pMemInputPinConnectedTo
);
246 This
->pMemInputPinConnectedTo
= NULL
;
248 if ( This
->pPinConnectedTo
!= NULL
)
250 /* FIXME - cleanup */
252 IPin_Release(This
->pPinConnectedTo
);
253 This
->pPinConnectedTo
= NULL
;
258 hr
= S_FALSE
; /* FIXME - is this correct??? */
261 LeaveCriticalSection( This
->pcsPin
);
266 static HRESULT WINAPI
267 CPinBaseImpl_fnConnectedTo(IPin
* iface
,IPin
** ppPin
)
269 ICOM_THIS(CPinBaseImpl
,iface
);
270 HRESULT hr
= VFW_E_NOT_CONNECTED
;
272 TRACE("(%p)->(%p)\n",This
,ppPin
);
277 EnterCriticalSection( This
->pcsPin
);
279 *ppPin
= This
->pPinConnectedTo
;
280 if ( This
->pPinConnectedTo
!= NULL
)
282 IPin_AddRef(This
->pPinConnectedTo
);
286 LeaveCriticalSection( This
->pcsPin
);
291 static HRESULT WINAPI
292 CPinBaseImpl_fnConnectionMediaType(IPin
* iface
,AM_MEDIA_TYPE
* pmt
)
294 ICOM_THIS(CPinBaseImpl
,iface
);
297 TRACE("(%p)->(%p)\n",This
,pmt
);
302 EnterCriticalSection( This
->pcsPin
);
304 if ( This
->pmtConn
!= NULL
)
306 hr
= QUARTZ_MediaType_Copy( pmt
, This
->pmtConn
);
310 ZeroMemory( pmt
, sizeof(AM_MEDIA_TYPE
) );
311 pmt
->bFixedSizeSamples
= TRUE
;
312 pmt
->lSampleSize
= 1;
316 LeaveCriticalSection( This
->pcsPin
);
321 static HRESULT WINAPI
322 CPinBaseImpl_fnQueryPinInfo(IPin
* iface
,PIN_INFO
* pinfo
)
324 ICOM_THIS(CPinBaseImpl
,iface
);
326 TRACE("(%p)->(%p)\n",This
,pinfo
);
331 EnterCriticalSection( This
->pcsPin
);
333 ZeroMemory( pinfo
, sizeof(PIN_INFO
) );
334 pinfo
->pFilter
= (IBaseFilter
*)(This
->pFilter
);
335 if ( pinfo
->pFilter
!= NULL
)
336 IBaseFilter_AddRef( pinfo
->pFilter
);
337 pinfo
->dir
= This
->bOutput
? PINDIR_OUTPUT
: PINDIR_INPUT
;
338 if ( This
->cbIdLen
<= sizeof(pinfo
->achName
) )
339 memcpy( pinfo
->achName
, This
->pwszId
, This
->cbIdLen
);
342 memcpy( pinfo
->achName
, This
->pwszId
, sizeof(pinfo
->achName
) );
343 pinfo
->achName
[sizeof(pinfo
->achName
)/sizeof(pinfo
->achName
[0])-1] = 0;
346 LeaveCriticalSection( This
->pcsPin
);
351 static HRESULT WINAPI
352 CPinBaseImpl_fnQueryDirection(IPin
* iface
,PIN_DIRECTION
* pdir
)
354 ICOM_THIS(CPinBaseImpl
,iface
);
356 TRACE("(%p)->(%p)\n",This
,pdir
);
361 *pdir
= This
->bOutput
? PINDIR_OUTPUT
: PINDIR_INPUT
;
366 static HRESULT WINAPI
367 CPinBaseImpl_fnQueryId(IPin
* iface
,LPWSTR
* lpwszId
)
369 ICOM_THIS(CPinBaseImpl
,iface
);
371 TRACE("(%p)->(%p)\n",This
,lpwszId
);
373 if ( lpwszId
== NULL
)
376 *lpwszId
= (WCHAR
*)CoTaskMemAlloc( This
->cbIdLen
);
377 if ( *lpwszId
== NULL
)
378 return E_OUTOFMEMORY
;
379 memcpy( *lpwszId
, This
->pwszId
, This
->cbIdLen
);
384 static HRESULT WINAPI
385 CPinBaseImpl_fnQueryAccept(IPin
* iface
,const AM_MEDIA_TYPE
* pmt
)
387 ICOM_THIS(CPinBaseImpl
,iface
);
390 TRACE("(%p)->(%p)\n",This
,pmt
);
396 EnterCriticalSection( This
->pcsPin
);
397 if ( This
->pHandlers
->pCheckMediaType
!= NULL
)
398 hr
= This
->pHandlers
->pCheckMediaType(This
,pmt
);
399 LeaveCriticalSection( This
->pcsPin
);
404 static HRESULT WINAPI
405 CPinBaseImpl_fnEnumMediaTypes(IPin
* iface
,IEnumMediaTypes
** ppenum
)
407 ICOM_THIS(CPinBaseImpl
,iface
);
410 TRACE("(%p)->(%p)\n",This
,ppenum
);
412 if ( ppenum
== NULL
)
417 EnterCriticalSection( This
->pcsPin
);
418 if ( This
->cAcceptTypes
> 0 )
419 hr
= QUARTZ_CreateEnumMediaTypes(
420 ppenum
, This
->pmtAcceptTypes
, This
->cAcceptTypes
);
421 LeaveCriticalSection( This
->pcsPin
);
426 static HRESULT WINAPI
427 CPinBaseImpl_fnQueryInternalConnections(IPin
* iface
,IPin
** ppPin
,ULONG
* pul
)
429 ICOM_THIS(CPinBaseImpl
,iface
);
431 TRACE("(%p)->(%p,%p)\n",This
,ppPin
,pul
);
433 /* E_NOTIMPL means 'no internal connections'. */
437 static HRESULT WINAPI
438 CPinBaseImpl_fnEndOfStream(IPin
* iface
)
440 ICOM_THIS(CPinBaseImpl
,iface
);
441 HRESULT hr
= E_NOTIMPL
;
443 TRACE("(%p)->()\n",This
);
448 EnterCriticalSection( This
->pcsPin
);
449 if ( This
->pHandlers
->pEndOfStream
!= NULL
)
450 hr
= This
->pHandlers
->pEndOfStream(This
);
451 LeaveCriticalSection( This
->pcsPin
);
456 static HRESULT WINAPI
457 CPinBaseImpl_fnBeginFlush(IPin
* iface
)
459 ICOM_THIS(CPinBaseImpl
,iface
);
460 HRESULT hr
= E_NOTIMPL
;
462 TRACE("(%p)->()\n",This
);
467 EnterCriticalSection( This
->pcsPin
);
468 if ( This
->pHandlers
->pBeginFlush
!= NULL
)
469 hr
= This
->pHandlers
->pBeginFlush(This
);
470 LeaveCriticalSection( This
->pcsPin
);
475 static HRESULT WINAPI
476 CPinBaseImpl_fnEndFlush(IPin
* iface
)
478 ICOM_THIS(CPinBaseImpl
,iface
);
479 HRESULT hr
= E_NOTIMPL
;
481 TRACE("(%p)->()\n",This
);
486 EnterCriticalSection( This
->pcsPin
);
487 if ( This
->pHandlers
->pEndFlush
!= NULL
)
488 hr
= This
->pHandlers
->pEndFlush(This
);
489 LeaveCriticalSection( This
->pcsPin
);
494 static HRESULT WINAPI
495 CPinBaseImpl_fnNewSegment(IPin
* iface
,REFERENCE_TIME rtStart
,REFERENCE_TIME rtStop
,double rate
)
497 ICOM_THIS(CPinBaseImpl
,iface
);
498 HRESULT hr
= E_NOTIMPL
;
500 TRACE("(%p)->()\n",This
);
505 EnterCriticalSection( This
->pcsPin
);
506 if ( This
->pHandlers
->pNewSegment
!= NULL
)
507 hr
= This
->pHandlers
->pNewSegment(This
,rtStart
,rtStop
,rate
);
508 LeaveCriticalSection( This
->pcsPin
);
516 static ICOM_VTABLE(IPin
) ipin
=
518 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
519 /* IUnknown fields */
520 CPinBaseImpl_fnQueryInterface
,
521 CPinBaseImpl_fnAddRef
,
522 CPinBaseImpl_fnRelease
,
524 CPinBaseImpl_fnConnect
,
525 CPinBaseImpl_fnReceiveConnection
,
526 CPinBaseImpl_fnDisconnect
,
527 CPinBaseImpl_fnConnectedTo
,
528 CPinBaseImpl_fnConnectionMediaType
,
529 CPinBaseImpl_fnQueryPinInfo
,
530 CPinBaseImpl_fnQueryDirection
,
531 CPinBaseImpl_fnQueryId
,
532 CPinBaseImpl_fnQueryAccept
,
533 CPinBaseImpl_fnEnumMediaTypes
,
534 CPinBaseImpl_fnQueryInternalConnections
,
535 CPinBaseImpl_fnEndOfStream
,
536 CPinBaseImpl_fnBeginFlush
,
537 CPinBaseImpl_fnEndFlush
,
538 CPinBaseImpl_fnNewSegment
,
542 HRESULT
CPinBaseImpl_InitIPin(
543 CPinBaseImpl
* This
, IUnknown
* punkControl
,
544 CRITICAL_SECTION
* pcsPin
,
545 CBaseFilterImpl
* pFilter
, LPCWSTR pwszId
,
547 const CBasePinHandlers
* pHandlers
)
549 HRESULT hr
= NOERROR
;
551 TRACE("(%p,%p,%p)\n",This
,punkControl
,pFilter
);
553 if ( punkControl
== NULL
)
555 ERR( "punkControl must not be NULL\n" );
559 ICOM_VTBL(This
) = &ipin
;
560 This
->punkControl
= punkControl
;
561 This
->pHandlers
= pHandlers
;
562 This
->cbIdLen
= sizeof(WCHAR
)*(strlenW(pwszId
)+1);
564 This
->bOutput
= bOutput
;
565 This
->pmtAcceptTypes
= NULL
;
566 This
->cAcceptTypes
= 0;
567 This
->pcsPin
= pcsPin
;
568 This
->pFilter
= pFilter
;
569 This
->pPinConnectedTo
= NULL
;
570 This
->pMemInputPinConnectedTo
= NULL
;
571 This
->pmtConn
= NULL
;
572 This
->pAsyncOut
= NULL
;
574 This
->pwszId
= (WCHAR
*)QUARTZ_AllocMem( This
->cbIdLen
);
575 if ( This
->pwszId
== NULL
)
580 memcpy( This
->pwszId
, pwszId
, This
->cbIdLen
);
585 CPinBaseImpl_UninitIPin( This
);
589 void CPinBaseImpl_UninitIPin( CPinBaseImpl
* This
)
591 TRACE("(%p)\n",This
);
593 IPin_Disconnect( (IPin
*)(This
) );
595 if ( This
->pwszId
!= NULL
)
597 QUARTZ_FreeMem( This
->pwszId
);
603 /***************************************************************************
605 * CMemInputPinBaseImpl
610 static HRESULT WINAPI
611 CMemInputPinBaseImpl_fnQueryInterface(IMemInputPin
* iface
,REFIID riid
,void** ppobj
)
613 ICOM_THIS(CMemInputPinBaseImpl
,iface
);
615 TRACE("(%p)->()\n",This
);
617 return IUnknown_QueryInterface(This
->punkControl
,riid
,ppobj
);
621 CMemInputPinBaseImpl_fnAddRef(IMemInputPin
* iface
)
623 ICOM_THIS(CMemInputPinBaseImpl
,iface
);
625 TRACE("(%p)->()\n",This
);
627 return IUnknown_AddRef(This
->punkControl
);
631 CMemInputPinBaseImpl_fnRelease(IMemInputPin
* iface
)
633 ICOM_THIS(CMemInputPinBaseImpl
,iface
);
635 TRACE("(%p)->()\n",This
);
637 return IUnknown_Release(This
->punkControl
);
641 static HRESULT WINAPI
642 CMemInputPinBaseImpl_fnGetAllocator(IMemInputPin
* iface
,IMemAllocator
** ppAllocator
)
644 ICOM_THIS(CMemInputPinBaseImpl
,iface
);
645 HRESULT hr
= NOERROR
;
648 TRACE("(%p)->()\n",This
);
650 if ( ppAllocator
== NULL
)
653 EnterCriticalSection( This
->pPin
->pcsPin
);
655 if ( This
->pAllocator
== NULL
)
657 hr
= QUARTZ_CreateMemoryAllocator(NULL
,(void**)&punk
);
660 hr
= IUnknown_QueryInterface(punk
,
661 &IID_IMemAllocator
,(void**)&This
->pAllocator
);
662 IUnknown_Release(punk
);
668 *ppAllocator
= This
->pAllocator
;
669 IMemAllocator_AddRef(This
->pAllocator
);
672 LeaveCriticalSection( This
->pPin
->pcsPin
);
677 static HRESULT WINAPI
678 CMemInputPinBaseImpl_fnNotifyAllocator(IMemInputPin
* iface
,IMemAllocator
* pAllocator
,BOOL bReadonly
)
680 ICOM_THIS(CMemInputPinBaseImpl
,iface
);
682 TRACE("(%p)->()\n",This
);
684 if ( pAllocator
== NULL
)
687 EnterCriticalSection( This
->pPin
->pcsPin
);
689 if ( This
->pAllocator
!= NULL
)
691 IMemAllocator_Release(This
->pAllocator
);
692 This
->pAllocator
= NULL
;
694 This
->pAllocator
= pAllocator
;
695 IMemAllocator_AddRef(This
->pAllocator
);
697 This
->bReadonly
= bReadonly
;
699 LeaveCriticalSection( This
->pPin
->pcsPin
);
704 static HRESULT WINAPI
705 CMemInputPinBaseImpl_fnGetAllocatorRequirements(IMemInputPin
* iface
,ALLOCATOR_PROPERTIES
* pProp
)
707 ICOM_THIS(CMemInputPinBaseImpl
,iface
);
709 TRACE("(%p)->(%p)\n",This
,pProp
);
714 /* E_MOTIMPL means 'no requirements' */
718 static HRESULT WINAPI
719 CMemInputPinBaseImpl_fnReceive(IMemInputPin
* iface
,IMediaSample
* pSample
)
721 ICOM_THIS(CMemInputPinBaseImpl
,iface
);
722 HRESULT hr
= E_NOTIMPL
;
724 TRACE("(%p)->(%p)\n",This
,pSample
);
726 EnterCriticalSection( This
->pPin
->pcsPin
);
727 if ( This
->pPin
->pHandlers
->pReceive
!= NULL
)
728 hr
= This
->pPin
->pHandlers
->pReceive(This
->pPin
,pSample
);
729 LeaveCriticalSection( This
->pPin
->pcsPin
);
734 static HRESULT WINAPI
735 CMemInputPinBaseImpl_fnReceiveMultiple(IMemInputPin
* iface
,IMediaSample
** ppSample
,long nSample
,long* pnSampleProcessed
)
737 ICOM_THIS(CMemInputPinBaseImpl
,iface
);
741 TRACE("(%p)->()\n",This
);
743 if ( ppSample
== NULL
|| pnSampleProcessed
== NULL
)
746 EnterCriticalSection( This
->pPin
->pcsPin
);
749 for ( n
= 0; n
< nSample
; n
++ )
751 hr
= IMemInputPin_Receive(iface
,ppSample
[n
]);
756 LeaveCriticalSection( This
->pPin
->pcsPin
);
758 *pnSampleProcessed
= n
;
762 static HRESULT WINAPI
763 CMemInputPinBaseImpl_fnReceiveCanBlock(IMemInputPin
* iface
)
765 ICOM_THIS(CMemInputPinBaseImpl
,iface
);
766 HRESULT hr
= E_NOTIMPL
;
768 TRACE("(%p)->()\n",This
);
770 EnterCriticalSection( This
->pPin
->pcsPin
);
771 if ( This
->pPin
->pHandlers
->pReceiveCanBlock
!= NULL
)
772 hr
= This
->pPin
->pHandlers
->pReceiveCanBlock(This
->pPin
);
773 LeaveCriticalSection( This
->pPin
->pcsPin
);
779 static ICOM_VTABLE(IMemInputPin
) imeminputpin
=
781 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
782 /* IUnknown fields */
783 CMemInputPinBaseImpl_fnQueryInterface
,
784 CMemInputPinBaseImpl_fnAddRef
,
785 CMemInputPinBaseImpl_fnRelease
,
786 /* IMemInputPin fields */
787 CMemInputPinBaseImpl_fnGetAllocator
,
788 CMemInputPinBaseImpl_fnNotifyAllocator
,
789 CMemInputPinBaseImpl_fnGetAllocatorRequirements
,
790 CMemInputPinBaseImpl_fnReceive
,
791 CMemInputPinBaseImpl_fnReceiveMultiple
,
792 CMemInputPinBaseImpl_fnReceiveCanBlock
,
795 HRESULT
CMemInputPinBaseImpl_InitIMemInputPin(
796 CMemInputPinBaseImpl
* This
, IUnknown
* punkControl
,
799 TRACE("(%p,%p)\n",This
,punkControl
);
801 if ( punkControl
== NULL
)
803 ERR( "punkControl must not be NULL\n" );
807 ICOM_VTBL(This
) = &imeminputpin
;
808 This
->punkControl
= punkControl
;
810 This
->pAllocator
= NULL
;
811 This
->bReadonly
= FALSE
;
816 void CMemInputPinBaseImpl_UninitIMemInputPin(
817 CMemInputPinBaseImpl
* This
)
819 TRACE("(%p)\n",This
);
821 if ( This
->pAllocator
!= NULL
)
823 IMemAllocator_Release(This
->pAllocator
);
824 This
->pAllocator
= NULL
;
828 /***************************************************************************
830 * CQualityControlPassThruImpl
834 static HRESULT WINAPI
835 CQualityControlPassThruImpl_fnQueryInterface(IQualityControl
* iface
,REFIID riid
,void** ppobj
)
837 ICOM_THIS(CQualityControlPassThruImpl
,iface
);
839 TRACE("(%p)->()\n",This
);
841 return IUnknown_QueryInterface(This
->punkControl
,riid
,ppobj
);
845 CQualityControlPassThruImpl_fnAddRef(IQualityControl
* iface
)
847 ICOM_THIS(CQualityControlPassThruImpl
,iface
);
849 TRACE("(%p)->()\n",This
);
851 return IUnknown_AddRef(This
->punkControl
);
855 CQualityControlPassThruImpl_fnRelease(IQualityControl
* iface
)
857 ICOM_THIS(CQualityControlPassThruImpl
,iface
);
859 TRACE("(%p)->()\n",This
);
861 return IUnknown_Release(This
->punkControl
);
865 static HRESULT WINAPI
866 CQualityControlPassThruImpl_fnNotify(IQualityControl
* iface
,IBaseFilter
* pFilter
,Quality q
)
868 ICOM_THIS(CQualityControlPassThruImpl
,iface
);
869 HRESULT hr
= S_FALSE
;
871 TRACE("(%p)->()\n",This
);
873 if ( This
->pControl
!= NULL
)
874 return IQualityControl_Notify( This
->pControl
, pFilter
, q
);
876 EnterCriticalSection( This
->pPin
->pcsPin
);
877 if ( This
->pPin
->pHandlers
->pQualityNotify
!= NULL
)
878 hr
= This
->pPin
->pHandlers
->pQualityNotify(This
->pPin
,pFilter
,q
);
879 LeaveCriticalSection( This
->pPin
->pcsPin
);
884 static HRESULT WINAPI
885 CQualityControlPassThruImpl_fnSetSink(IQualityControl
* iface
,IQualityControl
* pControl
)
887 ICOM_THIS(CQualityControlPassThruImpl
,iface
);
889 TRACE("(%p)->()\n",This
);
891 This
->pControl
= pControl
; /* AddRef() must not be called */
896 static ICOM_VTABLE(IQualityControl
) iqualitycontrol
=
898 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
899 /* IUnknown fields */
900 CQualityControlPassThruImpl_fnQueryInterface
,
901 CQualityControlPassThruImpl_fnAddRef
,
902 CQualityControlPassThruImpl_fnRelease
,
903 /* IQualityControl fields */
904 CQualityControlPassThruImpl_fnNotify
,
905 CQualityControlPassThruImpl_fnSetSink
,
908 HRESULT
CQualityControlPassThruImpl_InitIQualityControl(
909 CQualityControlPassThruImpl
* This
, IUnknown
* punkControl
,
912 TRACE("(%p,%p)\n",This
,punkControl
);
914 if ( punkControl
== NULL
)
916 ERR( "punkControl must not be NULL\n" );
920 ICOM_VTBL(This
) = &iqualitycontrol
;
921 This
->punkControl
= punkControl
;
927 void CQualityControlPassThruImpl_UninitIQualityControl(
928 CQualityControlPassThruImpl
* This
)
932 /***************************************************************************
934 * helper methods for output pins.
938 HRESULT
CPinBaseImpl_SendSample( CPinBaseImpl
* This
, IMediaSample
* pSample
)
940 if ( This
->pHandlers
->pReceive
== NULL
)
943 return This
->pHandlers
->pReceive( This
, pSample
);
946 HRESULT
CPinBaseImpl_SendEndOfStream( CPinBaseImpl
* This
)
948 if ( This
->pHandlers
->pEndOfStream
== NULL
)
951 return This
->pHandlers
->pEndOfStream( This
);
954 HRESULT
CPinBaseImpl_SendBeginFlush( CPinBaseImpl
* This
)
956 if ( This
->pHandlers
->pBeginFlush
== NULL
)
959 return This
->pHandlers
->pBeginFlush( This
);
962 HRESULT
CPinBaseImpl_SendEndFlush( CPinBaseImpl
* This
)
964 if ( This
->pHandlers
->pEndFlush
== NULL
)
967 return This
->pHandlers
->pEndFlush( This
);
970 HRESULT
CPinBaseImpl_SendNewSegment( CPinBaseImpl
* This
, REFERENCE_TIME rtStart
, REFERENCE_TIME rtStop
, double rate
)
972 if ( This
->pHandlers
->pNewSegment
== NULL
)
975 return This
->pHandlers
->pNewSegment( This
, rtStart
, rtStop
, rate
);
980 /***************************************************************************
982 * handlers for output pins.
986 HRESULT
OutputPinSync_Receive( CPinBaseImpl
* pImpl
, IMediaSample
* pSample
)
988 if ( pImpl
->pMemInputPinConnectedTo
== NULL
)
991 return IMemInputPin_Receive(pImpl
->pMemInputPinConnectedTo
,pSample
);
994 HRESULT
OutputPinSync_ReceiveCanBlock( CPinBaseImpl
* pImpl
)
996 if ( pImpl
->pMemInputPinConnectedTo
== NULL
)
999 return IMemInputPin_ReceiveCanBlock(pImpl
->pMemInputPinConnectedTo
);
1002 HRESULT
OutputPinSync_EndOfStream( CPinBaseImpl
* pImpl
)
1004 if ( pImpl
->pPinConnectedTo
== NULL
)
1007 return IPin_EndOfStream(pImpl
->pPinConnectedTo
);
1010 HRESULT
OutputPinSync_BeginFlush( CPinBaseImpl
* pImpl
)
1012 if ( pImpl
->pPinConnectedTo
== NULL
)
1015 return IPin_BeginFlush(pImpl
->pPinConnectedTo
);
1018 HRESULT
OutputPinSync_EndFlush( CPinBaseImpl
* pImpl
)
1020 if ( pImpl
->pPinConnectedTo
== NULL
)
1023 return IPin_EndFlush(pImpl
->pPinConnectedTo
);
1026 HRESULT
OutputPinSync_NewSegment( CPinBaseImpl
* pImpl
, REFERENCE_TIME rtStart
, REFERENCE_TIME rtStop
, double rate
)
1028 if ( pImpl
->pPinConnectedTo
== NULL
)
1031 return IPin_NewSegment(pImpl
->pPinConnectedTo
,rtStart
,rtStop
,rate
);
1034 /***************************************************************************
1036 * handlers for output pins (async).
1040 typedef struct OutputPinTask OutputPinTask
;
1042 enum OutputPinTaskType
1046 OutTask_EndOfStream
,
1052 struct OutputPinTask
1054 OutputPinTask
* pNext
;
1055 enum OutputPinTaskType tasktype
;
1056 IMediaSample
* pSample
;
1057 REFERENCE_TIME rtStart
;
1058 REFERENCE_TIME rtStop
;
1062 struct OutputPinAsyncImpl
1064 HANDLE m_hTaskThread
;
1065 HANDLE m_hTaskEvent
;
1066 IPin
* m_pPin
; /* connected pin */
1067 IMemInputPin
* m_pMemInputPin
; /* connected pin */
1068 CRITICAL_SECTION m_csTasks
;
1069 OutputPinTask
* m_pFirst
;
1070 OutputPinTask
* m_pLast
;
1071 OutputPinTask
* m_pTaskExitThread
;
1074 static OutputPinTask
* OutputPinAsync_AllocTask( enum OutputPinTaskType tasktype
)
1076 OutputPinTask
* pTask
;
1078 pTask
= (OutputPinTask
*)QUARTZ_AllocMem( sizeof(OutputPinTask
) );
1079 pTask
->pNext
= NULL
;
1080 pTask
->tasktype
= tasktype
;
1081 pTask
->pSample
= NULL
;
1086 static void OutputPinAsync_FreeTask( OutputPinTask
* pTask
)
1088 if ( pTask
->pSample
!= NULL
)
1089 IMediaSample_Release( pTask
->pSample
);
1090 QUARTZ_FreeMem( pTask
);
1093 static void OutputPinAsync_AddTask( OutputPinAsyncImpl
* This
, OutputPinTask
* pTask
, BOOL bFirst
)
1095 EnterCriticalSection( &This
->m_csTasks
);
1099 pTask
->pNext
= This
->m_pFirst
;
1100 This
->m_pFirst
= pTask
;
1101 if ( This
->m_pLast
== NULL
)
1102 This
->m_pLast
= pTask
;
1106 if ( This
->m_pLast
!= NULL
)
1107 This
->m_pLast
->pNext
= pTask
;
1109 This
->m_pFirst
= pTask
;
1110 This
->m_pLast
= pTask
;
1113 LeaveCriticalSection( &This
->m_csTasks
);
1115 SetEvent( This
->m_hTaskEvent
);
1118 static OutputPinTask
* OutputPinAsync_GetNextTask( OutputPinAsyncImpl
* This
)
1120 OutputPinTask
* pTask
;
1122 EnterCriticalSection( &This
->m_csTasks
);
1123 pTask
= This
->m_pFirst
;
1124 if ( pTask
!= NULL
)
1126 This
->m_pFirst
= pTask
->pNext
;
1127 if ( This
->m_pFirst
== NULL
)
1128 This
->m_pLast
= NULL
;
1130 SetEvent( This
->m_hTaskEvent
);
1133 LeaveCriticalSection( &This
->m_csTasks
);
1138 static DWORD WINAPI
OutputPinAsync_ThreadEntry( LPVOID pv
)
1140 OutputPinAsyncImpl
* This
= ((CPinBaseImpl
*)pv
)->pAsyncOut
;
1141 OutputPinTask
* pTask
;
1143 BOOL bInFlush
= FALSE
;
1148 WaitForSingleObject( This
->m_hTaskEvent
, INFINITE
);
1149 ResetEvent( This
->m_hTaskEvent
);
1151 pTask
= OutputPinAsync_GetNextTask( This
);
1152 if ( pTask
== NULL
)
1156 switch ( pTask
->tasktype
)
1158 case OutTask_ExitThread
:
1161 case OutTask_Receive
:
1163 hr
= IMemInputPin_Receive( This
->m_pMemInputPin
, pTask
->pSample
);
1165 case OutTask_EndOfStream
:
1166 hr
= IPin_EndOfStream( This
->m_pPin
);
1168 case OutTask_BeginFlush
:
1170 hr
= IPin_BeginFlush( This
->m_pPin
);
1172 case OutTask_EndFlush
:
1174 hr
= IPin_EndFlush( This
->m_pPin
);
1176 case OutTask_NewSegment
:
1177 hr
= IPin_NewSegment( This
->m_pPin
, pTask
->rtStart
, pTask
->rtStop
, pTask
->rate
);
1180 ERR( "unexpected task type %d.\n", pTask
->tasktype
);
1185 OutputPinAsync_FreeTask( pTask
);
1189 ERR( "hresult %08lx\n", hr
);
1197 HRESULT
OutputPinAsync_OnActive( CPinBaseImpl
* pImpl
)
1202 FIXME("(%p)\n",pImpl
);
1204 if ( pImpl
->pMemInputPinConnectedTo
== NULL
)
1207 pImpl
->pAsyncOut
= (OutputPinAsyncImpl
*)
1208 QUARTZ_AllocMem( sizeof( OutputPinAsyncImpl
) );
1209 if ( pImpl
->pAsyncOut
== NULL
)
1210 return E_OUTOFMEMORY
;
1212 InitializeCriticalSection( &pImpl
->pAsyncOut
->m_csTasks
);
1213 pImpl
->pAsyncOut
->m_hTaskThread
= (HANDLE
)NULL
;
1214 pImpl
->pAsyncOut
->m_hTaskEvent
= (HANDLE
)NULL
;
1215 pImpl
->pAsyncOut
->m_pFirst
= NULL
;
1216 pImpl
->pAsyncOut
->m_pLast
= NULL
;
1217 pImpl
->pAsyncOut
->m_pTaskExitThread
= NULL
;
1218 pImpl
->pAsyncOut
->m_pPin
= pImpl
->pPinConnectedTo
;
1219 pImpl
->pAsyncOut
->m_pMemInputPin
= pImpl
->pMemInputPinConnectedTo
;
1221 pImpl
->pAsyncOut
->m_hTaskEvent
=
1222 CreateEventA( NULL
, TRUE
, FALSE
, NULL
);
1223 if ( pImpl
->pAsyncOut
->m_hTaskEvent
== (HANDLE
)NULL
)
1229 pImpl
->pAsyncOut
->m_pTaskExitThread
=
1230 OutputPinAsync_AllocTask( OutTask_ExitThread
);
1231 if ( pImpl
->pAsyncOut
->m_pTaskExitThread
== NULL
)
1237 pImpl
->pAsyncOut
->m_hTaskThread
= CreateThread(
1238 NULL
, 0, OutputPinAsync_ThreadEntry
, pImpl
,
1240 if ( pImpl
->pAsyncOut
->m_hTaskThread
== (HANDLE
)NULL
)
1248 OutputPinAsync_OnInactive( pImpl
);
1252 HRESULT
OutputPinAsync_OnInactive( CPinBaseImpl
* pImpl
)
1254 OutputPinTask
* pTask
;
1256 FIXME("(%p)\n",pImpl
);
1258 if ( pImpl
->pAsyncOut
== NULL
)
1261 if ( pImpl
->pAsyncOut
->m_pTaskExitThread
!= NULL
)
1263 OutputPinAsync_AddTask( pImpl
->pAsyncOut
, pImpl
->pAsyncOut
->m_pTaskExitThread
, TRUE
);
1264 pImpl
->pAsyncOut
->m_pTaskExitThread
= NULL
;
1267 if ( pImpl
->pAsyncOut
->m_hTaskThread
!= (HANDLE
)NULL
)
1269 WaitForSingleObject( pImpl
->pAsyncOut
->m_hTaskThread
, INFINITE
);
1270 CloseHandle( pImpl
->pAsyncOut
->m_hTaskThread
);
1272 if ( pImpl
->pAsyncOut
->m_hTaskEvent
!= (HANDLE
)NULL
)
1273 CloseHandle( pImpl
->pAsyncOut
->m_hTaskEvent
);
1275 /* release all tasks. */
1278 pTask
= OutputPinAsync_GetNextTask( pImpl
->pAsyncOut
);
1279 if ( pTask
== NULL
)
1281 OutputPinAsync_FreeTask( pTask
);
1284 DeleteCriticalSection( &pImpl
->pAsyncOut
->m_csTasks
);
1286 QUARTZ_FreeMem( pImpl
->pAsyncOut
);
1287 pImpl
->pAsyncOut
= NULL
;
1292 HRESULT
OutputPinAsync_Receive( CPinBaseImpl
* pImpl
, IMediaSample
* pSample
)
1294 OutputPinAsyncImpl
* This
= pImpl
->pAsyncOut
;
1295 OutputPinTask
* pTask
;
1297 TRACE("(%p,%p)\n",pImpl
,pSample
);
1302 pTask
= OutputPinAsync_AllocTask( OutTask_Receive
);
1303 if ( pTask
== NULL
)
1304 return E_OUTOFMEMORY
;
1305 pTask
->pSample
= pSample
; IMediaSample_AddRef( pSample
);
1306 OutputPinAsync_AddTask( pImpl
->pAsyncOut
, pTask
, FALSE
);
1311 HRESULT
OutputPinAsync_ReceiveCanBlock( CPinBaseImpl
* pImpl
)
1316 HRESULT
OutputPinAsync_EndOfStream( CPinBaseImpl
* pImpl
)
1318 OutputPinAsyncImpl
* This
= pImpl
->pAsyncOut
;
1319 OutputPinTask
* pTask
;
1321 TRACE("(%p)\n",pImpl
);
1326 pTask
= OutputPinAsync_AllocTask( OutTask_EndOfStream
);
1327 if ( pTask
== NULL
)
1328 return E_OUTOFMEMORY
;
1329 OutputPinAsync_AddTask( pImpl
->pAsyncOut
, pTask
, FALSE
);
1334 HRESULT
OutputPinAsync_BeginFlush( CPinBaseImpl
* pImpl
)
1336 OutputPinAsyncImpl
* This
= pImpl
->pAsyncOut
;
1337 OutputPinTask
* pTask
;
1339 TRACE("(%p)\n",pImpl
);
1344 pTask
= OutputPinAsync_AllocTask( OutTask_BeginFlush
);
1345 if ( pTask
== NULL
)
1346 return E_OUTOFMEMORY
;
1347 OutputPinAsync_AddTask( pImpl
->pAsyncOut
, pTask
, TRUE
);
1352 HRESULT
OutputPinAsync_EndFlush( CPinBaseImpl
* pImpl
)
1354 OutputPinAsyncImpl
* This
= pImpl
->pAsyncOut
;
1355 OutputPinTask
* pTask
;
1357 TRACE("(%p)\n",pImpl
);
1362 pTask
= OutputPinAsync_AllocTask( OutTask_EndFlush
);
1363 if ( pTask
== NULL
)
1364 return E_OUTOFMEMORY
;
1365 OutputPinAsync_AddTask( pImpl
->pAsyncOut
, pTask
, FALSE
);
1370 HRESULT
OutputPinAsync_NewSegment( CPinBaseImpl
* pImpl
, REFERENCE_TIME rtStart
, REFERENCE_TIME rtStop
, double rate
)
1372 OutputPinAsyncImpl
* This
= pImpl
->pAsyncOut
;
1373 OutputPinTask
* pTask
;
1375 TRACE("(%p)\n",pImpl
);
1380 pTask
= OutputPinAsync_AllocTask( OutTask_NewSegment
);
1381 if ( pTask
== NULL
)
1382 return E_OUTOFMEMORY
;
1383 pTask
->rtStart
= rtStart
;
1384 pTask
->rtStop
= rtStop
;
1386 OutputPinAsync_AddTask( pImpl
->pAsyncOut
, pTask
, FALSE
);