2 * Implements IPin and IMemInputPin. (internal)
4 * Copyright (C) Hidenori TAKESHIMA <hidenori@a2.ctktv.ne.jp>
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
31 #include "wine/debug.h"
32 WINE_DEFAULT_DEBUG_CHANNEL(quartz);
34 #include "quartz_private.h"
39 /***************************************************************************
46 CPinBaseImpl_fnQueryInterface(IPin* iface,REFIID riid,void** ppobj)
48 ICOM_THIS(CPinBaseImpl,iface);
50 TRACE("(%p)->()\n",This);
52 return IUnknown_QueryInterface(This->punkControl,riid,ppobj);
56 CPinBaseImpl_fnAddRef(IPin* iface)
58 ICOM_THIS(CPinBaseImpl,iface);
60 TRACE("(%p)->()\n",This);
62 return IUnknown_AddRef(This->punkControl);
66 CPinBaseImpl_fnRelease(IPin* iface)
68 ICOM_THIS(CPinBaseImpl,iface);
70 TRACE("(%p)->()\n",This);
72 return IUnknown_Release(This->punkControl);
76 CPinBaseImpl_fnConnect(IPin* iface,IPin* pPin,const AM_MEDIA_TYPE* pmt)
78 ICOM_THIS(CPinBaseImpl,iface);
79 HRESULT hr = E_NOTIMPL;
83 TRACE("(%p)->(%p,%p)\n",This,pPin,pmt);
87 TRACE("Connect() should not be sent to input pins\n");
93 TRACE("try to connect to %p\n",pPin);
95 EnterCriticalSection( This->pcsPin );
97 if ( This->pPinConnectedTo != NULL )
99 hr = VFW_E_ALREADY_CONNECTED;
103 /* return fail if running */
104 hr = IBaseFilter_GetState((IBaseFilter*)(This->pFilter),0,&fs);
105 if ( hr != S_OK || fs != State_Stopped )
107 TRACE("not stopped\n");
108 hr = VFW_E_NOT_STOPPED;
112 if ( This->pHandlers->pOnPreConnect != NULL )
114 hr = This->pHandlers->pOnPreConnect(This,pPin);
117 TRACE("OnPreconnect() failed hr = %08lx\n",hr);
124 hr = IPin_QueryAccept(iface,pmt);
127 This->pPinConnectedTo = pPin;
128 hr = IPin_ReceiveConnection(pPin,iface,pmt);
129 This->pPinConnectedTo = NULL;
135 for ( i = 0; i < This->cAcceptTypes; i++ )
137 pmt = &This->pmtAcceptTypes[i];
138 hr = IPin_QueryAccept(iface,pmt);
141 This->pPinConnectedTo = pPin;
142 hr = IPin_ReceiveConnection(pPin,iface,pmt);
143 This->pPinConnectedTo = NULL;
145 TRACE("ReceiveConnection - %08lx\n",hr);
153 hr = VFW_E_TYPE_NOT_ACCEPTED;
158 This->pmtConn = QUARTZ_MediaType_Duplicate( pmt );
159 if ( This->pmtConn == NULL )
162 IPin_Disconnect(pPin);
166 This->pPinConnectedTo = pPin; IPin_AddRef(pPin);
167 hr = IPin_QueryInterface(pPin,&IID_IMemInputPin,(void**)&This->pMemInputPinConnectedTo);
170 TRACE("no IMemInputPin\n");
171 IPin_Disconnect(pPin);
175 if ( This->pHandlers->pOnPostConnect != NULL )
177 hr = This->pHandlers->pOnPostConnect(This,pPin);
180 TRACE("OnPostConnect() failed hr = %08lx\n",hr);
181 IPin_Disconnect(pPin);
191 IPin_Disconnect(iface);
193 LeaveCriticalSection( This->pcsPin );
195 TRACE("return %08lx\n",hr);
200 static HRESULT WINAPI
201 CPinBaseImpl_fnReceiveConnection(IPin* iface,IPin* pPin,const AM_MEDIA_TYPE* pmt)
203 ICOM_THIS(CPinBaseImpl,iface);
204 HRESULT hr = E_NOTIMPL;
207 TRACE("(%p)->(%p,%p)\n",This,pPin,pmt);
211 TRACE("ReceiveConnection() should not be sent to output pins\n");
214 if ( pPin == NULL || pmt == NULL )
217 EnterCriticalSection( This->pcsPin );
219 if ( This->pPinConnectedTo != NULL )
221 hr = VFW_E_ALREADY_CONNECTED;
225 /* return fail if running */
226 hr = IBaseFilter_GetState((IBaseFilter*)(This->pFilter),0,&fs);
227 if ( hr != S_OK || fs != State_Stopped )
229 TRACE("not stopped\n");
230 hr = VFW_E_NOT_STOPPED;
234 if ( This->pHandlers->pOnPreConnect != NULL )
236 hr = This->pHandlers->pOnPreConnect(This,pPin);
239 TRACE("OnPreConnect() failed hr = %08lx\n",hr);
244 hr = IPin_QueryAccept(iface,pmt);
248 This->pmtConn = QUARTZ_MediaType_Duplicate( pmt );
249 if ( This->pmtConn == NULL )
255 if ( This->pHandlers->pOnPostConnect != NULL )
257 hr = This->pHandlers->pOnPostConnect(This,pPin);
260 TRACE("OnPostConnect() failed hr = %08lx\n",hr);
266 This->pPinConnectedTo = pPin; IPin_AddRef(pPin);
270 IPin_Disconnect(iface);
271 LeaveCriticalSection( This->pcsPin );
276 static HRESULT WINAPI
277 CPinBaseImpl_fnDisconnect(IPin* iface)
279 ICOM_THIS(CPinBaseImpl,iface);
280 HRESULT hr = NOERROR;
283 TRACE("(%p)->()\n",This);
285 EnterCriticalSection( This->pcsPin );
287 /* return fail if running */
288 hr = IBaseFilter_GetState((IBaseFilter*)(This->pFilter),0,&fs);
289 if ( hr != S_OK || fs != State_Stopped )
291 TRACE("not stopped\n");
292 hr = VFW_E_NOT_STOPPED;
296 if ( This->pHandlers->pOnDisconnect != NULL )
297 hr = This->pHandlers->pOnDisconnect(This);
299 if ( This->pmtConn != NULL )
301 QUARTZ_MediaType_Destroy( This->pmtConn );
302 This->pmtConn = NULL;
304 if ( This->pMemInputPinConnectedTo != NULL )
306 IMemInputPin_Release(This->pMemInputPinConnectedTo);
307 This->pMemInputPinConnectedTo = NULL;
309 if ( This->pPinConnectedTo != NULL )
311 /* FIXME - cleanup */
313 IPin_Release(This->pPinConnectedTo);
314 This->pPinConnectedTo = NULL;
319 hr = S_FALSE; /* FIXME - is this correct??? */
323 LeaveCriticalSection( This->pcsPin );
328 static HRESULT WINAPI
329 CPinBaseImpl_fnConnectedTo(IPin* iface,IPin** ppPin)
331 ICOM_THIS(CPinBaseImpl,iface);
332 HRESULT hr = VFW_E_NOT_CONNECTED;
334 TRACE("(%p)->(%p)\n",This,ppPin);
339 EnterCriticalSection( This->pcsPin );
341 *ppPin = This->pPinConnectedTo;
342 if ( This->pPinConnectedTo != NULL )
344 IPin_AddRef(This->pPinConnectedTo);
348 LeaveCriticalSection( This->pcsPin );
353 static HRESULT WINAPI
354 CPinBaseImpl_fnConnectionMediaType(IPin* iface,AM_MEDIA_TYPE* pmt)
356 ICOM_THIS(CPinBaseImpl,iface);
359 TRACE("(%p)->(%p)\n",This,pmt);
364 EnterCriticalSection( This->pcsPin );
366 if ( This->pmtConn != NULL )
368 hr = QUARTZ_MediaType_Copy( pmt, This->pmtConn );
372 ZeroMemory( pmt, sizeof(AM_MEDIA_TYPE) );
373 pmt->bFixedSizeSamples = TRUE;
374 pmt->lSampleSize = 1;
375 hr = VFW_E_NOT_CONNECTED;
378 LeaveCriticalSection( This->pcsPin );
383 static HRESULT WINAPI
384 CPinBaseImpl_fnQueryPinInfo(IPin* iface,PIN_INFO* pinfo)
386 ICOM_THIS(CPinBaseImpl,iface);
388 TRACE("(%p)->(%p)\n",This,pinfo);
393 EnterCriticalSection( This->pcsPin );
395 ZeroMemory( pinfo, sizeof(PIN_INFO) );
396 pinfo->pFilter = (IBaseFilter*)(This->pFilter);
397 if ( pinfo->pFilter != NULL )
398 IBaseFilter_AddRef( pinfo->pFilter );
399 pinfo->dir = This->bOutput ? PINDIR_OUTPUT : PINDIR_INPUT;
400 if ( This->cbIdLen <= sizeof(pinfo->achName) )
401 memcpy( pinfo->achName, This->pwszId, This->cbIdLen );
404 memcpy( pinfo->achName, This->pwszId, sizeof(pinfo->achName) );
405 pinfo->achName[sizeof(pinfo->achName)/sizeof(pinfo->achName[0])-1] = 0;
408 LeaveCriticalSection( This->pcsPin );
413 static HRESULT WINAPI
414 CPinBaseImpl_fnQueryDirection(IPin* iface,PIN_DIRECTION* pdir)
416 ICOM_THIS(CPinBaseImpl,iface);
418 TRACE("(%p)->(%p)\n",This,pdir);
423 *pdir = This->bOutput ? PINDIR_OUTPUT : PINDIR_INPUT;
428 static HRESULT WINAPI
429 CPinBaseImpl_fnQueryId(IPin* iface,LPWSTR* lpwszId)
431 ICOM_THIS(CPinBaseImpl,iface);
433 TRACE("(%p)->(%p)\n",This,lpwszId);
435 if ( lpwszId == NULL )
438 *lpwszId = (WCHAR*)CoTaskMemAlloc( This->cbIdLen );
439 if ( *lpwszId == NULL )
440 return E_OUTOFMEMORY;
441 memcpy( *lpwszId, This->pwszId, This->cbIdLen );
446 static HRESULT WINAPI
447 CPinBaseImpl_fnQueryAccept(IPin* iface,const AM_MEDIA_TYPE* pmt)
449 ICOM_THIS(CPinBaseImpl,iface);
452 TRACE("(%p)->(%p)\n",This,pmt);
458 EnterCriticalSection( This->pcsPin );
459 if ( This->pHandlers->pCheckMediaType != NULL )
460 hr = This->pHandlers->pCheckMediaType(This,pmt);
461 LeaveCriticalSection( This->pcsPin );
466 static HRESULT WINAPI
467 CPinBaseImpl_fnEnumMediaTypes(IPin* iface,IEnumMediaTypes** ppenum)
469 ICOM_THIS(CPinBaseImpl,iface);
472 TRACE("(%p)->(%p)\n",This,ppenum);
474 if ( ppenum == NULL )
479 EnterCriticalSection( This->pcsPin );
480 if ( This->cAcceptTypes > 0 )
481 hr = QUARTZ_CreateEnumMediaTypes(
482 ppenum, This->pmtAcceptTypes, This->cAcceptTypes );
483 LeaveCriticalSection( This->pcsPin );
488 static HRESULT WINAPI
489 CPinBaseImpl_fnQueryInternalConnections(IPin* iface,IPin** ppPin,ULONG* pul)
491 ICOM_THIS(CPinBaseImpl,iface);
493 TRACE("(%p)->(%p,%p)\n",This,ppPin,pul);
495 /* E_NOTIMPL means 'no internal connections'. */
499 static HRESULT WINAPI
500 CPinBaseImpl_fnEndOfStream(IPin* iface)
502 ICOM_THIS(CPinBaseImpl,iface);
503 HRESULT hr = E_NOTIMPL;
505 TRACE("(%p)->()\n",This);
510 EnterCriticalSection( This->pcsPinReceive );
511 if ( This->pHandlers->pEndOfStream != NULL )
512 hr = This->pHandlers->pEndOfStream(This);
513 LeaveCriticalSection( This->pcsPinReceive );
518 static HRESULT WINAPI
519 CPinBaseImpl_fnBeginFlush(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->pBeginFlush != NULL )
531 hr = This->pHandlers->pBeginFlush(This);
532 LeaveCriticalSection( This->pcsPin );
534 EnterCriticalSection( This->pcsPinReceive );
535 LeaveCriticalSection( This->pcsPinReceive );
540 static HRESULT WINAPI
541 CPinBaseImpl_fnEndFlush(IPin* iface)
543 ICOM_THIS(CPinBaseImpl,iface);
544 HRESULT hr = E_NOTIMPL;
546 TRACE("(%p)->()\n",This);
551 EnterCriticalSection( This->pcsPin );
552 if ( This->pHandlers->pEndFlush != NULL )
553 hr = This->pHandlers->pEndFlush(This);
554 LeaveCriticalSection( This->pcsPin );
559 static HRESULT WINAPI
560 CPinBaseImpl_fnNewSegment(IPin* iface,REFERENCE_TIME rtStart,REFERENCE_TIME rtStop,double rate)
562 ICOM_THIS(CPinBaseImpl,iface);
563 HRESULT hr = E_NOTIMPL;
565 TRACE("(%p)->()\n",This);
570 EnterCriticalSection( This->pcsPin );
571 if ( This->pHandlers->pNewSegment != NULL )
572 hr = This->pHandlers->pNewSegment(This,rtStart,rtStop,rate);
573 LeaveCriticalSection( This->pcsPin );
581 static ICOM_VTABLE(IPin) ipin =
583 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
584 /* IUnknown fields */
585 CPinBaseImpl_fnQueryInterface,
586 CPinBaseImpl_fnAddRef,
587 CPinBaseImpl_fnRelease,
589 CPinBaseImpl_fnConnect,
590 CPinBaseImpl_fnReceiveConnection,
591 CPinBaseImpl_fnDisconnect,
592 CPinBaseImpl_fnConnectedTo,
593 CPinBaseImpl_fnConnectionMediaType,
594 CPinBaseImpl_fnQueryPinInfo,
595 CPinBaseImpl_fnQueryDirection,
596 CPinBaseImpl_fnQueryId,
597 CPinBaseImpl_fnQueryAccept,
598 CPinBaseImpl_fnEnumMediaTypes,
599 CPinBaseImpl_fnQueryInternalConnections,
600 CPinBaseImpl_fnEndOfStream,
601 CPinBaseImpl_fnBeginFlush,
602 CPinBaseImpl_fnEndFlush,
603 CPinBaseImpl_fnNewSegment,
607 HRESULT CPinBaseImpl_InitIPin(
608 CPinBaseImpl* This, IUnknown* punkControl,
609 CRITICAL_SECTION* pcsPin,
610 CRITICAL_SECTION* pcsPinReceive,
611 CBaseFilterImpl* pFilter, LPCWSTR pwszId,
613 const CBasePinHandlers* pHandlers )
615 HRESULT hr = NOERROR;
617 TRACE("(%p,%p,%p)\n",This,punkControl,pFilter);
619 if ( punkControl == NULL )
621 ERR( "punkControl must not be NULL\n" );
625 ICOM_VTBL(This) = &ipin;
626 This->punkControl = punkControl;
627 This->pHandlers = pHandlers;
628 This->cbIdLen = sizeof(WCHAR)*(lstrlenW(pwszId)+1);
630 This->bOutput = bOutput;
631 This->pmtAcceptTypes = NULL;
632 This->cAcceptTypes = 0;
633 This->pcsPin = pcsPin;
634 This->pcsPinReceive = pcsPinReceive;
635 This->pFilter = pFilter;
636 This->pPinConnectedTo = NULL;
637 This->pMemInputPinConnectedTo = NULL;
638 This->pmtConn = NULL;
639 This->pAsyncOut = NULL;
641 This->pwszId = (WCHAR*)QUARTZ_AllocMem( This->cbIdLen );
642 if ( This->pwszId == NULL )
647 memcpy( This->pwszId, pwszId, This->cbIdLen );
652 CPinBaseImpl_UninitIPin( This );
656 void CPinBaseImpl_UninitIPin( CPinBaseImpl* This )
658 TRACE("(%p)\n",This);
660 IPin_Disconnect( (IPin*)(This) );
662 if ( This->pwszId != NULL )
664 QUARTZ_FreeMem( This->pwszId );
670 /***************************************************************************
672 * CMemInputPinBaseImpl
677 static HRESULT WINAPI
678 CMemInputPinBaseImpl_fnQueryInterface(IMemInputPin* iface,REFIID riid,void** ppobj)
680 ICOM_THIS(CMemInputPinBaseImpl,iface);
682 TRACE("(%p)->()\n",This);
684 return IUnknown_QueryInterface(This->punkControl,riid,ppobj);
688 CMemInputPinBaseImpl_fnAddRef(IMemInputPin* iface)
690 ICOM_THIS(CMemInputPinBaseImpl,iface);
692 TRACE("(%p)->()\n",This);
694 return IUnknown_AddRef(This->punkControl);
698 CMemInputPinBaseImpl_fnRelease(IMemInputPin* iface)
700 ICOM_THIS(CMemInputPinBaseImpl,iface);
702 TRACE("(%p)->()\n",This);
704 return IUnknown_Release(This->punkControl);
708 static HRESULT WINAPI
709 CMemInputPinBaseImpl_fnGetAllocator(IMemInputPin* iface,IMemAllocator** ppAllocator)
711 ICOM_THIS(CMemInputPinBaseImpl,iface);
712 HRESULT hr = NOERROR;
715 TRACE("(%p)->()\n",This);
717 if ( ppAllocator == NULL )
720 EnterCriticalSection( This->pPin->pcsPin );
722 if ( This->pAllocator == NULL )
724 hr = QUARTZ_CreateMemoryAllocator(NULL,(void**)&punk);
727 hr = IUnknown_QueryInterface(punk,
728 &IID_IMemAllocator,(void**)&This->pAllocator);
729 IUnknown_Release(punk);
735 *ppAllocator = This->pAllocator;
736 IMemAllocator_AddRef(This->pAllocator);
739 LeaveCriticalSection( This->pPin->pcsPin );
744 static HRESULT WINAPI
745 CMemInputPinBaseImpl_fnNotifyAllocator(IMemInputPin* iface,IMemAllocator* pAllocator,BOOL bReadonly)
747 ICOM_THIS(CMemInputPinBaseImpl,iface);
749 TRACE("(%p)->()\n",This);
751 if ( pAllocator == NULL )
754 EnterCriticalSection( This->pPin->pcsPin );
756 if ( This->pAllocator != NULL )
758 IMemAllocator_Release(This->pAllocator);
759 This->pAllocator = NULL;
761 This->pAllocator = pAllocator;
762 IMemAllocator_AddRef(This->pAllocator);
764 This->bReadonly = bReadonly;
766 LeaveCriticalSection( This->pPin->pcsPin );
771 static HRESULT WINAPI
772 CMemInputPinBaseImpl_fnGetAllocatorRequirements(IMemInputPin* iface,ALLOCATOR_PROPERTIES* pProp)
774 ICOM_THIS(CMemInputPinBaseImpl,iface);
776 TRACE("(%p)->(%p)\n",This,pProp);
781 /* E_MOTIMPL means 'no requirements' */
785 static HRESULT WINAPI
786 CMemInputPinBaseImpl_fnReceive(IMemInputPin* iface,IMediaSample* pSample)
788 ICOM_THIS(CMemInputPinBaseImpl,iface);
789 HRESULT hr = E_NOTIMPL;
791 TRACE("(%p)->(%p)\n",This,pSample);
793 EnterCriticalSection( This->pPin->pcsPinReceive );
794 if ( This->pPin->pHandlers->pReceive != NULL )
795 hr = This->pPin->pHandlers->pReceive(This->pPin,pSample);
796 LeaveCriticalSection( This->pPin->pcsPinReceive );
801 static HRESULT WINAPI
802 CMemInputPinBaseImpl_fnReceiveMultiple(IMemInputPin* iface,IMediaSample** ppSample,long nSample,long* pnSampleProcessed)
804 ICOM_THIS(CMemInputPinBaseImpl,iface);
808 TRACE("(%p)->()\n",This);
810 if ( ppSample == NULL || pnSampleProcessed == NULL )
814 for ( n = 0; n < nSample; n++ )
816 hr = IMemInputPin_Receive(iface,ppSample[n]);
821 *pnSampleProcessed = n;
825 static HRESULT WINAPI
826 CMemInputPinBaseImpl_fnReceiveCanBlock(IMemInputPin* iface)
828 ICOM_THIS(CMemInputPinBaseImpl,iface);
829 HRESULT hr = E_NOTIMPL;
831 TRACE("(%p)->()\n",This);
833 EnterCriticalSection( This->pPin->pcsPin );
834 if ( This->pPin->pHandlers->pReceiveCanBlock != NULL )
835 hr = This->pPin->pHandlers->pReceiveCanBlock(This->pPin);
836 LeaveCriticalSection( This->pPin->pcsPin );
842 static ICOM_VTABLE(IMemInputPin) imeminputpin =
844 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
845 /* IUnknown fields */
846 CMemInputPinBaseImpl_fnQueryInterface,
847 CMemInputPinBaseImpl_fnAddRef,
848 CMemInputPinBaseImpl_fnRelease,
849 /* IMemInputPin fields */
850 CMemInputPinBaseImpl_fnGetAllocator,
851 CMemInputPinBaseImpl_fnNotifyAllocator,
852 CMemInputPinBaseImpl_fnGetAllocatorRequirements,
853 CMemInputPinBaseImpl_fnReceive,
854 CMemInputPinBaseImpl_fnReceiveMultiple,
855 CMemInputPinBaseImpl_fnReceiveCanBlock,
858 HRESULT CMemInputPinBaseImpl_InitIMemInputPin(
859 CMemInputPinBaseImpl* This, IUnknown* punkControl,
862 TRACE("(%p,%p)\n",This,punkControl);
864 if ( punkControl == NULL )
866 ERR( "punkControl must not be NULL\n" );
870 ICOM_VTBL(This) = &imeminputpin;
871 This->punkControl = punkControl;
873 This->pAllocator = NULL;
874 This->bReadonly = FALSE;
879 void CMemInputPinBaseImpl_UninitIMemInputPin(
880 CMemInputPinBaseImpl* This )
882 TRACE("(%p)\n",This);
884 if ( This->pAllocator != NULL )
886 IMemAllocator_Release(This->pAllocator);
887 This->pAllocator = NULL;
891 /***************************************************************************
893 * CQualityControlPassThruImpl
897 static HRESULT WINAPI
898 CQualityControlPassThruImpl_fnQueryInterface(IQualityControl* iface,REFIID riid,void** ppobj)
900 ICOM_THIS(CQualityControlPassThruImpl,iface);
902 TRACE("(%p)->()\n",This);
904 return IUnknown_QueryInterface(This->punkControl,riid,ppobj);
908 CQualityControlPassThruImpl_fnAddRef(IQualityControl* iface)
910 ICOM_THIS(CQualityControlPassThruImpl,iface);
912 TRACE("(%p)->()\n",This);
914 return IUnknown_AddRef(This->punkControl);
918 CQualityControlPassThruImpl_fnRelease(IQualityControl* iface)
920 ICOM_THIS(CQualityControlPassThruImpl,iface);
922 TRACE("(%p)->()\n",This);
924 return IUnknown_Release(This->punkControl);
928 static HRESULT WINAPI
929 CQualityControlPassThruImpl_fnNotify(IQualityControl* iface,IBaseFilter* pFilter,Quality q)
931 ICOM_THIS(CQualityControlPassThruImpl,iface);
932 HRESULT hr = S_FALSE;
934 TRACE("(%p)->()\n",This);
936 if ( This->pControl != NULL )
937 return IQualityControl_Notify( This->pControl, pFilter, q );
939 EnterCriticalSection( This->pPin->pcsPin );
940 if ( This->pPin->pHandlers->pQualityNotify != NULL )
941 hr = This->pPin->pHandlers->pQualityNotify(This->pPin,pFilter,q);
942 LeaveCriticalSection( This->pPin->pcsPin );
947 static HRESULT WINAPI
948 CQualityControlPassThruImpl_fnSetSink(IQualityControl* iface,IQualityControl* pControl)
950 ICOM_THIS(CQualityControlPassThruImpl,iface);
952 TRACE("(%p)->()\n",This);
954 This->pControl = pControl; /* AddRef() must not be called */
959 static ICOM_VTABLE(IQualityControl) iqualitycontrol =
961 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
962 /* IUnknown fields */
963 CQualityControlPassThruImpl_fnQueryInterface,
964 CQualityControlPassThruImpl_fnAddRef,
965 CQualityControlPassThruImpl_fnRelease,
966 /* IQualityControl fields */
967 CQualityControlPassThruImpl_fnNotify,
968 CQualityControlPassThruImpl_fnSetSink,
971 HRESULT CQualityControlPassThruImpl_InitIQualityControl(
972 CQualityControlPassThruImpl* This, IUnknown* punkControl,
975 TRACE("(%p,%p)\n",This,punkControl);
977 if ( punkControl == NULL )
979 ERR( "punkControl must not be NULL\n" );
983 ICOM_VTBL(This) = &iqualitycontrol;
984 This->punkControl = punkControl;
990 void CQualityControlPassThruImpl_UninitIQualityControl(
991 CQualityControlPassThruImpl* This )
995 /***************************************************************************
997 * helper methods for output pins.
1001 HRESULT CPinBaseImpl_SendSample( CPinBaseImpl* This, IMediaSample* pSample )
1003 if ( This->pHandlers->pReceive == NULL )
1006 return This->pHandlers->pReceive( This, pSample );
1009 HRESULT CPinBaseImpl_SendReceiveCanBlock( CPinBaseImpl* This )
1011 if ( This->pHandlers->pReceiveCanBlock == NULL )
1014 return This->pHandlers->pReceiveCanBlock( This );
1017 HRESULT CPinBaseImpl_SendEndOfStream( CPinBaseImpl* This )
1019 if ( This->pHandlers->pEndOfStream == NULL )
1022 return This->pHandlers->pEndOfStream( This );
1025 HRESULT CPinBaseImpl_SendBeginFlush( CPinBaseImpl* This )
1027 if ( This->pHandlers->pBeginFlush == NULL )
1030 return This->pHandlers->pBeginFlush( This );
1033 HRESULT CPinBaseImpl_SendEndFlush( CPinBaseImpl* This )
1035 if ( This->pHandlers->pEndFlush == NULL )
1038 return This->pHandlers->pEndFlush( This );
1041 HRESULT CPinBaseImpl_SendNewSegment( CPinBaseImpl* This, REFERENCE_TIME rtStart, REFERENCE_TIME rtStop, double rate )
1043 if ( This->pHandlers->pNewSegment == NULL )
1046 return This->pHandlers->pNewSegment( This, rtStart, rtStop, rate );
1051 /***************************************************************************
1053 * handlers for output pins.
1057 HRESULT OutputPinSync_Receive( CPinBaseImpl* pImpl, IMediaSample* pSample )
1059 if ( pImpl->pMemInputPinConnectedTo == NULL )
1062 return IMemInputPin_Receive(pImpl->pMemInputPinConnectedTo,pSample);
1065 HRESULT OutputPinSync_ReceiveCanBlock( CPinBaseImpl* pImpl )
1067 if ( pImpl->pMemInputPinConnectedTo == NULL )
1070 return IMemInputPin_ReceiveCanBlock(pImpl->pMemInputPinConnectedTo);
1073 HRESULT OutputPinSync_EndOfStream( CPinBaseImpl* pImpl )
1075 if ( pImpl->pPinConnectedTo == NULL )
1078 return IPin_EndOfStream(pImpl->pPinConnectedTo);
1081 HRESULT OutputPinSync_BeginFlush( CPinBaseImpl* pImpl )
1083 if ( pImpl->pPinConnectedTo == NULL )
1086 return IPin_BeginFlush(pImpl->pPinConnectedTo);
1089 HRESULT OutputPinSync_EndFlush( CPinBaseImpl* pImpl )
1091 if ( pImpl->pPinConnectedTo == NULL )
1094 return IPin_EndFlush(pImpl->pPinConnectedTo);
1097 HRESULT OutputPinSync_NewSegment( CPinBaseImpl* pImpl, REFERENCE_TIME rtStart, REFERENCE_TIME rtStop, double rate )
1099 if ( pImpl->pPinConnectedTo == NULL )
1102 return IPin_NewSegment(pImpl->pPinConnectedTo,rtStart,rtStop,rate);
1105 /***************************************************************************
1107 * handlers for output pins (async).
1111 typedef struct OutputPinTask OutputPinTask;
1113 enum OutputPinTaskType
1117 OutTask_EndOfStream,
1123 struct OutputPinTask
1125 OutputPinTask* pNext;
1126 enum OutputPinTaskType tasktype;
1127 IMediaSample* pSample;
1128 REFERENCE_TIME rtStart;
1129 REFERENCE_TIME rtStop;
1133 struct OutputPinAsyncImpl
1135 HANDLE m_hTaskThread;
1136 HANDLE m_hTaskEvent;
1137 IPin* m_pPin; /* connected pin */
1138 IMemInputPin* m_pMemInputPin; /* connected pin */
1139 CRITICAL_SECTION m_csTasks;
1140 OutputPinTask* m_pFirst;
1141 OutputPinTask* m_pLast;
1142 OutputPinTask* m_pTaskExitThread;
1145 static OutputPinTask* OutputPinAsync_AllocTask( enum OutputPinTaskType tasktype )
1147 OutputPinTask* pTask;
1149 pTask = (OutputPinTask*)QUARTZ_AllocMem( sizeof(OutputPinTask) );
1150 pTask->pNext = NULL;
1151 pTask->tasktype = tasktype;
1152 pTask->pSample = NULL;
1157 static void OutputPinAsync_FreeTask( OutputPinTask* pTask )
1159 if ( pTask->pSample != NULL )
1160 IMediaSample_Release( pTask->pSample );
1161 QUARTZ_FreeMem( pTask );
1164 static void OutputPinAsync_AddTask( OutputPinAsyncImpl* This, OutputPinTask* pTask, BOOL bFirst )
1166 EnterCriticalSection( &This->m_csTasks );
1170 pTask->pNext = This->m_pFirst;
1171 This->m_pFirst = pTask;
1172 if ( This->m_pLast == NULL )
1173 This->m_pLast = pTask;
1177 if ( This->m_pLast != NULL )
1178 This->m_pLast->pNext = pTask;
1180 This->m_pFirst = pTask;
1181 This->m_pLast = pTask;
1184 LeaveCriticalSection( &This->m_csTasks );
1186 SetEvent( This->m_hTaskEvent );
1189 static OutputPinTask* OutputPinAsync_GetNextTask( OutputPinAsyncImpl* This )
1191 OutputPinTask* pTask;
1193 EnterCriticalSection( &This->m_csTasks );
1194 pTask = This->m_pFirst;
1195 if ( pTask != NULL )
1197 This->m_pFirst = pTask->pNext;
1198 if ( This->m_pFirst == NULL )
1199 This->m_pLast = NULL;
1201 SetEvent( This->m_hTaskEvent );
1204 LeaveCriticalSection( &This->m_csTasks );
1209 static DWORD WINAPI OutputPinAsync_ThreadEntry( LPVOID pv )
1211 OutputPinAsyncImpl* This = ((CPinBaseImpl*)pv)->pAsyncOut;
1212 OutputPinTask* pTask;
1214 BOOL bInFlush = FALSE;
1219 WaitForSingleObject( This->m_hTaskEvent, INFINITE );
1220 ResetEvent( This->m_hTaskEvent );
1222 pTask = OutputPinAsync_GetNextTask( This );
1223 if ( pTask == NULL )
1227 switch ( pTask->tasktype )
1229 case OutTask_ExitThread:
1232 case OutTask_Receive:
1234 hr = IMemInputPin_Receive( This->m_pMemInputPin, pTask->pSample );
1236 case OutTask_EndOfStream:
1237 hr = IPin_EndOfStream( This->m_pPin );
1239 case OutTask_BeginFlush:
1241 hr = IPin_BeginFlush( This->m_pPin );
1243 case OutTask_EndFlush:
1245 hr = IPin_EndFlush( This->m_pPin );
1247 case OutTask_NewSegment:
1248 hr = IPin_NewSegment( This->m_pPin, pTask->rtStart, pTask->rtStop, pTask->rate );
1251 ERR( "unexpected task type %d.\n", pTask->tasktype );
1256 OutputPinAsync_FreeTask( pTask );
1260 ERR( "hresult %08lx\n", hr );
1268 HRESULT OutputPinAsync_OnActive( CPinBaseImpl* pImpl )
1273 FIXME("(%p)\n",pImpl);
1275 if ( pImpl->pMemInputPinConnectedTo == NULL )
1278 pImpl->pAsyncOut = (OutputPinAsyncImpl*)
1279 QUARTZ_AllocMem( sizeof( OutputPinAsyncImpl ) );
1280 if ( pImpl->pAsyncOut == NULL )
1281 return E_OUTOFMEMORY;
1283 InitializeCriticalSection( &pImpl->pAsyncOut->m_csTasks );
1284 pImpl->pAsyncOut->m_hTaskThread = (HANDLE)NULL;
1285 pImpl->pAsyncOut->m_hTaskEvent = (HANDLE)NULL;
1286 pImpl->pAsyncOut->m_pFirst = NULL;
1287 pImpl->pAsyncOut->m_pLast = NULL;
1288 pImpl->pAsyncOut->m_pTaskExitThread = NULL;
1289 pImpl->pAsyncOut->m_pPin = pImpl->pPinConnectedTo;
1290 pImpl->pAsyncOut->m_pMemInputPin = pImpl->pMemInputPinConnectedTo;
1292 pImpl->pAsyncOut->m_hTaskEvent =
1293 CreateEventA( NULL, TRUE, FALSE, NULL );
1294 if ( pImpl->pAsyncOut->m_hTaskEvent == (HANDLE)NULL )
1300 pImpl->pAsyncOut->m_pTaskExitThread =
1301 OutputPinAsync_AllocTask( OutTask_ExitThread );
1302 if ( pImpl->pAsyncOut->m_pTaskExitThread == NULL )
1308 pImpl->pAsyncOut->m_hTaskThread = CreateThread(
1309 NULL, 0, OutputPinAsync_ThreadEntry, pImpl,
1311 if ( pImpl->pAsyncOut->m_hTaskThread == (HANDLE)NULL )
1319 OutputPinAsync_OnInactive( pImpl );
1323 HRESULT OutputPinAsync_OnInactive( CPinBaseImpl* pImpl )
1325 OutputPinTask* pTask;
1327 FIXME("(%p)\n",pImpl);
1329 if ( pImpl->pAsyncOut == NULL )
1332 if ( pImpl->pAsyncOut->m_pTaskExitThread != NULL )
1334 OutputPinAsync_AddTask( pImpl->pAsyncOut, pImpl->pAsyncOut->m_pTaskExitThread, TRUE );
1335 pImpl->pAsyncOut->m_pTaskExitThread = NULL;
1338 if ( pImpl->pAsyncOut->m_hTaskThread != (HANDLE)NULL )
1340 WaitForSingleObject( pImpl->pAsyncOut->m_hTaskThread, INFINITE );
1341 CloseHandle( pImpl->pAsyncOut->m_hTaskThread );
1343 if ( pImpl->pAsyncOut->m_hTaskEvent != (HANDLE)NULL )
1344 CloseHandle( pImpl->pAsyncOut->m_hTaskEvent );
1346 /* release all tasks. */
1349 pTask = OutputPinAsync_GetNextTask( pImpl->pAsyncOut );
1350 if ( pTask == NULL )
1352 OutputPinAsync_FreeTask( pTask );
1355 DeleteCriticalSection( &pImpl->pAsyncOut->m_csTasks );
1357 QUARTZ_FreeMem( pImpl->pAsyncOut );
1358 pImpl->pAsyncOut = NULL;
1363 HRESULT OutputPinAsync_Receive( CPinBaseImpl* pImpl, IMediaSample* pSample )
1365 OutputPinAsyncImpl* This = pImpl->pAsyncOut;
1366 OutputPinTask* pTask;
1368 TRACE("(%p,%p)\n",pImpl,pSample);
1373 pTask = OutputPinAsync_AllocTask( OutTask_Receive );
1374 if ( pTask == NULL )
1375 return E_OUTOFMEMORY;
1376 pTask->pSample = pSample; IMediaSample_AddRef( pSample );
1377 OutputPinAsync_AddTask( pImpl->pAsyncOut, pTask, FALSE );
1382 HRESULT OutputPinAsync_ReceiveCanBlock( CPinBaseImpl* pImpl )
1387 HRESULT OutputPinAsync_EndOfStream( CPinBaseImpl* pImpl )
1389 OutputPinAsyncImpl* This = pImpl->pAsyncOut;
1390 OutputPinTask* pTask;
1392 TRACE("(%p)\n",pImpl);
1397 pTask = OutputPinAsync_AllocTask( OutTask_EndOfStream );
1398 if ( pTask == NULL )
1399 return E_OUTOFMEMORY;
1400 OutputPinAsync_AddTask( pImpl->pAsyncOut, pTask, FALSE );
1405 HRESULT OutputPinAsync_BeginFlush( CPinBaseImpl* pImpl )
1407 OutputPinAsyncImpl* This = pImpl->pAsyncOut;
1408 OutputPinTask* pTask;
1410 TRACE("(%p)\n",pImpl);
1415 pTask = OutputPinAsync_AllocTask( OutTask_BeginFlush );
1416 if ( pTask == NULL )
1417 return E_OUTOFMEMORY;
1418 OutputPinAsync_AddTask( pImpl->pAsyncOut, pTask, TRUE );
1423 HRESULT OutputPinAsync_EndFlush( CPinBaseImpl* pImpl )
1425 OutputPinAsyncImpl* This = pImpl->pAsyncOut;
1426 OutputPinTask* pTask;
1428 TRACE("(%p)\n",pImpl);
1433 pTask = OutputPinAsync_AllocTask( OutTask_EndFlush );
1434 if ( pTask == NULL )
1435 return E_OUTOFMEMORY;
1436 OutputPinAsync_AddTask( pImpl->pAsyncOut, pTask, FALSE );
1441 HRESULT OutputPinAsync_NewSegment( CPinBaseImpl* pImpl, REFERENCE_TIME rtStart, REFERENCE_TIME rtStop, double rate )
1443 OutputPinAsyncImpl* This = pImpl->pAsyncOut;
1444 OutputPinTask* pTask;
1446 TRACE("(%p)\n",pImpl);
1451 pTask = OutputPinAsync_AllocTask( OutTask_NewSegment );
1452 if ( pTask == NULL )
1453 return E_OUTOFMEMORY;
1454 pTask->rtStart = rtStart;
1455 pTask->rtStop = rtStop;
1457 OutputPinAsync_AddTask( pImpl->pAsyncOut, pTask, FALSE );