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;
68 FIXME("(%p)->(%p,%p)\n",This,pPin,pmt);
75 TRACE("try to connect to %p\n",pPin);
77 EnterCriticalSection( This->pcsPin );
79 if ( This->pPinConnectedTo != NULL )
81 hr = VFW_E_ALREADY_CONNECTED;
85 /* FIXME - return fail if running */
87 if ( This->pHandlers->pOnPreConnect != NULL )
89 hr = This->pHandlers->pOnPreConnect(This,pPin);
96 hr = IPin_QueryAccept(iface,pmt);
99 hr = IPin_ReceiveConnection(pPin,iface,pmt);
105 for ( i = 0; i < This->cAcceptTypes; i++ )
107 pmt = &This->pmtAcceptTypes[i];
108 hr = IPin_QueryAccept(iface,pmt);
111 hr = IPin_ReceiveConnection(pPin,iface,pmt);
119 hr = VFW_E_TYPE_NOT_ACCEPTED;
124 This->pmtConn = QUARTZ_MediaType_Duplicate( pmt );
125 if ( This->pmtConn == NULL )
128 IPin_Disconnect(pPin);
132 This->pPinConnectedTo = pPin; IPin_AddRef(pPin);
133 hr = IPin_QueryInterface(pPin,&IID_IMemInputPin,(void**)&This->pMemInputPinConnectedTo);
136 IPin_Disconnect(pPin);
140 if ( This->pHandlers->pOnPostConnect != NULL )
142 hr = This->pHandlers->pOnPostConnect(This,pPin);
145 IPin_Disconnect(pPin);
155 IPin_Disconnect(iface);
157 LeaveCriticalSection( This->pcsPin );
162 static HRESULT WINAPI
163 CPinBaseImpl_fnReceiveConnection(IPin* iface,IPin* pPin,const AM_MEDIA_TYPE* pmt)
165 ICOM_THIS(CPinBaseImpl,iface);
166 HRESULT hr = E_NOTIMPL;
168 FIXME("(%p)->(%p,%p)\n",This,pPin,pmt);
172 if ( pPin == NULL || pmt == NULL )
175 EnterCriticalSection( This->pcsPin );
177 if ( This->pPinConnectedTo != NULL )
179 hr = VFW_E_ALREADY_CONNECTED;
183 /* FIXME - return fail if running */
185 if ( This->pHandlers->pOnPreConnect != NULL )
187 hr = This->pHandlers->pOnPreConnect(This,pPin);
192 hr = IPin_QueryAccept(iface,pmt);
196 This->pmtConn = QUARTZ_MediaType_Duplicate( pmt );
197 if ( This->pmtConn == NULL )
203 if ( This->pHandlers->pOnPostConnect != NULL )
205 hr = This->pHandlers->pOnPostConnect(This,pPin);
211 This->pPinConnectedTo = pPin; IPin_AddRef(pPin);
215 IPin_Disconnect(iface);
216 LeaveCriticalSection( This->pcsPin );
221 static HRESULT WINAPI
222 CPinBaseImpl_fnDisconnect(IPin* iface)
224 ICOM_THIS(CPinBaseImpl,iface);
225 HRESULT hr = NOERROR;
227 FIXME("(%p)->() stub!\n",This);
229 EnterCriticalSection( This->pcsPin );
231 /* FIXME - return fail if running */
233 if ( This->pHandlers->pOnDisconnect != NULL )
234 hr = This->pHandlers->pOnDisconnect(This);
236 if ( This->pmtConn != NULL )
238 QUARTZ_MediaType_Destroy( This->pmtConn );
239 This->pmtConn = NULL;
241 if ( This->pMemInputPinConnectedTo != NULL )
243 IMemInputPin_Release(This->pMemInputPinConnectedTo);
244 This->pMemInputPinConnectedTo = NULL;
246 if ( This->pPinConnectedTo != NULL )
248 /* FIXME - cleanup */
250 IPin_Release(This->pPinConnectedTo);
251 This->pPinConnectedTo = NULL;
256 hr = S_FALSE; /* FIXME - is this correct??? */
259 LeaveCriticalSection( This->pcsPin );
264 static HRESULT WINAPI
265 CPinBaseImpl_fnConnectedTo(IPin* iface,IPin** ppPin)
267 ICOM_THIS(CPinBaseImpl,iface);
268 HRESULT hr = VFW_E_NOT_CONNECTED;
270 TRACE("(%p)->(%p)\n",This,ppPin);
275 EnterCriticalSection( This->pcsPin );
277 *ppPin = This->pPinConnectedTo;
278 if ( This->pPinConnectedTo != NULL )
280 IPin_AddRef(This->pPinConnectedTo);
284 LeaveCriticalSection( This->pcsPin );
289 static HRESULT WINAPI
290 CPinBaseImpl_fnConnectionMediaType(IPin* iface,AM_MEDIA_TYPE* pmt)
292 ICOM_THIS(CPinBaseImpl,iface);
295 TRACE("(%p)->(%p)\n",This,pmt);
300 EnterCriticalSection( This->pcsPin );
302 if ( This->pmtConn != NULL )
304 hr = QUARTZ_MediaType_Copy( pmt, This->pmtConn );
308 ZeroMemory( pmt, sizeof(AM_MEDIA_TYPE) );
309 pmt->bFixedSizeSamples = TRUE;
310 pmt->lSampleSize = 1;
314 LeaveCriticalSection( This->pcsPin );
319 static HRESULT WINAPI
320 CPinBaseImpl_fnQueryPinInfo(IPin* iface,PIN_INFO* pinfo)
322 ICOM_THIS(CPinBaseImpl,iface);
324 TRACE("(%p)->(%p)\n",This,pinfo);
329 EnterCriticalSection( This->pcsPin );
331 ZeroMemory( pinfo, sizeof(PIN_INFO) );
332 pinfo->pFilter = (IBaseFilter*)(This->pFilter);
333 if ( pinfo->pFilter != NULL )
334 IBaseFilter_AddRef( pinfo->pFilter );
335 pinfo->dir = This->bOutput ? PINDIR_OUTPUT : PINDIR_INPUT;
336 if ( This->cbIdLen <= sizeof(pinfo->achName) )
337 memcpy( pinfo->achName, This->pwszId, This->cbIdLen );
340 memcpy( pinfo->achName, This->pwszId, sizeof(pinfo->achName) );
341 pinfo->achName[sizeof(pinfo->achName)/sizeof(pinfo->achName[0])-1] = 0;
344 LeaveCriticalSection( This->pcsPin );
349 static HRESULT WINAPI
350 CPinBaseImpl_fnQueryDirection(IPin* iface,PIN_DIRECTION* pdir)
352 ICOM_THIS(CPinBaseImpl,iface);
354 TRACE("(%p)->(%p)\n",This,pdir);
359 *pdir = This->bOutput ? PINDIR_OUTPUT : PINDIR_INPUT;
364 static HRESULT WINAPI
365 CPinBaseImpl_fnQueryId(IPin* iface,LPWSTR* lpwszId)
367 ICOM_THIS(CPinBaseImpl,iface);
369 TRACE("(%p)->(%p)\n",This,lpwszId);
371 if ( lpwszId == NULL )
374 *lpwszId = (WCHAR*)CoTaskMemAlloc( This->cbIdLen );
375 if ( *lpwszId == NULL )
376 return E_OUTOFMEMORY;
377 memcpy( *lpwszId, This->pwszId, This->cbIdLen );
382 static HRESULT WINAPI
383 CPinBaseImpl_fnQueryAccept(IPin* iface,const AM_MEDIA_TYPE* pmt)
385 ICOM_THIS(CPinBaseImpl,iface);
388 TRACE("(%p)->(%p)\n",This,pmt);
394 EnterCriticalSection( This->pcsPin );
395 if ( This->pHandlers->pCheckMediaType != NULL )
396 hr = This->pHandlers->pCheckMediaType(This,pmt);
397 LeaveCriticalSection( This->pcsPin );
402 static HRESULT WINAPI
403 CPinBaseImpl_fnEnumMediaTypes(IPin* iface,IEnumMediaTypes** ppenum)
405 ICOM_THIS(CPinBaseImpl,iface);
408 TRACE("(%p)->(%p)\n",This,ppenum);
410 if ( ppenum == NULL )
415 EnterCriticalSection( This->pcsPin );
416 if ( This->cAcceptTypes > 0 )
417 hr = QUARTZ_CreateEnumMediaTypes(
418 ppenum, This->pmtAcceptTypes, This->cAcceptTypes );
419 LeaveCriticalSection( This->pcsPin );
424 static HRESULT WINAPI
425 CPinBaseImpl_fnQueryInternalConnections(IPin* iface,IPin** ppPin,ULONG* pul)
427 ICOM_THIS(CPinBaseImpl,iface);
429 TRACE("(%p)->(%p,%p)\n",This,ppPin,pul);
431 /* E_NOTIMPL means 'no internal connections'. */
435 static HRESULT WINAPI
436 CPinBaseImpl_fnEndOfStream(IPin* iface)
438 ICOM_THIS(CPinBaseImpl,iface);
439 HRESULT hr = E_NOTIMPL;
441 TRACE("(%p)->()\n",This);
446 EnterCriticalSection( This->pcsPin );
447 if ( This->pHandlers->pEndOfStream != NULL )
448 hr = This->pHandlers->pEndOfStream(This);
449 LeaveCriticalSection( This->pcsPin );
454 static HRESULT WINAPI
455 CPinBaseImpl_fnBeginFlush(IPin* iface)
457 ICOM_THIS(CPinBaseImpl,iface);
458 HRESULT hr = E_NOTIMPL;
460 TRACE("(%p)->()\n",This);
465 EnterCriticalSection( This->pcsPin );
466 if ( This->pHandlers->pBeginFlush != NULL )
467 hr = This->pHandlers->pBeginFlush(This);
468 LeaveCriticalSection( This->pcsPin );
473 static HRESULT WINAPI
474 CPinBaseImpl_fnEndFlush(IPin* iface)
476 ICOM_THIS(CPinBaseImpl,iface);
477 HRESULT hr = E_NOTIMPL;
479 TRACE("(%p)->()\n",This);
484 EnterCriticalSection( This->pcsPin );
485 if ( This->pHandlers->pEndFlush != NULL )
486 hr = This->pHandlers->pEndFlush(This);
487 LeaveCriticalSection( This->pcsPin );
492 static HRESULT WINAPI
493 CPinBaseImpl_fnNewSegment(IPin* iface,REFERENCE_TIME rtStart,REFERENCE_TIME rtStop,double rate)
495 ICOM_THIS(CPinBaseImpl,iface);
496 HRESULT hr = E_NOTIMPL;
498 TRACE("(%p)->()\n",This);
503 EnterCriticalSection( This->pcsPin );
504 if ( This->pHandlers->pNewSegment != NULL )
505 hr = This->pHandlers->pNewSegment(This,rtStart,rtStop,rate);
506 LeaveCriticalSection( This->pcsPin );
514 static ICOM_VTABLE(IPin) ipin =
516 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
517 /* IUnknown fields */
518 CPinBaseImpl_fnQueryInterface,
519 CPinBaseImpl_fnAddRef,
520 CPinBaseImpl_fnRelease,
522 CPinBaseImpl_fnConnect,
523 CPinBaseImpl_fnReceiveConnection,
524 CPinBaseImpl_fnDisconnect,
525 CPinBaseImpl_fnConnectedTo,
526 CPinBaseImpl_fnConnectionMediaType,
527 CPinBaseImpl_fnQueryPinInfo,
528 CPinBaseImpl_fnQueryDirection,
529 CPinBaseImpl_fnQueryId,
530 CPinBaseImpl_fnQueryAccept,
531 CPinBaseImpl_fnEnumMediaTypes,
532 CPinBaseImpl_fnQueryInternalConnections,
533 CPinBaseImpl_fnEndOfStream,
534 CPinBaseImpl_fnBeginFlush,
535 CPinBaseImpl_fnEndFlush,
536 CPinBaseImpl_fnNewSegment,
540 HRESULT CPinBaseImpl_InitIPin(
541 CPinBaseImpl* This, IUnknown* punkControl,
542 CRITICAL_SECTION* pcsPin,
543 CBaseFilterImpl* pFilter, LPCWSTR pwszId,
545 const CBasePinHandlers* pHandlers )
547 HRESULT hr = NOERROR;
549 TRACE("(%p,%p,%p)\n",This,punkControl,pFilter);
551 if ( punkControl == NULL )
553 ERR( "punkControl must not be NULL\n" );
557 ICOM_VTBL(This) = &ipin;
558 This->punkControl = punkControl;
559 This->pHandlers = pHandlers;
560 This->cbIdLen = sizeof(WCHAR)*(lstrlenW(pwszId)+1);
562 This->bOutput = bOutput;
563 This->pmtAcceptTypes = NULL;
564 This->cAcceptTypes = 0;
565 This->pcsPin = pcsPin;
566 This->pFilter = pFilter;
567 This->pPinConnectedTo = NULL;
568 This->pMemInputPinConnectedTo = NULL;
569 This->pmtConn = NULL;
570 This->pAsyncOut = NULL;
572 This->pwszId = (WCHAR*)QUARTZ_AllocMem( This->cbIdLen );
573 if ( This->pwszId == NULL )
578 memcpy( This->pwszId, pwszId, This->cbIdLen );
583 CPinBaseImpl_UninitIPin( This );
587 void CPinBaseImpl_UninitIPin( CPinBaseImpl* This )
589 TRACE("(%p)\n",This);
591 IPin_Disconnect( (IPin*)(This) );
593 if ( This->pwszId != NULL )
595 QUARTZ_FreeMem( This->pwszId );
601 /***************************************************************************
603 * CMemInputPinBaseImpl
608 static HRESULT WINAPI
609 CMemInputPinBaseImpl_fnQueryInterface(IMemInputPin* iface,REFIID riid,void** ppobj)
611 ICOM_THIS(CMemInputPinBaseImpl,iface);
613 TRACE("(%p)->()\n",This);
615 return IUnknown_QueryInterface(This->punkControl,riid,ppobj);
619 CMemInputPinBaseImpl_fnAddRef(IMemInputPin* iface)
621 ICOM_THIS(CMemInputPinBaseImpl,iface);
623 TRACE("(%p)->()\n",This);
625 return IUnknown_AddRef(This->punkControl);
629 CMemInputPinBaseImpl_fnRelease(IMemInputPin* iface)
631 ICOM_THIS(CMemInputPinBaseImpl,iface);
633 TRACE("(%p)->()\n",This);
635 return IUnknown_Release(This->punkControl);
639 static HRESULT WINAPI
640 CMemInputPinBaseImpl_fnGetAllocator(IMemInputPin* iface,IMemAllocator** ppAllocator)
642 ICOM_THIS(CMemInputPinBaseImpl,iface);
643 HRESULT hr = NOERROR;
646 TRACE("(%p)->()\n",This);
648 if ( ppAllocator == NULL )
651 EnterCriticalSection( This->pPin->pcsPin );
653 if ( This->pAllocator == NULL )
655 hr = QUARTZ_CreateMemoryAllocator(NULL,(void**)&punk);
658 hr = IUnknown_QueryInterface(punk,
659 &IID_IMemAllocator,(void**)&This->pAllocator);
660 IUnknown_Release(punk);
666 *ppAllocator = This->pAllocator;
667 IMemAllocator_AddRef(This->pAllocator);
670 LeaveCriticalSection( This->pPin->pcsPin );
675 static HRESULT WINAPI
676 CMemInputPinBaseImpl_fnNotifyAllocator(IMemInputPin* iface,IMemAllocator* pAllocator,BOOL bReadonly)
678 ICOM_THIS(CMemInputPinBaseImpl,iface);
680 TRACE("(%p)->()\n",This);
682 if ( pAllocator == NULL )
685 EnterCriticalSection( This->pPin->pcsPin );
687 if ( This->pAllocator != NULL )
689 IMemAllocator_Release(This->pAllocator);
690 This->pAllocator = NULL;
692 This->pAllocator = pAllocator;
693 IMemAllocator_AddRef(This->pAllocator);
695 This->bReadonly = bReadonly;
697 LeaveCriticalSection( This->pPin->pcsPin );
702 static HRESULT WINAPI
703 CMemInputPinBaseImpl_fnGetAllocatorRequirements(IMemInputPin* iface,ALLOCATOR_PROPERTIES* pProp)
705 ICOM_THIS(CMemInputPinBaseImpl,iface);
707 TRACE("(%p)->(%p)\n",This,pProp);
712 /* E_MOTIMPL means 'no requirements' */
716 static HRESULT WINAPI
717 CMemInputPinBaseImpl_fnReceive(IMemInputPin* iface,IMediaSample* pSample)
719 ICOM_THIS(CMemInputPinBaseImpl,iface);
720 HRESULT hr = E_NOTIMPL;
722 TRACE("(%p)->(%p)\n",This,pSample);
724 EnterCriticalSection( This->pPin->pcsPin );
725 if ( This->pPin->pHandlers->pReceive != NULL )
726 hr = This->pPin->pHandlers->pReceive(This->pPin,pSample);
727 LeaveCriticalSection( This->pPin->pcsPin );
732 static HRESULT WINAPI
733 CMemInputPinBaseImpl_fnReceiveMultiple(IMemInputPin* iface,IMediaSample** ppSample,long nSample,long* pnSampleProcessed)
735 ICOM_THIS(CMemInputPinBaseImpl,iface);
739 TRACE("(%p)->()\n",This);
741 if ( ppSample == NULL || pnSampleProcessed == NULL )
744 EnterCriticalSection( This->pPin->pcsPin );
747 for ( n = 0; n < nSample; n++ )
749 hr = IMemInputPin_Receive(iface,ppSample[n]);
754 LeaveCriticalSection( This->pPin->pcsPin );
756 *pnSampleProcessed = n;
760 static HRESULT WINAPI
761 CMemInputPinBaseImpl_fnReceiveCanBlock(IMemInputPin* iface)
763 ICOM_THIS(CMemInputPinBaseImpl,iface);
764 HRESULT hr = E_NOTIMPL;
766 TRACE("(%p)->()\n",This);
768 EnterCriticalSection( This->pPin->pcsPin );
769 if ( This->pPin->pHandlers->pReceiveCanBlock != NULL )
770 hr = This->pPin->pHandlers->pReceiveCanBlock(This->pPin);
771 LeaveCriticalSection( This->pPin->pcsPin );
777 static ICOM_VTABLE(IMemInputPin) imeminputpin =
779 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
780 /* IUnknown fields */
781 CMemInputPinBaseImpl_fnQueryInterface,
782 CMemInputPinBaseImpl_fnAddRef,
783 CMemInputPinBaseImpl_fnRelease,
784 /* IMemInputPin fields */
785 CMemInputPinBaseImpl_fnGetAllocator,
786 CMemInputPinBaseImpl_fnNotifyAllocator,
787 CMemInputPinBaseImpl_fnGetAllocatorRequirements,
788 CMemInputPinBaseImpl_fnReceive,
789 CMemInputPinBaseImpl_fnReceiveMultiple,
790 CMemInputPinBaseImpl_fnReceiveCanBlock,
793 HRESULT CMemInputPinBaseImpl_InitIMemInputPin(
794 CMemInputPinBaseImpl* This, IUnknown* punkControl,
797 TRACE("(%p,%p)\n",This,punkControl);
799 if ( punkControl == NULL )
801 ERR( "punkControl must not be NULL\n" );
805 ICOM_VTBL(This) = &imeminputpin;
806 This->punkControl = punkControl;
808 This->pAllocator = NULL;
809 This->bReadonly = FALSE;
814 void CMemInputPinBaseImpl_UninitIMemInputPin(
815 CMemInputPinBaseImpl* This )
817 TRACE("(%p)\n",This);
819 if ( This->pAllocator != NULL )
821 IMemAllocator_Release(This->pAllocator);
822 This->pAllocator = NULL;
826 /***************************************************************************
828 * CQualityControlPassThruImpl
832 static HRESULT WINAPI
833 CQualityControlPassThruImpl_fnQueryInterface(IQualityControl* iface,REFIID riid,void** ppobj)
835 ICOM_THIS(CQualityControlPassThruImpl,iface);
837 TRACE("(%p)->()\n",This);
839 return IUnknown_QueryInterface(This->punkControl,riid,ppobj);
843 CQualityControlPassThruImpl_fnAddRef(IQualityControl* iface)
845 ICOM_THIS(CQualityControlPassThruImpl,iface);
847 TRACE("(%p)->()\n",This);
849 return IUnknown_AddRef(This->punkControl);
853 CQualityControlPassThruImpl_fnRelease(IQualityControl* iface)
855 ICOM_THIS(CQualityControlPassThruImpl,iface);
857 TRACE("(%p)->()\n",This);
859 return IUnknown_Release(This->punkControl);
863 static HRESULT WINAPI
864 CQualityControlPassThruImpl_fnNotify(IQualityControl* iface,IBaseFilter* pFilter,Quality q)
866 ICOM_THIS(CQualityControlPassThruImpl,iface);
867 HRESULT hr = S_FALSE;
869 TRACE("(%p)->()\n",This);
871 if ( This->pControl != NULL )
872 return IQualityControl_Notify( This->pControl, pFilter, q );
874 EnterCriticalSection( This->pPin->pcsPin );
875 if ( This->pPin->pHandlers->pQualityNotify != NULL )
876 hr = This->pPin->pHandlers->pQualityNotify(This->pPin,pFilter,q);
877 LeaveCriticalSection( This->pPin->pcsPin );
882 static HRESULT WINAPI
883 CQualityControlPassThruImpl_fnSetSink(IQualityControl* iface,IQualityControl* pControl)
885 ICOM_THIS(CQualityControlPassThruImpl,iface);
887 TRACE("(%p)->()\n",This);
889 This->pControl = pControl; /* AddRef() must not be called */
894 static ICOM_VTABLE(IQualityControl) iqualitycontrol =
896 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
897 /* IUnknown fields */
898 CQualityControlPassThruImpl_fnQueryInterface,
899 CQualityControlPassThruImpl_fnAddRef,
900 CQualityControlPassThruImpl_fnRelease,
901 /* IQualityControl fields */
902 CQualityControlPassThruImpl_fnNotify,
903 CQualityControlPassThruImpl_fnSetSink,
906 HRESULT CQualityControlPassThruImpl_InitIQualityControl(
907 CQualityControlPassThruImpl* This, IUnknown* punkControl,
910 TRACE("(%p,%p)\n",This,punkControl);
912 if ( punkControl == NULL )
914 ERR( "punkControl must not be NULL\n" );
918 ICOM_VTBL(This) = &iqualitycontrol;
919 This->punkControl = punkControl;
925 void CQualityControlPassThruImpl_UninitIQualityControl(
926 CQualityControlPassThruImpl* This )
930 /***************************************************************************
932 * helper methods for output pins.
936 HRESULT CPinBaseImpl_SendSample( CPinBaseImpl* This, IMediaSample* pSample )
938 if ( This->pHandlers->pReceive == NULL )
941 return This->pHandlers->pReceive( This, pSample );
944 HRESULT CPinBaseImpl_SendEndOfStream( CPinBaseImpl* This )
946 if ( This->pHandlers->pEndOfStream == NULL )
949 return This->pHandlers->pEndOfStream( This );
952 HRESULT CPinBaseImpl_SendBeginFlush( CPinBaseImpl* This )
954 if ( This->pHandlers->pBeginFlush == NULL )
957 return This->pHandlers->pBeginFlush( This );
960 HRESULT CPinBaseImpl_SendEndFlush( CPinBaseImpl* This )
962 if ( This->pHandlers->pEndFlush == NULL )
965 return This->pHandlers->pEndFlush( This );
968 HRESULT CPinBaseImpl_SendNewSegment( CPinBaseImpl* This, REFERENCE_TIME rtStart, REFERENCE_TIME rtStop, double rate )
970 if ( This->pHandlers->pNewSegment == NULL )
973 return This->pHandlers->pNewSegment( This, rtStart, rtStop, rate );
978 /***************************************************************************
980 * handlers for output pins.
984 HRESULT OutputPinSync_Receive( CPinBaseImpl* pImpl, IMediaSample* pSample )
986 if ( pImpl->pMemInputPinConnectedTo == NULL )
989 return IMemInputPin_Receive(pImpl->pMemInputPinConnectedTo,pSample);
992 HRESULT OutputPinSync_ReceiveCanBlock( CPinBaseImpl* pImpl )
994 if ( pImpl->pMemInputPinConnectedTo == NULL )
997 return IMemInputPin_ReceiveCanBlock(pImpl->pMemInputPinConnectedTo);
1000 HRESULT OutputPinSync_EndOfStream( CPinBaseImpl* pImpl )
1002 if ( pImpl->pPinConnectedTo == NULL )
1005 return IPin_EndOfStream(pImpl->pPinConnectedTo);
1008 HRESULT OutputPinSync_BeginFlush( CPinBaseImpl* pImpl )
1010 if ( pImpl->pPinConnectedTo == NULL )
1013 return IPin_BeginFlush(pImpl->pPinConnectedTo);
1016 HRESULT OutputPinSync_EndFlush( CPinBaseImpl* pImpl )
1018 if ( pImpl->pPinConnectedTo == NULL )
1021 return IPin_EndFlush(pImpl->pPinConnectedTo);
1024 HRESULT OutputPinSync_NewSegment( CPinBaseImpl* pImpl, REFERENCE_TIME rtStart, REFERENCE_TIME rtStop, double rate )
1026 if ( pImpl->pPinConnectedTo == NULL )
1029 return IPin_NewSegment(pImpl->pPinConnectedTo,rtStart,rtStop,rate);
1032 /***************************************************************************
1034 * handlers for output pins (async).
1038 typedef struct OutputPinTask OutputPinTask;
1040 enum OutputPinTaskType
1044 OutTask_EndOfStream,
1050 struct OutputPinTask
1052 OutputPinTask* pNext;
1053 enum OutputPinTaskType tasktype;
1054 IMediaSample* pSample;
1055 REFERENCE_TIME rtStart;
1056 REFERENCE_TIME rtStop;
1060 struct OutputPinAsyncImpl
1062 HANDLE m_hTaskThread;
1063 HANDLE m_hTaskEvent;
1064 IPin* m_pPin; /* connected pin */
1065 IMemInputPin* m_pMemInputPin; /* connected pin */
1066 CRITICAL_SECTION m_csTasks;
1067 OutputPinTask* m_pFirst;
1068 OutputPinTask* m_pLast;
1069 OutputPinTask* m_pTaskExitThread;
1072 static OutputPinTask* OutputPinAsync_AllocTask( enum OutputPinTaskType tasktype )
1074 OutputPinTask* pTask;
1076 pTask = (OutputPinTask*)QUARTZ_AllocMem( sizeof(OutputPinTask) );
1077 pTask->pNext = NULL;
1078 pTask->tasktype = tasktype;
1079 pTask->pSample = NULL;
1084 static void OutputPinAsync_FreeTask( OutputPinTask* pTask )
1086 if ( pTask->pSample != NULL )
1087 IMediaSample_Release( pTask->pSample );
1088 QUARTZ_FreeMem( pTask );
1091 static void OutputPinAsync_AddTask( OutputPinAsyncImpl* This, OutputPinTask* pTask, BOOL bFirst )
1093 EnterCriticalSection( &This->m_csTasks );
1097 pTask->pNext = This->m_pFirst;
1098 This->m_pFirst = pTask;
1099 if ( This->m_pLast == NULL )
1100 This->m_pLast = pTask;
1104 if ( This->m_pLast != NULL )
1105 This->m_pLast->pNext = pTask;
1107 This->m_pFirst = pTask;
1108 This->m_pLast = pTask;
1111 LeaveCriticalSection( &This->m_csTasks );
1113 SetEvent( This->m_hTaskEvent );
1116 static OutputPinTask* OutputPinAsync_GetNextTask( OutputPinAsyncImpl* This )
1118 OutputPinTask* pTask;
1120 EnterCriticalSection( &This->m_csTasks );
1121 pTask = This->m_pFirst;
1122 if ( pTask != NULL )
1124 This->m_pFirst = pTask->pNext;
1125 if ( This->m_pFirst == NULL )
1126 This->m_pLast = NULL;
1128 SetEvent( This->m_hTaskEvent );
1131 LeaveCriticalSection( &This->m_csTasks );
1136 static DWORD WINAPI OutputPinAsync_ThreadEntry( LPVOID pv )
1138 OutputPinAsyncImpl* This = ((CPinBaseImpl*)pv)->pAsyncOut;
1139 OutputPinTask* pTask;
1141 BOOL bInFlush = FALSE;
1146 WaitForSingleObject( This->m_hTaskEvent, INFINITE );
1147 ResetEvent( This->m_hTaskEvent );
1149 pTask = OutputPinAsync_GetNextTask( This );
1150 if ( pTask == NULL )
1154 switch ( pTask->tasktype )
1156 case OutTask_ExitThread:
1159 case OutTask_Receive:
1161 hr = IMemInputPin_Receive( This->m_pMemInputPin, pTask->pSample );
1163 case OutTask_EndOfStream:
1164 hr = IPin_EndOfStream( This->m_pPin );
1166 case OutTask_BeginFlush:
1168 hr = IPin_BeginFlush( This->m_pPin );
1170 case OutTask_EndFlush:
1172 hr = IPin_EndFlush( This->m_pPin );
1174 case OutTask_NewSegment:
1175 hr = IPin_NewSegment( This->m_pPin, pTask->rtStart, pTask->rtStop, pTask->rate );
1178 ERR( "unexpected task type %d.\n", pTask->tasktype );
1183 OutputPinAsync_FreeTask( pTask );
1187 ERR( "hresult %08lx\n", hr );
1195 HRESULT OutputPinAsync_OnActive( CPinBaseImpl* pImpl )
1200 FIXME("(%p)\n",pImpl);
1202 if ( pImpl->pMemInputPinConnectedTo == NULL )
1205 pImpl->pAsyncOut = (OutputPinAsyncImpl*)
1206 QUARTZ_AllocMem( sizeof( OutputPinAsyncImpl ) );
1207 if ( pImpl->pAsyncOut == NULL )
1208 return E_OUTOFMEMORY;
1210 InitializeCriticalSection( &pImpl->pAsyncOut->m_csTasks );
1211 pImpl->pAsyncOut->m_hTaskThread = (HANDLE)NULL;
1212 pImpl->pAsyncOut->m_hTaskEvent = (HANDLE)NULL;
1213 pImpl->pAsyncOut->m_pFirst = NULL;
1214 pImpl->pAsyncOut->m_pLast = NULL;
1215 pImpl->pAsyncOut->m_pTaskExitThread = NULL;
1216 pImpl->pAsyncOut->m_pPin = pImpl->pPinConnectedTo;
1217 pImpl->pAsyncOut->m_pMemInputPin = pImpl->pMemInputPinConnectedTo;
1219 pImpl->pAsyncOut->m_hTaskEvent =
1220 CreateEventA( NULL, TRUE, FALSE, NULL );
1221 if ( pImpl->pAsyncOut->m_hTaskEvent == (HANDLE)NULL )
1227 pImpl->pAsyncOut->m_pTaskExitThread =
1228 OutputPinAsync_AllocTask( OutTask_ExitThread );
1229 if ( pImpl->pAsyncOut->m_pTaskExitThread == NULL )
1235 pImpl->pAsyncOut->m_hTaskThread = CreateThread(
1236 NULL, 0, OutputPinAsync_ThreadEntry, pImpl,
1238 if ( pImpl->pAsyncOut->m_hTaskThread == (HANDLE)NULL )
1246 OutputPinAsync_OnInactive( pImpl );
1250 HRESULT OutputPinAsync_OnInactive( CPinBaseImpl* pImpl )
1252 OutputPinTask* pTask;
1254 FIXME("(%p)\n",pImpl);
1256 if ( pImpl->pAsyncOut == NULL )
1259 if ( pImpl->pAsyncOut->m_pTaskExitThread != NULL )
1261 OutputPinAsync_AddTask( pImpl->pAsyncOut, pImpl->pAsyncOut->m_pTaskExitThread, TRUE );
1262 pImpl->pAsyncOut->m_pTaskExitThread = NULL;
1265 if ( pImpl->pAsyncOut->m_hTaskThread != (HANDLE)NULL )
1267 WaitForSingleObject( pImpl->pAsyncOut->m_hTaskThread, INFINITE );
1268 CloseHandle( pImpl->pAsyncOut->m_hTaskThread );
1270 if ( pImpl->pAsyncOut->m_hTaskEvent != (HANDLE)NULL )
1271 CloseHandle( pImpl->pAsyncOut->m_hTaskEvent );
1273 /* release all tasks. */
1276 pTask = OutputPinAsync_GetNextTask( pImpl->pAsyncOut );
1277 if ( pTask == NULL )
1279 OutputPinAsync_FreeTask( pTask );
1282 DeleteCriticalSection( &pImpl->pAsyncOut->m_csTasks );
1284 QUARTZ_FreeMem( pImpl->pAsyncOut );
1285 pImpl->pAsyncOut = NULL;
1290 HRESULT OutputPinAsync_Receive( CPinBaseImpl* pImpl, IMediaSample* pSample )
1292 OutputPinAsyncImpl* This = pImpl->pAsyncOut;
1293 OutputPinTask* pTask;
1295 TRACE("(%p,%p)\n",pImpl,pSample);
1300 pTask = OutputPinAsync_AllocTask( OutTask_Receive );
1301 if ( pTask == NULL )
1302 return E_OUTOFMEMORY;
1303 pTask->pSample = pSample; IMediaSample_AddRef( pSample );
1304 OutputPinAsync_AddTask( pImpl->pAsyncOut, pTask, FALSE );
1309 HRESULT OutputPinAsync_ReceiveCanBlock( CPinBaseImpl* pImpl )
1314 HRESULT OutputPinAsync_EndOfStream( CPinBaseImpl* pImpl )
1316 OutputPinAsyncImpl* This = pImpl->pAsyncOut;
1317 OutputPinTask* pTask;
1319 TRACE("(%p)\n",pImpl);
1324 pTask = OutputPinAsync_AllocTask( OutTask_EndOfStream );
1325 if ( pTask == NULL )
1326 return E_OUTOFMEMORY;
1327 OutputPinAsync_AddTask( pImpl->pAsyncOut, pTask, FALSE );
1332 HRESULT OutputPinAsync_BeginFlush( CPinBaseImpl* pImpl )
1334 OutputPinAsyncImpl* This = pImpl->pAsyncOut;
1335 OutputPinTask* pTask;
1337 TRACE("(%p)\n",pImpl);
1342 pTask = OutputPinAsync_AllocTask( OutTask_BeginFlush );
1343 if ( pTask == NULL )
1344 return E_OUTOFMEMORY;
1345 OutputPinAsync_AddTask( pImpl->pAsyncOut, pTask, TRUE );
1350 HRESULT OutputPinAsync_EndFlush( CPinBaseImpl* pImpl )
1352 OutputPinAsyncImpl* This = pImpl->pAsyncOut;
1353 OutputPinTask* pTask;
1355 TRACE("(%p)\n",pImpl);
1360 pTask = OutputPinAsync_AllocTask( OutTask_EndFlush );
1361 if ( pTask == NULL )
1362 return E_OUTOFMEMORY;
1363 OutputPinAsync_AddTask( pImpl->pAsyncOut, pTask, FALSE );
1368 HRESULT OutputPinAsync_NewSegment( CPinBaseImpl* pImpl, REFERENCE_TIME rtStart, REFERENCE_TIME rtStop, double rate )
1370 OutputPinAsyncImpl* This = pImpl->pAsyncOut;
1371 OutputPinTask* pTask;
1373 TRACE("(%p)\n",pImpl);
1378 pTask = OutputPinAsync_AllocTask( OutTask_NewSegment );
1379 if ( pTask == NULL )
1380 return E_OUTOFMEMORY;
1381 pTask->rtStart = rtStart;
1382 pTask->rtStop = rtStop;
1384 OutputPinAsync_AddTask( pImpl->pAsyncOut, pTask, FALSE );