diff --git a/dlls/quartz/acmwrapper.c b/dlls/quartz/acmwrapper.c index 506e6547356..ec9ca75d429 100644 --- a/dlls/quartz/acmwrapper.c +++ b/dlls/quartz/acmwrapper.c @@ -52,8 +52,9 @@ typedef struct ACMWrapperImpl LONGLONG lasttime_sent; } ACMWrapperImpl; -static HRESULT ACMWrapper_ProcessSampleData(InputPin *pin, IMediaSample *pSample) +static HRESULT WINAPI ACMWrapper_ProcessSampleData(IPin *iface, IMediaSample *pSample) { + BaseInputPin *pin = (BaseInputPin*) iface; ACMWrapperImpl* This = (ACMWrapperImpl*)pin->pin.pinInfo.pFilter; AM_MEDIA_TYPE amt; IMediaSample* pOutSample = NULL; @@ -234,7 +235,7 @@ error: return hr; } -static HRESULT ACMWrapper_ConnectInput(InputPin *pin, const AM_MEDIA_TYPE * pmt) +static HRESULT ACMWrapper_ConnectInput(BaseInputPin *pin, const AM_MEDIA_TYPE * pmt) { ACMWrapperImpl* This = (ACMWrapperImpl *)pin->pin.pinInfo.pFilter; MMRESULT res; @@ -286,7 +287,7 @@ static HRESULT ACMWrapper_ConnectInput(InputPin *pin, const AM_MEDIA_TYPE * pmt) return VFW_E_TYPE_NOT_ACCEPTED; } -static HRESULT ACMWrapper_Cleanup(InputPin *pin) +static HRESULT ACMWrapper_Cleanup(BaseInputPin *pin) { ACMWrapperImpl *This = (ACMWrapperImpl *)pin->pin.pinInfo.pFilter; diff --git a/dlls/quartz/avidec.c b/dlls/quartz/avidec.c index d09b97eca1e..aeabc024472 100644 --- a/dlls/quartz/avidec.c +++ b/dlls/quartz/avidec.c @@ -66,8 +66,9 @@ static HRESULT AVIDec_ProcessBegin(TransformFilterImpl* pTransformFilter) return S_OK; } -static HRESULT AVIDec_ProcessSampleData(InputPin *pin, IMediaSample *pSample) +static HRESULT WINAPI AVIDec_ProcessSampleData(IPin *iface, IMediaSample *pSample) { + BaseInputPin *pin = (BaseInputPin*)iface; AVIDecImpl* This = (AVIDecImpl *)pin->pin.pinInfo.pFilter; AM_MEDIA_TYPE amt; HRESULT hr; @@ -182,7 +183,7 @@ static HRESULT AVIDec_ProcessEnd(TransformFilterImpl* pTransformFilter) return S_OK; } -static HRESULT AVIDec_ConnectInput(InputPin *pin, const AM_MEDIA_TYPE * pmt) +static HRESULT AVIDec_ConnectInput(BaseInputPin *pin, const AM_MEDIA_TYPE * pmt) { AVIDecImpl* This = (AVIDecImpl*)pin->pin.pinInfo.pFilter; HRESULT hr = VFW_E_TYPE_NOT_ACCEPTED; @@ -283,7 +284,7 @@ failed: return hr; } -static HRESULT AVIDec_Cleanup(InputPin *pin) +static HRESULT AVIDec_Cleanup(BaseInputPin *pin) { AVIDecImpl *This = (AVIDecImpl *)pin->pin.pinInfo.pFilter; diff --git a/dlls/quartz/dsoundrender.c b/dlls/quartz/dsoundrender.c index 63846ce3b25..d102c0ad23b 100644 --- a/dlls/quartz/dsoundrender.c +++ b/dlls/quartz/dsoundrender.c @@ -63,7 +63,7 @@ typedef struct DSoundRenderImpl IReferenceClock * pClock; FILTER_INFO filterInfo; - InputPin * pInputPin; + BaseInputPin * pInputPin; IDirectSound8 *dsound; LPDIRECTSOUNDBUFFER dsbuffer; @@ -211,9 +211,10 @@ static HRESULT DSoundRender_SendSampleData(DSoundRenderImpl* This, const BYTE *d return hr; } -static HRESULT DSoundRender_Sample(LPVOID iface, IMediaSample * pSample) +static HRESULT WINAPI DSoundRender_Receive(IPin *iface, IMediaSample * pSample) { - DSoundRenderImpl *This = iface; + BaseInputPin *pin = (BaseInputPin*)iface; + DSoundRenderImpl *This = (DSoundRenderImpl*)pin->pin.pinInfo.pFilter; LPBYTE pbSrcStream = NULL; LONG cbSrcStream = 0; REFERENCE_TIME tStart, tStop; @@ -344,7 +345,7 @@ static HRESULT DSoundRender_Sample(LPVOID iface, IMediaSample * pSample) return hr; } -static HRESULT DSoundRender_QueryAccept(LPVOID iface, const AM_MEDIA_TYPE * pmt) +static HRESULT WINAPI DSoundRender_CheckMediaType(IPin *iface, const AM_MEDIA_TYPE * pmt) { WAVEFORMATEX* format; @@ -397,7 +398,7 @@ HRESULT DSoundRender_create(IUnknown * pUnkOuter, LPVOID * ppv) piInput.dir = PINDIR_INPUT; piInput.pFilter = (IBaseFilter *)pDSoundRender; lstrcpynW(piInput.achName, wcsInputPinName, sizeof(piInput.achName) / sizeof(piInput.achName[0])); - hr = InputPin_Construct(&DSoundRender_InputPin_Vtbl, &piInput, DSoundRender_Sample, pDSoundRender, DSoundRender_QueryAccept, NULL, &pDSoundRender->csFilter, NULL, (IPin **)&pDSoundRender->pInputPin); + hr = BaseInputPin_Construct(&DSoundRender_InputPin_Vtbl, &piInput, DSoundRender_CheckMediaType, DSoundRender_Receive, &pDSoundRender->csFilter, NULL, (IPin **)&pDSoundRender->pInputPin); if (SUCCEEDED(hr)) { @@ -809,7 +810,7 @@ static const IBaseFilterVtbl DSoundRender_Vtbl = static HRESULT WINAPI DSoundRender_InputPin_ReceiveConnection(IPin * iface, IPin * pReceivePin, const AM_MEDIA_TYPE * pmt) { - InputPin *This = (InputPin *)iface; + BaseInputPin *This = (BaseInputPin *)iface; PIN_DIRECTION pindirReceive; DSoundRenderImpl *DSImpl; HRESULT hr = S_OK; @@ -825,7 +826,7 @@ static HRESULT WINAPI DSoundRender_InputPin_ReceiveConnection(IPin * iface, IPin if (This->pin.pConnectedTo) hr = VFW_E_ALREADY_CONNECTED; - if (SUCCEEDED(hr) && This->fnQueryAccept(This->pUserData, pmt) != S_OK) + if (SUCCEEDED(hr) && This->fnCheckMediaType(iface, pmt) != S_OK) hr = VFW_E_TYPE_NOT_ACCEPTED; if (SUCCEEDED(hr)) @@ -914,7 +915,7 @@ static HRESULT WINAPI DSoundRender_InputPin_Disconnect(IPin * iface) static HRESULT WINAPI DSoundRender_InputPin_EndOfStream(IPin * iface) { - InputPin* This = (InputPin*)iface; + BaseInputPin* This = (BaseInputPin*)iface; DSoundRenderImpl *me = (DSoundRenderImpl*)This->pin.pinInfo.pFilter; IMediaEventSink* pEventSink; HRESULT hr; @@ -922,7 +923,7 @@ static HRESULT WINAPI DSoundRender_InputPin_EndOfStream(IPin * iface) EnterCriticalSection(This->pin.pCritSec); TRACE("(%p/%p)->()\n", This, iface); - hr = InputPin_EndOfStream(iface); + hr = BaseInputPinImpl_EndOfStream(iface); if (hr != S_OK) { ERR("%08x\n", hr); @@ -954,14 +955,14 @@ static HRESULT WINAPI DSoundRender_InputPin_EndOfStream(IPin * iface) static HRESULT WINAPI DSoundRender_InputPin_BeginFlush(IPin * iface) { - InputPin *This = (InputPin *)iface; + BaseInputPin *This = (BaseInputPin *)iface; DSoundRenderImpl *pFilter = (DSoundRenderImpl *)This->pin.pinInfo.pFilter; HRESULT hr; TRACE("\n"); EnterCriticalSection(This->pin.pCritSec); - hr = InputPin_BeginFlush(iface); + hr = BaseInputPinImpl_BeginFlush(iface); SetEvent(pFilter->blocked); LeaveCriticalSection(This->pin.pCritSec); @@ -970,7 +971,7 @@ static HRESULT WINAPI DSoundRender_InputPin_BeginFlush(IPin * iface) static HRESULT WINAPI DSoundRender_InputPin_EndFlush(IPin * iface) { - InputPin *This = (InputPin *)iface; + BaseInputPin *This = (BaseInputPin *)iface; DSoundRenderImpl *pFilter = (DSoundRenderImpl *)This->pin.pinInfo.pFilter; HRESULT hr; @@ -1002,7 +1003,7 @@ static HRESULT WINAPI DSoundRender_InputPin_EndFlush(IPin * iface) memset(buffer, 0, size); IDirectSoundBuffer_Unlock(pFilter->dsbuffer, buffer, size, NULL, 0); } - hr = InputPin_EndFlush(iface); + hr = BaseInputPinImpl_EndFlush(iface); LeaveCriticalSection(This->pin.pCritSec); MediaSeekingPassThru_ResetMediaTime(pFilter->seekthru_unk); @@ -1011,10 +1012,10 @@ static HRESULT WINAPI DSoundRender_InputPin_EndFlush(IPin * iface) static const IPinVtbl DSoundRender_InputPin_Vtbl = { - InputPin_QueryInterface, + BaseInputPinImpl_QueryInterface, BasePinImpl_AddRef, - InputPin_Release, - InputPin_Connect, + BaseInputPinImpl_Release, + BaseInputPinImpl_Connect, DSoundRender_InputPin_ReceiveConnection, DSoundRender_InputPin_Disconnect, BasePinImpl_ConnectedTo, @@ -1022,13 +1023,13 @@ static const IPinVtbl DSoundRender_InputPin_Vtbl = BasePinImpl_QueryPinInfo, BasePinImpl_QueryDirection, BasePinImpl_QueryId, - InputPin_QueryAccept, + BaseInputPinImpl_QueryAccept, BasePinImpl_EnumMediaTypes, BasePinImpl_QueryInternalConnections, DSoundRender_InputPin_EndOfStream, DSoundRender_InputPin_BeginFlush, DSoundRender_InputPin_EndFlush, - InputPin_NewSegment + BaseInputPinImpl_NewSegment }; /*** IUnknown methods ***/ diff --git a/dlls/quartz/nullrenderer.c b/dlls/quartz/nullrenderer.c index 954f93e38cf..b82be2f8ba3 100644 --- a/dlls/quartz/nullrenderer.c +++ b/dlls/quartz/nullrenderer.c @@ -62,15 +62,16 @@ typedef struct NullRendererImpl IReferenceClock * pClock; FILTER_INFO filterInfo; - InputPin *pInputPin; + BaseInputPin *pInputPin; IUnknown * pUnkOuter; BOOL bUnkOuterValid; BOOL bAggregatable; } NullRendererImpl; -static HRESULT NullRenderer_Sample(LPVOID iface, IMediaSample * pSample) +static HRESULT WINAPI NullRenderer_Receive(IPin *iface, IMediaSample * pSample) { - NullRendererImpl *This = iface; + BaseInputPin *pin = (BaseInputPin*)iface; + NullRendererImpl *This = ((NullRendererImpl*)pin->pin.pinInfo.pFilter); HRESULT hr = S_OK; REFERENCE_TIME start, stop; @@ -86,7 +87,7 @@ static HRESULT NullRenderer_Sample(LPVOID iface, IMediaSample * pSample) return hr; } -static HRESULT NullRenderer_QueryAccept(LPVOID iface, const AM_MEDIA_TYPE * pmt) +static HRESULT WINAPI NullRenderer_CheckMediaType(IPin *iface, const AM_MEDIA_TYPE * pmt) { TRACE("Not a stub!\n"); return S_OK; @@ -121,7 +122,7 @@ HRESULT NullRenderer_create(IUnknown * pUnkOuter, LPVOID * ppv) piInput.pFilter = (IBaseFilter *)pNullRenderer; lstrcpynW(piInput.achName, wcsInputPinName, sizeof(piInput.achName) / sizeof(piInput.achName[0])); - hr = InputPin_Construct(&NullRenderer_InputPin_Vtbl, &piInput, NullRenderer_Sample, (LPVOID)pNullRenderer, NullRenderer_QueryAccept, NULL, &pNullRenderer->csFilter, NULL, (IPin **)&pNullRenderer->pInputPin); + hr = BaseInputPin_Construct(&NullRenderer_InputPin_Vtbl, &piInput, NullRenderer_CheckMediaType, NullRenderer_Receive, &pNullRenderer->csFilter, NULL, (IPin **)&pNullRenderer->pInputPin); if (SUCCEEDED(hr)) { @@ -511,7 +512,7 @@ static const IBaseFilterVtbl NullRenderer_Vtbl = static HRESULT WINAPI NullRenderer_InputPin_EndOfStream(IPin * iface) { - InputPin* This = (InputPin*)iface; + BaseInputPin* This = (BaseInputPin*)iface; IMediaEventSink* pEventSink; NullRendererImpl *pNull; IFilterGraph *graph; @@ -519,7 +520,7 @@ static HRESULT WINAPI NullRenderer_InputPin_EndOfStream(IPin * iface) TRACE("(%p/%p)->()\n", This, iface); - InputPin_EndOfStream(iface); + BaseInputPinImpl_EndOfStream(iface); pNull = (NullRendererImpl*)This->pin.pinInfo.pFilter; graph = pNull->filterInfo.pGraph; if (graph) @@ -538,13 +539,13 @@ static HRESULT WINAPI NullRenderer_InputPin_EndOfStream(IPin * iface) static HRESULT WINAPI NullRenderer_InputPin_EndFlush(IPin * iface) { - InputPin* This = (InputPin*)iface; + BaseInputPin* This = (BaseInputPin*)iface; NullRendererImpl *pNull; HRESULT hr = S_OK; TRACE("(%p/%p)->()\n", This, iface); - hr = InputPin_EndOfStream(iface); + hr = BaseInputPinImpl_EndOfStream(iface); pNull = (NullRendererImpl*)This->pin.pinInfo.pFilter; MediaSeekingPassThru_ResetMediaTime(pNull->seekthru_unk); return hr; @@ -552,22 +553,22 @@ static HRESULT WINAPI NullRenderer_InputPin_EndFlush(IPin * iface) static const IPinVtbl NullRenderer_InputPin_Vtbl = { - InputPin_QueryInterface, + BaseInputPinImpl_QueryInterface, BasePinImpl_AddRef, - InputPin_Release, - InputPin_Connect, - InputPin_ReceiveConnection, + BaseInputPinImpl_Release, + BaseInputPinImpl_Connect, + BaseInputPinImpl_ReceiveConnection, BasePinImpl_Disconnect, BasePinImpl_ConnectedTo, BasePinImpl_ConnectionMediaType, BasePinImpl_QueryPinInfo, BasePinImpl_QueryDirection, BasePinImpl_QueryId, - InputPin_QueryAccept, + BaseInputPinImpl_QueryAccept, BasePinImpl_EnumMediaTypes, BasePinImpl_QueryInternalConnections, NullRenderer_InputPin_EndOfStream, - InputPin_BeginFlush, + BaseInputPinImpl_BeginFlush, NullRenderer_InputPin_EndFlush, - InputPin_NewSegment + BaseInputPinImpl_NewSegment }; diff --git a/dlls/quartz/parser.c b/dlls/quartz/parser.c index 22a2c8be594..8f6edbbb6e0 100644 --- a/dlls/quartz/parser.c +++ b/dlls/quartz/parser.c @@ -781,7 +781,7 @@ static const IPinVtbl Parser_InputPin_Vtbl = PullPin_QueryInterface, BasePinImpl_AddRef, PullPin_Release, - InputPin_Connect, + BaseInputPinImpl_Connect, Parser_PullPin_ReceiveConnection, Parser_PullPin_Disconnect, BasePinImpl_ConnectedTo, diff --git a/dlls/quartz/pin.c b/dlls/quartz/pin.c index e45c0c01994..118be2ce202 100644 --- a/dlls/quartz/pin.c +++ b/dlls/quartz/pin.c @@ -29,8 +29,6 @@ WINE_DEFAULT_DEBUG_CHANNEL(quartz); -static const IPinVtbl InputPin_Vtbl; -static const IMemInputPinVtbl MemInputPin_Vtbl; static const IPinVtbl PullPin_Vtbl; #define ALIGNDOWN(value,boundary) ((value)/(boundary)*(boundary)) @@ -153,184 +151,21 @@ static void Copy_PinInfo(PIN_INFO * pDest, const PIN_INFO * pSrc) pDest->pFilter = pSrc->pFilter; } -/*** IPin implementation for an input pin ***/ - -HRESULT WINAPI InputPin_QueryInterface(IPin * iface, REFIID riid, LPVOID * ppv) -{ - InputPin *This = (InputPin *)iface; - - TRACE("(%p)->(%s, %p)\n", iface, qzdebugstr_guid(riid), ppv); - - *ppv = NULL; - - if (IsEqualIID(riid, &IID_IUnknown)) - *ppv = iface; - else if (IsEqualIID(riid, &IID_IPin)) - *ppv = iface; - else if (IsEqualIID(riid, &IID_IMemInputPin)) - *ppv = &This->lpVtblMemInput; - else if (IsEqualIID(riid, &IID_IMediaSeeking)) - { - return IBaseFilter_QueryInterface(This->pin.pinInfo.pFilter, &IID_IMediaSeeking, ppv); - } - - if (*ppv) - { - IUnknown_AddRef((IUnknown *)(*ppv)); - return S_OK; - } - - FIXME("No interface for %s!\n", qzdebugstr_guid(riid)); - - return E_NOINTERFACE; -} - -ULONG WINAPI InputPin_Release(IPin * iface) -{ - InputPin *This = (InputPin *)iface; - ULONG refCount = InterlockedDecrement(&This->pin.refCount); - - TRACE("(%p)->() Release from %d\n", iface, refCount + 1); - - if (!refCount) - { - FreeMediaType(&This->pin.mtCurrent); - if (This->pAllocator) - IMemAllocator_Release(This->pAllocator); - This->pAllocator = NULL; - This->pin.lpVtbl = NULL; - CoTaskMemFree(This); - return 0; - } - else - return refCount; -} - -HRESULT WINAPI InputPin_Connect(IPin * iface, IPin * pConnector, const AM_MEDIA_TYPE * pmt) -{ - ERR("Outgoing connection on an input pin! (%p, %p)\n", pConnector, pmt); - - return E_UNEXPECTED; -} - - -HRESULT WINAPI InputPin_ReceiveConnection(IPin * iface, IPin * pReceivePin, const AM_MEDIA_TYPE * pmt) -{ - InputPin *This = (InputPin *)iface; - PIN_DIRECTION pindirReceive; - HRESULT hr = S_OK; - - TRACE("(%p, %p)\n", pReceivePin, pmt); - dump_AM_MEDIA_TYPE(pmt); - - EnterCriticalSection(This->pin.pCritSec); - { - if (This->pin.pConnectedTo) - hr = VFW_E_ALREADY_CONNECTED; - - if (SUCCEEDED(hr) && This->fnQueryAccept(This->pUserData, pmt) != S_OK) - hr = VFW_E_TYPE_NOT_ACCEPTED; /* FIXME: shouldn't we just map common errors onto - * VFW_E_TYPE_NOT_ACCEPTED and pass the value on otherwise? */ - - if (SUCCEEDED(hr)) - { - IPin_QueryDirection(pReceivePin, &pindirReceive); - - if (pindirReceive != PINDIR_OUTPUT) - { - ERR("Can't connect from non-output pin\n"); - hr = VFW_E_INVALID_DIRECTION; - } - } - - if (SUCCEEDED(hr)) - { - CopyMediaType(&This->pin.mtCurrent, pmt); - This->pin.pConnectedTo = pReceivePin; - IPin_AddRef(pReceivePin); - } - } - LeaveCriticalSection(This->pin.pCritSec); - - return hr; -} - static HRESULT deliver_endofstream(IPin* pin, LPVOID unused) { return IPin_EndOfStream( pin ); } -HRESULT WINAPI InputPin_QueryAccept(IPin * iface, const AM_MEDIA_TYPE * pmt) -{ - InputPin *This = (InputPin *)iface; - - TRACE("(%p/%p)->(%p)\n", This, iface, pmt); - - return (This->fnQueryAccept(This->pUserData, pmt) == S_OK ? S_OK : S_FALSE); -} - -HRESULT WINAPI InputPin_EndOfStream(IPin * iface) -{ - HRESULT hr = S_OK; - InputPin *This = (InputPin *)iface; - - TRACE("(%p)\n", This); - - EnterCriticalSection(This->pin.pCritSec); - if (This->flushing) - hr = S_FALSE; - else - This->end_of_stream = 1; - LeaveCriticalSection(This->pin.pCritSec); - - if (hr == S_OK) - hr = SendFurther( iface, deliver_endofstream, NULL, NULL ); - return hr; -} - static HRESULT deliver_beginflush(IPin* pin, LPVOID unused) { return IPin_BeginFlush( pin ); } -HRESULT WINAPI InputPin_BeginFlush(IPin * iface) -{ - InputPin *This = (InputPin *)iface; - HRESULT hr; - TRACE("() semi-stub\n"); - - EnterCriticalSection(This->pin.pCritSec); - This->flushing = 1; - - if (This->fnCleanProc) - This->fnCleanProc(This->pUserData); - - hr = SendFurther( iface, deliver_beginflush, NULL, NULL ); - LeaveCriticalSection(This->pin.pCritSec); - - return hr; -} - static HRESULT deliver_endflush(IPin* pin, LPVOID unused) { return IPin_EndFlush( pin ); } -HRESULT WINAPI InputPin_EndFlush(IPin * iface) -{ - InputPin *This = (InputPin *)iface; - HRESULT hr; - TRACE("(%p)\n", This); - - EnterCriticalSection(This->pin.pCritSec); - This->flushing = This->end_of_stream = 0; - - hr = SendFurther( iface, deliver_endflush, NULL, NULL ); - LeaveCriticalSection(This->pin.pCritSec); - - return hr; -} - typedef struct newsegmentargs { REFERENCE_TIME tStart, tStop; @@ -343,172 +178,6 @@ static HRESULT deliver_newsegment(IPin *pin, LPVOID data) return IPin_NewSegment(pin, args->tStart, args->tStop, args->rate); } -HRESULT WINAPI InputPin_NewSegment(IPin * iface, REFERENCE_TIME tStart, REFERENCE_TIME tStop, double dRate) -{ - InputPin *This = (InputPin *)iface; - newsegmentargs args; - - TRACE("(%x%08x, %x%08x, %e)\n", (ULONG)(tStart >> 32), (ULONG)tStart, (ULONG)(tStop >> 32), (ULONG)tStop, dRate); - - args.tStart = This->tStart = tStart; - args.tStop = This->tStop = tStop; - args.rate = This->dRate = dRate; - - return SendFurther( iface, deliver_newsegment, &args, NULL ); -} - -static const IPinVtbl InputPin_Vtbl = -{ - InputPin_QueryInterface, - BasePinImpl_AddRef, - InputPin_Release, - InputPin_Connect, - InputPin_ReceiveConnection, - BasePinImpl_Disconnect, - BasePinImpl_ConnectedTo, - BasePinImpl_ConnectionMediaType, - BasePinImpl_QueryPinInfo, - BasePinImpl_QueryDirection, - BasePinImpl_QueryId, - InputPin_QueryAccept, - BasePinImpl_EnumMediaTypes, - BasePinImpl_QueryInternalConnections, - InputPin_EndOfStream, - InputPin_BeginFlush, - InputPin_EndFlush, - InputPin_NewSegment -}; - -/*** IMemInputPin implementation ***/ - -static inline InputPin *impl_from_IMemInputPin( IMemInputPin *iface ) -{ - return (InputPin *)((char*)iface - FIELD_OFFSET(InputPin, lpVtblMemInput)); -} - -static HRESULT WINAPI MemInputPin_QueryInterface(IMemInputPin * iface, REFIID riid, LPVOID * ppv) -{ - InputPin *This = impl_from_IMemInputPin(iface); - - return IPin_QueryInterface((IPin *)&This->pin, riid, ppv); -} - -static ULONG WINAPI MemInputPin_AddRef(IMemInputPin * iface) -{ - InputPin *This = impl_from_IMemInputPin(iface); - - return IPin_AddRef((IPin *)&This->pin); -} - -static ULONG WINAPI MemInputPin_Release(IMemInputPin * iface) -{ - InputPin *This = impl_from_IMemInputPin(iface); - - return IPin_Release((IPin *)&This->pin); -} - -static HRESULT WINAPI MemInputPin_GetAllocator(IMemInputPin * iface, IMemAllocator ** ppAllocator) -{ - InputPin *This = impl_from_IMemInputPin(iface); - - TRACE("(%p/%p)->(%p)\n", This, iface, ppAllocator); - - *ppAllocator = This->pAllocator; - if (*ppAllocator) - IMemAllocator_AddRef(*ppAllocator); - - return *ppAllocator ? S_OK : VFW_E_NO_ALLOCATOR; -} - -static HRESULT WINAPI MemInputPin_NotifyAllocator(IMemInputPin * iface, IMemAllocator * pAllocator, BOOL bReadOnly) -{ - InputPin *This = impl_from_IMemInputPin(iface); - - TRACE("(%p/%p)->(%p, %d)\n", This, iface, pAllocator, bReadOnly); - - if (bReadOnly) - FIXME("Read only flag not handled yet!\n"); - - /* FIXME: Should we release the allocator on disconnection? */ - if (!pAllocator) - { - WARN("Null allocator\n"); - return E_POINTER; - } - - if (This->preferred_allocator && pAllocator != This->preferred_allocator) - return E_FAIL; - - if (This->pAllocator) - IMemAllocator_Release(This->pAllocator); - This->pAllocator = pAllocator; - if (This->pAllocator) - IMemAllocator_AddRef(This->pAllocator); - - return S_OK; -} - -static HRESULT WINAPI MemInputPin_GetAllocatorRequirements(IMemInputPin * iface, ALLOCATOR_PROPERTIES * pProps) -{ - InputPin *This = impl_from_IMemInputPin(iface); - - TRACE("(%p/%p)->(%p)\n", This, iface, pProps); - - /* override this method if you have any specific requirements */ - - return E_NOTIMPL; -} - -static HRESULT WINAPI MemInputPin_Receive(IMemInputPin * iface, IMediaSample * pSample) -{ - InputPin *This = impl_from_IMemInputPin(iface); - HRESULT hr; - - /* this trace commented out for performance reasons */ - /*TRACE("(%p/%p)->(%p)\n", This, iface, pSample);*/ - hr = This->fnSampleProc(This->pUserData, pSample); - return hr; -} - -static HRESULT WINAPI MemInputPin_ReceiveMultiple(IMemInputPin * iface, IMediaSample ** pSamples, LONG nSamples, LONG *nSamplesProcessed) -{ - HRESULT hr = S_OK; - InputPin *This = impl_from_IMemInputPin(iface); - - TRACE("(%p/%p)->(%p, %d, %p)\n", This, iface, pSamples, nSamples, nSamplesProcessed); - - for (*nSamplesProcessed = 0; *nSamplesProcessed < nSamples; (*nSamplesProcessed)++) - { - hr = IMemInputPin_Receive(iface, pSamples[*nSamplesProcessed]); - if (hr != S_OK) - break; - } - - return hr; -} - -static HRESULT WINAPI MemInputPin_ReceiveCanBlock(IMemInputPin * iface) -{ - InputPin *This = impl_from_IMemInputPin(iface); - - TRACE("(%p/%p)->()\n", This, iface); - - return S_OK; -} - -static const IMemInputPinVtbl MemInputPin_Vtbl = -{ - MemInputPin_QueryInterface, - MemInputPin_AddRef, - MemInputPin_Release, - MemInputPin_GetAllocator, - MemInputPin_NotifyAllocator, - MemInputPin_GetAllocatorRequirements, - MemInputPin_Receive, - MemInputPin_ReceiveMultiple, - MemInputPin_ReceiveCanBlock -}; - /*** PullPin implementation ***/ static HRESULT PullPin_Init(const IPinVtbl *PullPin_Vtbl, const PIN_INFO * pPinInfo, SAMPLEPROC_PULL pSampleProc, LPVOID pUserData, @@ -1119,7 +788,7 @@ static const IPinVtbl PullPin_Vtbl = PullPin_QueryInterface, BasePinImpl_AddRef, PullPin_Release, - InputPin_Connect, + BaseInputPinImpl_Connect, PullPin_ReceiveConnection, PullPin_Disconnect, BasePinImpl_ConnectedTo, @@ -1135,62 +804,3 @@ static const IPinVtbl PullPin_Vtbl = PullPin_EndFlush, PullPin_NewSegment }; - -/*** The Construct functions ***/ - -static HRESULT InputPin_Init(const IPinVtbl *InputPin_Vtbl, const PIN_INFO * pPinInfo, SAMPLEPROC_PUSH pSampleProc, LPVOID pUserData, - QUERYACCEPTPROC pQueryAccept, CLEANUPPROC pCleanUp, LPCRITICAL_SECTION pCritSec, IMemAllocator *allocator, InputPin * pPinImpl) -{ - TRACE("\n"); - - /* Common attributes */ - pPinImpl->pin.refCount = 1; - pPinImpl->pin.pConnectedTo = NULL; - pPinImpl->pin.pCritSec = pCritSec; - Copy_PinInfo(&pPinImpl->pin.pinInfo, pPinInfo); - ZeroMemory(&pPinImpl->pin.mtCurrent, sizeof(AM_MEDIA_TYPE)); - - /* Input pin attributes */ - pPinImpl->pUserData = pUserData; - pPinImpl->fnQueryAccept = pQueryAccept; - pPinImpl->fnSampleProc = pSampleProc; - pPinImpl->fnCleanProc = pCleanUp; - pPinImpl->pAllocator = pPinImpl->preferred_allocator = allocator; - if (pPinImpl->preferred_allocator) - IMemAllocator_AddRef(pPinImpl->preferred_allocator); - pPinImpl->tStart = 0; - pPinImpl->tStop = 0; - pPinImpl->dRate = 1.0; - pPinImpl->pin.lpVtbl = InputPin_Vtbl; - pPinImpl->lpVtblMemInput = &MemInputPin_Vtbl; - pPinImpl->flushing = pPinImpl->end_of_stream = 0; - - return S_OK; -} - -HRESULT InputPin_Construct(const IPinVtbl *InputPin_Vtbl, const PIN_INFO * pPinInfo, SAMPLEPROC_PUSH pSampleProc, LPVOID pUserData, QUERYACCEPTPROC pQueryAccept, CLEANUPPROC pCleanUp, LPCRITICAL_SECTION pCritSec, IMemAllocator *allocator, IPin ** ppPin) -{ - InputPin * pPinImpl; - - *ppPin = NULL; - - if (pPinInfo->dir != PINDIR_INPUT) - { - ERR("Pin direction(%x) != PINDIR_INPUT\n", pPinInfo->dir); - return E_INVALIDARG; - } - - pPinImpl = CoTaskMemAlloc(sizeof(*pPinImpl)); - - if (!pPinImpl) - return E_OUTOFMEMORY; - - if (SUCCEEDED(InputPin_Init(InputPin_Vtbl, pPinInfo, pSampleProc, pUserData, pQueryAccept, pCleanUp, pCritSec, allocator, pPinImpl))) - { - *ppPin = (IPin *)pPinImpl; - return S_OK; - } - - CoTaskMemFree(pPinImpl); - return E_FAIL; -} diff --git a/dlls/quartz/pin.h b/dlls/quartz/pin.h index db7cd1a9183..732606138c2 100644 --- a/dlls/quartz/pin.h +++ b/dlls/quartz/pin.h @@ -24,7 +24,6 @@ * Cookie is the cookie that was set when requesting the buffer, if you don't * implement custom requesting, you can safely ignore this */ -typedef HRESULT (* SAMPLEPROC_PUSH)(LPVOID userdata, IMediaSample * pSample); typedef HRESULT (* SAMPLEPROC_PULL)(LPVOID userdata, IMediaSample * pSample, DWORD_PTR cookie); /* This function will determine whether a type is supported or not. @@ -66,24 +65,6 @@ typedef HRESULT (* STOPPROCESSPROC) (LPVOID userdata); #define ALIGNDOWN(value,boundary) ((value)/(boundary)*(boundary)) #define ALIGNUP(value,boundary) (ALIGNDOWN((value)+(boundary)-1, (boundary))) -typedef struct InputPin -{ - /* inheritance C style! */ - BasePin pin; - LPVOID pUserData; - - const IMemInputPinVtbl * lpVtblMemInput; - IMemAllocator * pAllocator; - QUERYACCEPTPROC fnQueryAccept; - SAMPLEPROC_PUSH fnSampleProc; - CLEANUPPROC fnCleanProc; - REFERENCE_TIME tStart; - REFERENCE_TIME tStop; - double dRate; - BOOL flushing, end_of_stream; - IMemAllocator *preferred_allocator; -} InputPin; - typedef struct PullPin { /* inheritance C style! */ @@ -120,23 +101,11 @@ typedef struct PullPin #define Req_Pause 3 /*** Constructors ***/ -HRESULT InputPin_Construct(const IPinVtbl *InputPin_Vtbl, const PIN_INFO * pPinInfo, SAMPLEPROC_PUSH pSampleProc, LPVOID pUserData, QUERYACCEPTPROC pQueryAccept, CLEANUPPROC pCleanUp, LPCRITICAL_SECTION pCritSec, IMemAllocator *, IPin ** ppPin); HRESULT PullPin_Construct(const IPinVtbl *PullPin_Vtbl, const PIN_INFO * pPinInfo, SAMPLEPROC_PULL pSampleProc, LPVOID pUserData, QUERYACCEPTPROC pQueryAccept, CLEANUPPROC pCleanUp, STOPPROCESSPROC, REQUESTPROC pCustomRequest, LPCRITICAL_SECTION pCritSec, IPin ** ppPin); /**************************/ /*** Pin Implementation ***/ -/* Input Pin */ -HRESULT WINAPI InputPin_QueryInterface(IPin * iface, REFIID riid, LPVOID * ppv); -ULONG WINAPI InputPin_Release(IPin * iface); -HRESULT WINAPI InputPin_Connect(IPin * iface, IPin * pConnector, const AM_MEDIA_TYPE * pmt); -HRESULT WINAPI InputPin_ReceiveConnection(IPin * iface, IPin * pReceivePin, const AM_MEDIA_TYPE * pmt); -HRESULT WINAPI InputPin_QueryAccept(IPin * iface, const AM_MEDIA_TYPE * pmt); -HRESULT WINAPI InputPin_EndOfStream(IPin * iface); -HRESULT WINAPI InputPin_BeginFlush(IPin * iface); -HRESULT WINAPI InputPin_EndFlush(IPin * iface); -HRESULT WINAPI InputPin_NewSegment(IPin * iface, REFERENCE_TIME tStart, REFERENCE_TIME tStop, double dRate); - /* Pull Pin */ HRESULT WINAPI PullPin_ReceiveConnection(IPin * iface, IPin * pReceivePin, const AM_MEDIA_TYPE * pmt); HRESULT WINAPI PullPin_Disconnect(IPin * iface); diff --git a/dlls/quartz/transform.c b/dlls/quartz/transform.c index 29b8c786c25..e904f50bc6d 100644 --- a/dlls/quartz/transform.c +++ b/dlls/quartz/transform.c @@ -47,7 +47,7 @@ static const IBaseFilterVtbl TransformFilter_Vtbl; static const IPinVtbl TransformFilter_InputPin_Vtbl; static const IPinVtbl TransformFilter_OutputPin_Vtbl; -static HRESULT TransformFilter_Input_QueryAccept(LPVOID iface, const AM_MEDIA_TYPE * pmt) +static HRESULT WINAPI TransformFilter_Input_CheckMediaType(IPin *iface, const AM_MEDIA_TYPE * pmt) { TransformFilterImpl* This = (TransformFilterImpl *)((BasePin *)iface)->pinInfo.pFilter; TRACE("%p\n", iface); @@ -105,7 +105,7 @@ HRESULT TransformFilter_Create(TransformFilterImpl* pTransformFilter, const CLSI piOutput.pFilter = (IBaseFilter *)pTransformFilter; lstrcpynW(piOutput.achName, wcsOutputPinName, sizeof(piOutput.achName) / sizeof(piOutput.achName[0])); - hr = InputPin_Construct(&TransformFilter_InputPin_Vtbl, &piInput, (SAMPLEPROC_PUSH)pFuncsTable->pfnProcessSampleData, NULL, TransformFilter_Input_QueryAccept, NULL, &pTransformFilter->csFilter, NULL, &pTransformFilter->ppPins[0]); + hr = BaseInputPin_Construct(&TransformFilter_InputPin_Vtbl, &piInput, TransformFilter_Input_CheckMediaType, pFuncsTable->pfnProcessSampleData, &pTransformFilter->csFilter, NULL, &pTransformFilter->ppPins[0]); if (SUCCEEDED(hr)) { @@ -115,8 +115,6 @@ HRESULT TransformFilter_Create(TransformFilterImpl* pTransformFilter, const CLSI props.cbBuffer = 0; /* Will be updated at connection time */ props.cBuffers = 1; - ((InputPin *)pTransformFilter->ppPins[0])->pUserData = pTransformFilter->ppPins[0]; - hr = BaseOutputPin_Construct(&TransformFilter_OutputPin_Vtbl, sizeof(BaseOutputPin), &piOutput, &props, NULL, &pTransformFilter->csFilter, &pTransformFilter->ppPins[1]); if (FAILED(hr)) @@ -291,7 +289,7 @@ static HRESULT WINAPI TransformFilter_Run(IBaseFilter * iface, REFERENCE_TIME tS { if (This->state == State_Stopped) { - ((InputPin *)This->ppPins[0])->end_of_stream = 0; + ((BaseInputPin *)This->ppPins[0])->end_of_stream = 0; if (This->pFuncsTable->pfnProcessBegin) hr = This->pFuncsTable->pfnProcessBegin(This); if (SUCCEEDED(hr)) @@ -467,7 +465,7 @@ static const IBaseFilterVtbl TransformFilter_Vtbl = static HRESULT WINAPI TransformFilter_InputPin_EndOfStream(IPin * iface) { - InputPin* This = (InputPin*) iface; + BaseInputPin* This = (BaseInputPin*) iface; TransformFilterImpl* pTransform; IPin* ppin; HRESULT hr; @@ -493,7 +491,7 @@ static HRESULT WINAPI TransformFilter_InputPin_EndOfStream(IPin * iface) static HRESULT WINAPI TransformFilter_InputPin_ReceiveConnection(IPin * iface, IPin * pReceivePin, const AM_MEDIA_TYPE * pmt) { - InputPin* This = (InputPin*) iface; + BaseInputPin* This = (BaseInputPin*) iface; TransformFilterImpl* pTransform; HRESULT hr; @@ -504,7 +502,7 @@ static HRESULT WINAPI TransformFilter_InputPin_ReceiveConnection(IPin * iface, I hr = pTransform->pFuncsTable->pfnConnectInput(This, pmt); if (SUCCEEDED(hr)) { - hr = InputPin_ReceiveConnection(iface, pReceivePin, pmt); + hr = BaseInputPinImpl_ReceiveConnection(iface, pReceivePin, pmt); if (FAILED(hr)) pTransform->pFuncsTable->pfnCleanup(This); } @@ -514,7 +512,7 @@ static HRESULT WINAPI TransformFilter_InputPin_ReceiveConnection(IPin * iface, I static HRESULT WINAPI TransformFilter_InputPin_Disconnect(IPin * iface) { - InputPin* This = (InputPin*) iface; + BaseInputPin* This = (BaseInputPin*) iface; TransformFilterImpl* pTransform; TRACE("(%p)->()\n", iface); @@ -527,7 +525,7 @@ static HRESULT WINAPI TransformFilter_InputPin_Disconnect(IPin * iface) static HRESULT WINAPI TransformFilter_InputPin_BeginFlush(IPin * iface) { - InputPin* This = (InputPin*) iface; + BaseInputPin* This = (BaseInputPin*) iface; TransformFilterImpl* pTransform; HRESULT hr = S_OK; @@ -538,14 +536,14 @@ static HRESULT WINAPI TransformFilter_InputPin_BeginFlush(IPin * iface) if (pTransform->pFuncsTable->pfnBeginFlush) hr = pTransform->pFuncsTable->pfnBeginFlush(This); if (SUCCEEDED(hr)) - hr = InputPin_BeginFlush(iface); + hr = BaseInputPinImpl_BeginFlush(iface); LeaveCriticalSection(&pTransform->csFilter); return hr; } static HRESULT WINAPI TransformFilter_InputPin_EndFlush(IPin * iface) { - InputPin* This = (InputPin*) iface; + BaseInputPin* This = (BaseInputPin*) iface; TransformFilterImpl* pTransform; HRESULT hr = S_OK; @@ -556,14 +554,14 @@ static HRESULT WINAPI TransformFilter_InputPin_EndFlush(IPin * iface) if (pTransform->pFuncsTable->pfnEndFlush) hr = pTransform->pFuncsTable->pfnEndFlush(This); if (SUCCEEDED(hr)) - hr = InputPin_EndFlush(iface); + hr = BaseInputPinImpl_EndFlush(iface); LeaveCriticalSection(&pTransform->csFilter); return hr; } static HRESULT WINAPI TransformFilter_InputPin_NewSegment(IPin * iface, REFERENCE_TIME tStart, REFERENCE_TIME tStop, double dRate) { - InputPin* This = (InputPin*) iface; + BaseInputPin* This = (BaseInputPin*) iface; TransformFilterImpl* pTransform; HRESULT hr = S_OK; @@ -574,17 +572,17 @@ static HRESULT WINAPI TransformFilter_InputPin_NewSegment(IPin * iface, REFERENC if (pTransform->pFuncsTable->pfnNewSegment) hr = pTransform->pFuncsTable->pfnNewSegment(This, tStart, tStop, dRate); if (SUCCEEDED(hr)) - hr = InputPin_NewSegment(iface, tStart, tStop, dRate); + hr = BaseInputPinImpl_NewSegment(iface, tStart, tStop, dRate); LeaveCriticalSection(&pTransform->csFilter); return hr; } static const IPinVtbl TransformFilter_InputPin_Vtbl = { - InputPin_QueryInterface, + BaseInputPinImpl_QueryInterface, BasePinImpl_AddRef, - InputPin_Release, - InputPin_Connect, + BaseInputPinImpl_Release, + BaseInputPinImpl_Connect, TransformFilter_InputPin_ReceiveConnection, TransformFilter_InputPin_Disconnect, BasePinImpl_ConnectedTo, @@ -592,7 +590,7 @@ static const IPinVtbl TransformFilter_InputPin_Vtbl = BasePinImpl_QueryPinInfo, BasePinImpl_QueryDirection, BasePinImpl_QueryId, - InputPin_QueryAccept, + BaseInputPinImpl_QueryAccept, BasePinImpl_EnumMediaTypes, BasePinImpl_QueryInternalConnections, TransformFilter_InputPin_EndOfStream, diff --git a/dlls/quartz/transform.h b/dlls/quartz/transform.h index e2486cd84af..8a18c58dc35 100644 --- a/dlls/quartz/transform.h +++ b/dlls/quartz/transform.h @@ -24,15 +24,15 @@ typedef struct TransformFilterImpl TransformFilterImpl; typedef struct TransformFuncsTable { HRESULT (*pfnProcessBegin) (TransformFilterImpl *This); - HRESULT (*pfnProcessSampleData) (InputPin *pin, IMediaSample *pSample); + BaseInputPin_Receive pfnProcessSampleData; HRESULT (*pfnProcessEnd) (TransformFilterImpl *This); HRESULT (*pfnQueryConnect) (TransformFilterImpl *This, const AM_MEDIA_TYPE * pmt); - HRESULT (*pfnConnectInput) (InputPin *pin, const AM_MEDIA_TYPE * pmt); - HRESULT (*pfnCleanup) (InputPin *pin); - HRESULT (*pfnEndOfStream) (InputPin *pin); - HRESULT (*pfnBeginFlush) (InputPin *pin); - HRESULT (*pfnEndFlush) (InputPin *pin); - HRESULT (*pfnNewSegment) (InputPin *pin, REFERENCE_TIME tStart, REFERENCE_TIME tStop, double dRate); + HRESULT (*pfnConnectInput) (BaseInputPin *pin, const AM_MEDIA_TYPE * pmt); + HRESULT (*pfnCleanup) (BaseInputPin *pin); + HRESULT (*pfnEndOfStream) (BaseInputPin *pin); + HRESULT (*pfnBeginFlush) (BaseInputPin *pin); + HRESULT (*pfnEndFlush) (BaseInputPin *pin); + HRESULT (*pfnNewSegment) (BaseInputPin *pin, REFERENCE_TIME tStart, REFERENCE_TIME tStop, double dRate); } TransformFuncsTable; struct TransformFilterImpl diff --git a/dlls/quartz/videorenderer.c b/dlls/quartz/videorenderer.c index 0cfef54d8df..756e376e8ac 100644 --- a/dlls/quartz/videorenderer.c +++ b/dlls/quartz/videorenderer.c @@ -68,7 +68,7 @@ typedef struct VideoRendererImpl IReferenceClock * pClock; FILTER_INFO filterInfo; - InputPin *pInputPin; + BaseInputPin *pInputPin; BOOL init; HANDLE hThread; @@ -354,9 +354,10 @@ static DWORD VideoRenderer_SendSampleData(VideoRendererImpl* This, LPBYTE data, return S_OK; } -static HRESULT VideoRenderer_Sample(LPVOID iface, IMediaSample * pSample) +static HRESULT WINAPI VideoRenderer_Receive(IPin* iface, IMediaSample * pSample) { - VideoRendererImpl *This = iface; + BaseInputPin* pin = (BaseInputPin*)iface; + VideoRendererImpl *This = (VideoRendererImpl *)pin->pin.pinInfo.pFilter; LPBYTE pbSrcStream = NULL; LONG cbSrcStream = 0; REFERENCE_TIME tStart, tStop; @@ -491,8 +492,11 @@ static HRESULT VideoRenderer_Sample(LPVOID iface, IMediaSample * pSample) return S_OK; } -static HRESULT VideoRenderer_QueryAccept(LPVOID iface, const AM_MEDIA_TYPE * pmt) +static HRESULT WINAPI VideoRenderer_CheckMediaType(IPin *iface, const AM_MEDIA_TYPE * pmt) { + BaseInputPin* pin = (BaseInputPin*)iface; + VideoRendererImpl *This = (VideoRendererImpl *)pin->pin.pinInfo.pFilter; + if (!IsEqualIID(&pmt->majortype, &MEDIATYPE_Video)) return S_FALSE; @@ -501,7 +505,6 @@ static HRESULT VideoRenderer_QueryAccept(LPVOID iface, const AM_MEDIA_TYPE * pmt IsEqualIID(&pmt->subtype, &MEDIASUBTYPE_RGB565) || IsEqualIID(&pmt->subtype, &MEDIASUBTYPE_RGB8)) { - VideoRendererImpl* This = iface; LONG height; if (IsEqualIID(&pmt->formattype, &FORMAT_VideoInfo)) @@ -580,7 +583,7 @@ HRESULT VideoRenderer_create(IUnknown * pUnkOuter, LPVOID * ppv) piInput.pFilter = (IBaseFilter *)pVideoRenderer; lstrcpynW(piInput.achName, wcsInputPinName, sizeof(piInput.achName) / sizeof(piInput.achName[0])); - hr = InputPin_Construct(&VideoRenderer_InputPin_Vtbl, &piInput, VideoRenderer_Sample, (LPVOID)pVideoRenderer, VideoRenderer_QueryAccept, NULL, &pVideoRenderer->csFilter, NULL, (IPin **)&pVideoRenderer->pInputPin); + hr = BaseInputPin_Construct(&VideoRenderer_InputPin_Vtbl, &piInput, VideoRenderer_CheckMediaType, VideoRenderer_Receive, &pVideoRenderer->csFilter, NULL, (IPin **)&pVideoRenderer->pInputPin); if (SUCCEEDED(hr)) { @@ -1010,7 +1013,7 @@ static const IBaseFilterVtbl VideoRenderer_Vtbl = static HRESULT WINAPI VideoRenderer_InputPin_EndOfStream(IPin * iface) { - InputPin* This = (InputPin*)iface; + BaseInputPin* This = (BaseInputPin*)iface; VideoRendererImpl *pFilter; IMediaEventSink* pEventSink; HRESULT hr; @@ -1031,7 +1034,7 @@ static HRESULT WINAPI VideoRenderer_InputPin_EndOfStream(IPin * iface) static HRESULT WINAPI VideoRenderer_InputPin_BeginFlush(IPin * iface) { - InputPin* This = (InputPin*)iface; + BaseInputPin* This = (BaseInputPin*)iface; VideoRendererImpl *pVideoRenderer = (VideoRendererImpl *)This->pin.pinInfo.pFilter; HRESULT hr; @@ -1041,7 +1044,7 @@ static HRESULT WINAPI VideoRenderer_InputPin_BeginFlush(IPin * iface) if (pVideoRenderer->state == State_Paused) SetEvent(pVideoRenderer->blocked); - hr = InputPin_BeginFlush(iface); + hr = BaseInputPinImpl_BeginFlush(iface); LeaveCriticalSection(This->pin.pCritSec); return hr; @@ -1049,7 +1052,7 @@ static HRESULT WINAPI VideoRenderer_InputPin_BeginFlush(IPin * iface) static HRESULT WINAPI VideoRenderer_InputPin_EndFlush(IPin * iface) { - InputPin* This = (InputPin*)iface; + BaseInputPin* This = (BaseInputPin*)iface; VideoRendererImpl *pVideoRenderer = (VideoRendererImpl *)This->pin.pinInfo.pFilter; HRESULT hr; @@ -1059,7 +1062,7 @@ static HRESULT WINAPI VideoRenderer_InputPin_EndFlush(IPin * iface) if (pVideoRenderer->state == State_Paused) ResetEvent(pVideoRenderer->blocked); - hr = InputPin_EndFlush(iface); + hr = BaseInputPinImpl_EndFlush(iface); LeaveCriticalSection(This->pin.pCritSec); MediaSeekingPassThru_ResetMediaTime(pVideoRenderer->seekthru_unk); @@ -1068,24 +1071,24 @@ static HRESULT WINAPI VideoRenderer_InputPin_EndFlush(IPin * iface) static const IPinVtbl VideoRenderer_InputPin_Vtbl = { - InputPin_QueryInterface, + BaseInputPinImpl_QueryInterface, BasePinImpl_AddRef, - InputPin_Release, - InputPin_Connect, - InputPin_ReceiveConnection, + BaseInputPinImpl_Release, + BaseInputPinImpl_Connect, + BaseInputPinImpl_ReceiveConnection, BasePinImpl_Disconnect, BasePinImpl_ConnectedTo, BasePinImpl_ConnectionMediaType, BasePinImpl_QueryPinInfo, BasePinImpl_QueryDirection, BasePinImpl_QueryId, - InputPin_QueryAccept, + BaseInputPinImpl_QueryAccept, BasePinImpl_EnumMediaTypes, BasePinImpl_QueryInternalConnections, VideoRenderer_InputPin_EndOfStream, VideoRenderer_InputPin_BeginFlush, VideoRenderer_InputPin_EndFlush, - InputPin_NewSegment + BaseInputPinImpl_NewSegment }; /*** IUnknown methods ***/ diff --git a/dlls/strmbase/pin.c b/dlls/strmbase/pin.c index 1e52314d335..3c3d7531716 100644 --- a/dlls/strmbase/pin.c +++ b/dlls/strmbase/pin.c @@ -31,7 +31,114 @@ WINE_DEFAULT_DEBUG_CHANNEL(strmbase); +static const IPinVtbl InputPin_Vtbl; static const IPinVtbl OutputPin_Vtbl; +static const IMemInputPinVtbl MemInputPin_Vtbl; + +typedef HRESULT (*SendPinFunc)( IPin *to, LPVOID arg ); + +/** Helper function, there are a lot of places where the error code is inherited + * The following rules apply: + * + * Return the first received error code (E_NOTIMPL is ignored) + * If no errors occur: return the first received non-error-code that isn't S_OK + */ +static HRESULT updatehres( HRESULT original, HRESULT new ) +{ + if (FAILED( original ) || new == E_NOTIMPL) + return original; + + if (FAILED( new ) || original == S_OK) + return new; + + return original; +} + +/** Sends a message from a pin further to other, similar pins + * fnMiddle is called on each pin found further on the stream. + * fnEnd (can be NULL) is called when the message can't be sent any further (this is a renderer or source) + * + * If the pin given is an input pin, the message will be sent downstream to other input pins + * If the pin given is an output pin, the message will be sent upstream to other output pins + */ +static HRESULT SendFurther( IPin *from, SendPinFunc fnMiddle, LPVOID arg, SendPinFunc fnEnd ) +{ + PIN_INFO pin_info; + ULONG amount = 0; + HRESULT hr = S_OK; + HRESULT hr_return = S_OK; + IEnumPins *enumpins = NULL; + BOOL foundend = TRUE; + PIN_DIRECTION from_dir; + + IPin_QueryDirection( from, &from_dir ); + + hr = IPin_QueryInternalConnections( from, NULL, &amount ); + if (hr != E_NOTIMPL && amount) + FIXME("Use QueryInternalConnections!\n"); + hr = S_OK; + + pin_info.pFilter = NULL; + hr = IPin_QueryPinInfo( from, &pin_info ); + if (FAILED(hr)) + goto out; + + hr = IBaseFilter_EnumPins( pin_info.pFilter, &enumpins ); + if (FAILED(hr)) + goto out; + + hr = IEnumPins_Reset( enumpins ); + while (hr == S_OK) { + IPin *pin = NULL; + hr = IEnumPins_Next( enumpins, 1, &pin, NULL ); + if (hr == VFW_E_ENUM_OUT_OF_SYNC) + { + hr = IEnumPins_Reset( enumpins ); + continue; + } + if (pin) + { + PIN_DIRECTION dir; + + IPin_QueryDirection( pin, &dir ); + if (dir != from_dir) + { + IPin *connected = NULL; + + foundend = FALSE; + IPin_ConnectedTo( pin, &connected ); + if (connected) + { + HRESULT hr_local; + + hr_local = fnMiddle( connected, arg ); + hr_return = updatehres( hr_return, hr_local ); + IPin_Release(connected); + } + } + IPin_Release( pin ); + } + else + { + hr = S_OK; + break; + } + } + + if (!foundend) + hr = hr_return; + else if (fnEnd) { + HRESULT hr_local; + + hr_local = fnEnd( from, arg ); + hr_return = updatehres( hr_return, hr_local ); + } + +out: + if (pin_info.pFilter) + IBaseFilter_Release( pin_info.pFilter ); + return hr; +} static void Copy_PinInfo(PIN_INFO * pDest, const PIN_INFO * pSrc) { @@ -758,3 +865,414 @@ HRESULT WINAPI BaseOutputPin_Construct(const IPinVtbl *OutputPin_Vtbl, LONG outp CoTaskMemFree(pPinImpl); return E_FAIL; } + +/*** Input Pin implementation ***/ + +HRESULT WINAPI BaseInputPinImpl_QueryInterface(IPin * iface, REFIID riid, LPVOID * ppv) +{ + BaseInputPin *This = (BaseInputPin *)iface; + + TRACE("(%p)->(%s, %p)\n", iface, debugstr_guid(riid), ppv); + + *ppv = NULL; + + if (IsEqualIID(riid, &IID_IUnknown)) + *ppv = iface; + else if (IsEqualIID(riid, &IID_IPin)) + *ppv = iface; + else if (IsEqualIID(riid, &IID_IMemInputPin)) + *ppv = &This->lpVtblMemInput; + else if (IsEqualIID(riid, &IID_IMediaSeeking)) + { + return IBaseFilter_QueryInterface(This->pin.pinInfo.pFilter, &IID_IMediaSeeking, ppv); + } + + if (*ppv) + { + IUnknown_AddRef((IUnknown *)(*ppv)); + return S_OK; + } + + FIXME("No interface for %s!\n", debugstr_guid(riid)); + + return E_NOINTERFACE; +} + +ULONG WINAPI BaseInputPinImpl_Release(IPin * iface) +{ + BaseInputPin *This = (BaseInputPin *)iface; + ULONG refCount = InterlockedDecrement(&This->pin.refCount); + + TRACE("(%p)->() Release from %d\n", iface, refCount + 1); + + if (!refCount) + { + FreeMediaType(&This->pin.mtCurrent); + if (This->pAllocator) + IMemAllocator_Release(This->pAllocator); + This->pAllocator = NULL; + This->pin.lpVtbl = NULL; + CoTaskMemFree(This); + return 0; + } + else + return refCount; +} + +HRESULT WINAPI BaseInputPinImpl_Connect(IPin * iface, IPin * pConnector, const AM_MEDIA_TYPE * pmt) +{ + ERR("Outgoing connection on an input pin! (%p, %p)\n", pConnector, pmt); + + return E_UNEXPECTED; +} + + +HRESULT WINAPI BaseInputPinImpl_ReceiveConnection(IPin * iface, IPin * pReceivePin, const AM_MEDIA_TYPE * pmt) +{ + BaseInputPin *This = (BaseInputPin *)iface; + PIN_DIRECTION pindirReceive; + HRESULT hr = S_OK; + + TRACE("(%p, %p)\n", pReceivePin, pmt); + dump_AM_MEDIA_TYPE(pmt); + + EnterCriticalSection(This->pin.pCritSec); + { + if (This->pin.pConnectedTo) + hr = VFW_E_ALREADY_CONNECTED; + + if (SUCCEEDED(hr) && This->fnCheckMediaType((IPin*)This, pmt) != S_OK) + hr = VFW_E_TYPE_NOT_ACCEPTED; /* FIXME: shouldn't we just map common errors onto + * VFW_E_TYPE_NOT_ACCEPTED and pass the value on otherwise? */ + + if (SUCCEEDED(hr)) + { + IPin_QueryDirection(pReceivePin, &pindirReceive); + + if (pindirReceive != PINDIR_OUTPUT) + { + ERR("Can't connect from non-output pin\n"); + hr = VFW_E_INVALID_DIRECTION; + } + } + + if (SUCCEEDED(hr)) + { + CopyMediaType(&This->pin.mtCurrent, pmt); + This->pin.pConnectedTo = pReceivePin; + IPin_AddRef(pReceivePin); + } + } + LeaveCriticalSection(This->pin.pCritSec); + + return hr; +} + +static HRESULT deliver_endofstream(IPin* pin, LPVOID unused) +{ + return IPin_EndOfStream( pin ); +} + +HRESULT WINAPI BaseInputPinImpl_QueryAccept(IPin * iface, const AM_MEDIA_TYPE * pmt) +{ + BaseInputPin *This = (BaseInputPin *)iface; + + TRACE("(%p/%p)->(%p)\n", This, iface, pmt); + + return (This->fnCheckMediaType((IPin*)This, pmt) == S_OK ? S_OK : S_FALSE); +} + +HRESULT WINAPI BaseInputPinImpl_EndOfStream(IPin * iface) +{ + HRESULT hr = S_OK; + BaseInputPin *This = (BaseInputPin *)iface; + + TRACE("(%p)\n", This); + + EnterCriticalSection(This->pin.pCritSec); + if (This->flushing) + hr = S_FALSE; + else + This->end_of_stream = 1; + LeaveCriticalSection(This->pin.pCritSec); + + if (hr == S_OK) + hr = SendFurther( iface, deliver_endofstream, NULL, NULL ); + return hr; +} + +static HRESULT deliver_beginflush(IPin* pin, LPVOID unused) +{ + return IPin_BeginFlush( pin ); +} + +HRESULT WINAPI BaseInputPinImpl_BeginFlush(IPin * iface) +{ + BaseInputPin *This = (BaseInputPin *)iface; + HRESULT hr; + TRACE("() semi-stub\n"); + + EnterCriticalSection(This->pin.pCritSec); + This->flushing = 1; + + hr = SendFurther( iface, deliver_beginflush, NULL, NULL ); + LeaveCriticalSection(This->pin.pCritSec); + + return hr; +} + +static HRESULT deliver_endflush(IPin* pin, LPVOID unused) +{ + return IPin_EndFlush( pin ); +} + +HRESULT WINAPI BaseInputPinImpl_EndFlush(IPin * iface) +{ + BaseInputPin *This = (BaseInputPin *)iface; + HRESULT hr; + TRACE("(%p)\n", This); + + EnterCriticalSection(This->pin.pCritSec); + This->flushing = This->end_of_stream = 0; + + hr = SendFurther( iface, deliver_endflush, NULL, NULL ); + LeaveCriticalSection(This->pin.pCritSec); + + return hr; +} + +typedef struct newsegmentargs +{ + REFERENCE_TIME tStart, tStop; + double rate; +} newsegmentargs; + +static HRESULT deliver_newsegment(IPin *pin, LPVOID data) +{ + newsegmentargs *args = data; + return IPin_NewSegment(pin, args->tStart, args->tStop, args->rate); +} + +HRESULT WINAPI BaseInputPinImpl_NewSegment(IPin * iface, REFERENCE_TIME tStart, REFERENCE_TIME tStop, double dRate) +{ + BaseInputPin *This = (BaseInputPin *)iface; + newsegmentargs args; + + TRACE("(%x%08x, %x%08x, %e)\n", (ULONG)(tStart >> 32), (ULONG)tStart, (ULONG)(tStop >> 32), (ULONG)tStop, dRate); + + args.tStart = This->tStart = tStart; + args.tStop = This->tStop = tStop; + args.rate = This->dRate = dRate; + + return SendFurther( iface, deliver_newsegment, &args, NULL ); +} + +static const IPinVtbl InputPin_Vtbl = +{ + BaseInputPinImpl_QueryInterface, + BasePinImpl_AddRef, + BaseInputPinImpl_Release, + BaseInputPinImpl_Connect, + BaseInputPinImpl_ReceiveConnection, + BasePinImpl_Disconnect, + BasePinImpl_ConnectedTo, + BasePinImpl_ConnectionMediaType, + BasePinImpl_QueryPinInfo, + BasePinImpl_QueryDirection, + BasePinImpl_QueryId, + BaseInputPinImpl_QueryAccept, + BasePinImpl_EnumMediaTypes, + BasePinImpl_QueryInternalConnections, + BaseInputPinImpl_EndOfStream, + BaseInputPinImpl_BeginFlush, + BaseInputPinImpl_EndFlush, + BaseInputPinImpl_NewSegment +}; + +/*** IMemInputPin implementation ***/ + +static inline BaseInputPin *impl_from_IMemInputPin( IMemInputPin *iface ) +{ + return (BaseInputPin *)((char*)iface - FIELD_OFFSET(BaseInputPin, lpVtblMemInput)); +} + +static HRESULT WINAPI MemInputPin_QueryInterface(IMemInputPin * iface, REFIID riid, LPVOID * ppv) +{ + BaseInputPin *This = impl_from_IMemInputPin(iface); + + return IPin_QueryInterface((IPin *)&This->pin, riid, ppv); +} + +static ULONG WINAPI MemInputPin_AddRef(IMemInputPin * iface) +{ + BaseInputPin *This = impl_from_IMemInputPin(iface); + + return IPin_AddRef((IPin *)&This->pin); +} + +static ULONG WINAPI MemInputPin_Release(IMemInputPin * iface) +{ + BaseInputPin *This = impl_from_IMemInputPin(iface); + + return IPin_Release((IPin *)&This->pin); +} + +static HRESULT WINAPI MemInputPin_GetAllocator(IMemInputPin * iface, IMemAllocator ** ppAllocator) +{ + BaseInputPin *This = impl_from_IMemInputPin(iface); + + TRACE("(%p/%p)->(%p)\n", This, iface, ppAllocator); + + *ppAllocator = This->pAllocator; + if (*ppAllocator) + IMemAllocator_AddRef(*ppAllocator); + + return *ppAllocator ? S_OK : VFW_E_NO_ALLOCATOR; +} + +static HRESULT WINAPI MemInputPin_NotifyAllocator(IMemInputPin * iface, IMemAllocator * pAllocator, BOOL bReadOnly) +{ + BaseInputPin *This = impl_from_IMemInputPin(iface); + + TRACE("(%p/%p)->(%p, %d)\n", This, iface, pAllocator, bReadOnly); + + if (bReadOnly) + FIXME("Read only flag not handled yet!\n"); + + /* FIXME: Should we release the allocator on disconnection? */ + if (!pAllocator) + { + WARN("Null allocator\n"); + return E_POINTER; + } + + if (This->preferred_allocator && pAllocator != This->preferred_allocator) + return E_FAIL; + + if (This->pAllocator) + IMemAllocator_Release(This->pAllocator); + This->pAllocator = pAllocator; + if (This->pAllocator) + IMemAllocator_AddRef(This->pAllocator); + + return S_OK; +} + +static HRESULT WINAPI MemInputPin_GetAllocatorRequirements(IMemInputPin * iface, ALLOCATOR_PROPERTIES * pProps) +{ + BaseInputPin *This = impl_from_IMemInputPin(iface); + + TRACE("(%p/%p)->(%p)\n", This, iface, pProps); + + /* override this method if you have any specific requirements */ + + return E_NOTIMPL; +} + +static HRESULT WINAPI MemInputPin_Receive(IMemInputPin * iface, IMediaSample * pSample) +{ + BaseInputPin *This = impl_from_IMemInputPin(iface); + HRESULT hr; + + /* this trace commented out for performance reasons */ + /*TRACE("(%p/%p)->(%p)\n", This, iface, pSample);*/ + hr = This->fnReceive((IPin*)This, pSample); + return hr; +} + +static HRESULT WINAPI MemInputPin_ReceiveMultiple(IMemInputPin * iface, IMediaSample ** pSamples, LONG nSamples, LONG *nSamplesProcessed) +{ + HRESULT hr = S_OK; + BaseInputPin *This = impl_from_IMemInputPin(iface); + + TRACE("(%p/%p)->(%p, %d, %p)\n", This, iface, pSamples, nSamples, nSamplesProcessed); + + for (*nSamplesProcessed = 0; *nSamplesProcessed < nSamples; (*nSamplesProcessed)++) + { + hr = IMemInputPin_Receive(iface, pSamples[*nSamplesProcessed]); + if (hr != S_OK) + break; + } + + return hr; +} + +static HRESULT WINAPI MemInputPin_ReceiveCanBlock(IMemInputPin * iface) +{ + BaseInputPin *This = impl_from_IMemInputPin(iface); + + TRACE("(%p/%p)->()\n", This, iface); + + return S_OK; +} + +static const IMemInputPinVtbl MemInputPin_Vtbl = +{ + MemInputPin_QueryInterface, + MemInputPin_AddRef, + MemInputPin_Release, + MemInputPin_GetAllocator, + MemInputPin_NotifyAllocator, + MemInputPin_GetAllocatorRequirements, + MemInputPin_Receive, + MemInputPin_ReceiveMultiple, + MemInputPin_ReceiveCanBlock +}; + +static HRESULT InputPin_Init(const IPinVtbl *InputPin_Vtbl, const PIN_INFO * pPinInfo, + BasePin_CheckMediaType pCheckMediaType, BaseInputPin_Receive pReceive, + LPCRITICAL_SECTION pCritSec, IMemAllocator *allocator, BaseInputPin * pPinImpl) +{ + TRACE("\n"); + + /* Common attributes */ + pPinImpl->pin.refCount = 1; + pPinImpl->pin.pConnectedTo = NULL; + pPinImpl->pin.pCritSec = pCritSec; + Copy_PinInfo(&pPinImpl->pin.pinInfo, pPinInfo); + ZeroMemory(&pPinImpl->pin.mtCurrent, sizeof(AM_MEDIA_TYPE)); + + /* Input pin attributes */ + pPinImpl->fnCheckMediaType = pCheckMediaType; + pPinImpl->fnReceive = pReceive; + pPinImpl->pAllocator = pPinImpl->preferred_allocator = allocator; + if (pPinImpl->preferred_allocator) + IMemAllocator_AddRef(pPinImpl->preferred_allocator); + pPinImpl->tStart = 0; + pPinImpl->tStop = 0; + pPinImpl->dRate = 1.0; + pPinImpl->pin.lpVtbl = InputPin_Vtbl; + pPinImpl->lpVtblMemInput = &MemInputPin_Vtbl; + pPinImpl->flushing = pPinImpl->end_of_stream = 0; + + return S_OK; +} + +HRESULT BaseInputPin_Construct(const IPinVtbl *InputPin_Vtbl, const PIN_INFO * pPinInfo, + BasePin_CheckMediaType pCheckMediaType, BaseInputPin_Receive pReceive, + LPCRITICAL_SECTION pCritSec, IMemAllocator *allocator, IPin ** ppPin) +{ + BaseInputPin * pPinImpl; + + *ppPin = NULL; + + if (pPinInfo->dir != PINDIR_INPUT) + { + ERR("Pin direction(%x) != PINDIR_INPUT\n", pPinInfo->dir); + return E_INVALIDARG; + } + + pPinImpl = CoTaskMemAlloc(sizeof(*pPinImpl)); + + if (!pPinImpl) + return E_OUTOFMEMORY; + + if (SUCCEEDED(InputPin_Init(InputPin_Vtbl, pPinInfo, pCheckMediaType, pReceive, pCritSec, allocator, pPinImpl))) + { + *ppPin = (IPin *)pPinImpl; + return S_OK; + } + + CoTaskMemFree(pPinImpl); + return E_FAIL; +} diff --git a/include/wine/strmbase.h b/include/wine/strmbase.h index 217827b3781..b0efeeabf04 100644 --- a/include/wine/strmbase.h +++ b/include/wine/strmbase.h @@ -27,11 +27,14 @@ void WINAPI DeleteMediaType(AM_MEDIA_TYPE * pMediaType); typedef HRESULT (WINAPI *BasePin_GetMediaType)(IPin* iface, int iPosition, AM_MEDIA_TYPE *amt); typedef LONG (WINAPI *BasePin_GetMediaTypeVersion)(IPin* iface); typedef HRESULT (WINAPI *BasePin_AttemptConnection)(IPin *iface, IPin *pReceivePin, const AM_MEDIA_TYPE *pmt); +typedef HRESULT (WINAPI *BasePin_CheckMediaType)(IPin *iface, const AM_MEDIA_TYPE *pmt); typedef IPin* (WINAPI *BaseFilter_GetPin)(IBaseFilter* iface, int iPosition); typedef LONG (WINAPI *BaseFilter_GetPinCount)(IBaseFilter* iface); typedef LONG (WINAPI *BaseFilter_GetPinVersion)(IBaseFilter* iface); +typedef HRESULT (WINAPI *BaseInputPin_Receive)(IPin *This, IMediaSample *pSample); + HRESULT WINAPI EnumMediaTypes_Construct(IPin *iface, BasePin_GetMediaType enumFunc, BasePin_GetMediaTypeVersion versionFunc, IEnumMediaTypes ** ppEnum); HRESULT WINAPI EnumPins_Construct(IBaseFilter *base, BaseFilter_GetPin receive_pin, BaseFilter_GetPinCount receive_pincount, BaseFilter_GetPinVersion receive_version, IEnumPins ** ppEnum); @@ -61,6 +64,22 @@ typedef struct BaseOutputPin ALLOCATOR_PROPERTIES allocProps; } BaseOutputPin; +typedef struct BaseInputPin +{ + /* inheritance C style! */ + BasePin pin; + + const IMemInputPinVtbl * lpVtblMemInput; + IMemAllocator * pAllocator; + BaseInputPin_Receive fnReceive; + BasePin_CheckMediaType fnCheckMediaType; + REFERENCE_TIME tStart; + REFERENCE_TIME tStop; + double dRate; + BOOL flushing, end_of_stream; + IMemAllocator *preferred_allocator; +} BaseInputPin; + /* Base Pin */ HRESULT WINAPI BasePinImpl_GetMediaType(IPin *iface, int iPosition, AM_MEDIA_TYPE *pmt); LONG WINAPI BasePinImpl_GetMediaTypeVersion(IPin *iface); @@ -92,3 +111,16 @@ HRESULT WINAPI BaseOutputPinImpl_BreakConnect(BaseOutputPin * This); HRESULT WINAPI BaseOutputPinImpl_Active(BaseOutputPin * This); HRESULT WINAPI BaseOutputPinImpl_Inactive(BaseOutputPin * This); HRESULT WINAPI BaseOutputPin_Construct(const IPinVtbl *OutputPin_Vtbl, LONG outputpin_size, const PIN_INFO * pPinInfo, ALLOCATOR_PROPERTIES *props, BasePin_AttemptConnection pConnectProc, LPCRITICAL_SECTION pCritSec, IPin ** ppPin); + +/* Base Input Pin */ +HRESULT WINAPI BaseInputPinImpl_QueryInterface(IPin * iface, REFIID riid, LPVOID * ppv); +ULONG WINAPI BaseInputPinImpl_Release(IPin * iface); +HRESULT WINAPI BaseInputPinImpl_Connect(IPin * iface, IPin * pConnector, const AM_MEDIA_TYPE * pmt); +HRESULT WINAPI BaseInputPinImpl_ReceiveConnection(IPin * iface, IPin * pReceivePin, const AM_MEDIA_TYPE * pmt); +HRESULT WINAPI BaseInputPinImpl_QueryAccept(IPin * iface, const AM_MEDIA_TYPE * pmt); +HRESULT WINAPI BaseInputPinImpl_EndOfStream(IPin * iface); +HRESULT WINAPI BaseInputPinImpl_BeginFlush(IPin * iface); +HRESULT WINAPI BaseInputPinImpl_EndFlush(IPin * iface); +HRESULT WINAPI BaseInputPinImpl_NewSegment(IPin * iface, REFERENCE_TIME tStart, REFERENCE_TIME tStop, double dRate); + +HRESULT BaseInputPin_Construct(const IPinVtbl *InputPin_Vtbl, const PIN_INFO * pPinInfo, BasePin_CheckMediaType pQueryAccept, BaseInputPin_Receive pSampleProc, LPCRITICAL_SECTION pCritSec, IMemAllocator *, IPin ** ppPin);