diff --git a/dlls/quartz/nullrenderer.c b/dlls/quartz/nullrenderer.c index 3172dcaf953..ab4dba2e6ce 100644 --- a/dlls/quartz/nullrenderer.c +++ b/dlls/quartz/nullrenderer.c @@ -71,6 +71,7 @@ static HRESULT WINAPI NullRenderer_CheckMediaType(BaseRenderer *iface, const AM_ static const BaseRendererFuncTable RendererFuncTable = { NullRenderer_CheckMediaType, NullRenderer_DoRenderSample, + /**/ NULL, NULL, NULL, @@ -81,6 +82,10 @@ static const BaseRendererFuncTable RendererFuncTable = { NULL, NULL, NULL, + /**/ + NULL, + NULL, + NULL, NULL, NULL, }; @@ -233,7 +238,7 @@ static const IBaseFilterVtbl NullRenderer_Vtbl = BaseRendererImpl_Stop, BaseRendererImpl_Pause, BaseRendererImpl_Run, - BaseFilterImpl_GetState, + BaseRendererImpl_GetState, BaseFilterImpl_SetSyncSource, BaseFilterImpl_GetSyncSource, BaseFilterImpl_EnumPins, diff --git a/dlls/strmbase/renderer.c b/dlls/strmbase/renderer.c index 3c9225c16bc..1d3f3b5e76a 100644 --- a/dlls/strmbase/renderer.c +++ b/dlls/strmbase/renderer.c @@ -47,6 +47,46 @@ static inline BaseRenderer *impl_from_BaseFilter(BaseFilter *iface) return CONTAINING_RECORD(iface, BaseRenderer, filter); } +static HRESULT WINAPI BaseRenderer_InputPin_ReceiveConnection(IPin * iface, IPin * pReceivePin, const AM_MEDIA_TYPE * pmt) +{ + BaseInputPin *This = impl_BaseInputPin_from_IPin(iface); + BaseRenderer *renderer = impl_from_IBaseFilter(This->pin.pinInfo.pFilter); + HRESULT hr = S_OK; + + TRACE("(%p/%p)->(%p, %p)\n", This, renderer, pReceivePin, pmt); + + EnterCriticalSection(This->pin.pCritSec); + hr = BaseInputPinImpl_ReceiveConnection(iface, pReceivePin, pmt); + if (SUCCEEDED(hr)) + { + if (renderer->pFuncsTable->pfnCompleteConnect) + hr = renderer->pFuncsTable->pfnCompleteConnect(renderer, pReceivePin); + } + LeaveCriticalSection(This->pin.pCritSec); + + return hr; +} + +static HRESULT WINAPI BaseRenderer_InputPin_Disconnect(IPin * iface) +{ + BaseInputPin *This = impl_BaseInputPin_from_IPin(iface); + BaseRenderer *renderer = impl_from_IBaseFilter(This->pin.pinInfo.pFilter); + HRESULT hr; + + TRACE("(%p/%p)\n", This, renderer); + + EnterCriticalSection(This->pin.pCritSec); + hr = BasePinImpl_Disconnect(iface); + if (SUCCEEDED(hr)) + { + if (renderer->pFuncsTable->pfnBreakConnect) + hr = renderer->pFuncsTable->pfnBreakConnect(renderer); + } + LeaveCriticalSection(This->pin.pCritSec); + + return hr; +} + static HRESULT WINAPI BaseRenderer_InputPin_EndOfStream(IPin * iface) { HRESULT hr = S_OK; @@ -72,6 +112,31 @@ static HRESULT WINAPI BaseRenderer_InputPin_EndOfStream(IPin * iface) return hr; } +static HRESULT WINAPI BaseRenderer_InputPin_BeginFlush(IPin * iface) +{ + BaseInputPin* This = impl_BaseInputPin_from_IPin(iface); + BaseRenderer *pFilter = impl_from_IBaseFilter(This->pin.pinInfo.pFilter); + HRESULT hr = S_OK; + + TRACE("(%p/%p)->()\n", This, iface); + + EnterCriticalSection(&pFilter->filter.csFilter); + EnterCriticalSection(&pFilter->csRenderLock); + EnterCriticalSection(This->pin.pCritSec); + hr = BaseInputPinImpl_BeginFlush(iface); + if (SUCCEEDED(hr)) + { + if (pFilter->pFuncsTable->pfnBeginFlush) + hr = pFilter->pFuncsTable->pfnBeginFlush(pFilter); + else + hr = BaseRendererImpl_BeginFlush(pFilter); + } + LeaveCriticalSection(This->pin.pCritSec); + LeaveCriticalSection(&pFilter->filter.csFilter); + LeaveCriticalSection(&pFilter->csRenderLock); + return hr; +} + static HRESULT WINAPI BaseRenderer_InputPin_EndFlush(IPin * iface) { BaseInputPin* This = impl_BaseInputPin_from_IPin(iface); @@ -103,8 +168,8 @@ static const IPinVtbl BaseRenderer_InputPin_Vtbl = BasePinImpl_AddRef, BaseInputPinImpl_Release, BaseInputPinImpl_Connect, - BaseInputPinImpl_ReceiveConnection, - BasePinImpl_Disconnect, + BaseRenderer_InputPin_ReceiveConnection, + BaseRenderer_InputPin_Disconnect, BasePinImpl_ConnectedTo, BasePinImpl_ConnectionMediaType, BasePinImpl_QueryPinInfo, @@ -114,7 +179,7 @@ static const IPinVtbl BaseRenderer_InputPin_Vtbl = BasePinImpl_EnumMediaTypes, BasePinImpl_QueryInternalConnections, BaseRenderer_InputPin_EndOfStream, - BaseInputPinImpl_BeginFlush, + BaseRenderer_InputPin_BeginFlush, BaseRenderer_InputPin_EndFlush, BaseInputPinImpl_NewSegment }; @@ -188,6 +253,7 @@ HRESULT WINAPI BaseRenderer_Init(BaseRenderer * This, const IBaseFilterVtbl *Vtb InitializeCriticalSection(&This->csRenderLock); This->csRenderLock.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__": BaseRenderer.csRenderLock"); + This->evComplete = CreateEventW(NULL, TRUE, TRUE, NULL); } return hr; @@ -225,6 +291,7 @@ ULONG WINAPI BaseRendererImpl_Release(IBaseFilter* iface) This->csRenderLock.DebugInfo->Spare[0] = 0; DeleteCriticalSection(&This->csRenderLock); + CloseHandle(This->evComplete); } return refCount; } @@ -233,9 +300,24 @@ HRESULT WINAPI BaseRendererImpl_Receive(BaseRenderer *This, IMediaSample * pSamp { HRESULT hr = S_OK; REFERENCE_TIME start, stop; + AM_MEDIA_TYPE *pmt; TRACE("(%p)->%p\n", This, pSample); + if (This->pInputPin->end_of_stream || This->pInputPin->flushing) + return S_FALSE; + + if (This->filter.state == State_Stopped) + return VFW_E_WRONG_STATE; + + if (IMediaSample_GetMediaType(pSample, &pmt) == S_OK) + { + if (FAILED(This->pFuncsTable->pfnCheckMediaType(This, pmt))) + { + return VFW_E_TYPE_NOT_ACCEPTED; + } + } + if (This->pFuncsTable->pfnPrepareReceive) hr = This->pFuncsTable->pfnPrepareReceive(This, pSample); if (FAILED(hr)) @@ -254,6 +336,8 @@ HRESULT WINAPI BaseRendererImpl_Receive(BaseRenderer *This, IMediaSample * pSamp { if (This->pFuncsTable->pfnOnReceiveFirstSample) This->pFuncsTable->pfnOnReceiveFirstSample(This, pSample); + + SetEvent(This->evComplete); } /* Wait for render Time */ @@ -281,8 +365,6 @@ HRESULT WINAPI BaseRendererImpl_Receive(BaseRenderer *This, IMediaSample * pSamp return S_OK; } } - if (This->pInputPin->flushing || This->pInputPin->end_of_stream) - hr = S_FALSE; if (SUCCEEDED(hr)) hr = This->pFuncsTable->pfnDoRenderSample(This, pSample); @@ -322,6 +404,7 @@ HRESULT WINAPI BaseRendererImpl_Stop(IBaseFilter * iface) if (This->pFuncsTable->pfnOnStopStreaming) This->pFuncsTable->pfnOnStopStreaming(This); This->filter.state = State_Stopped; + SetEvent(This->evComplete); } LeaveCriticalSection(&This->csRenderLock); @@ -338,6 +421,9 @@ HRESULT WINAPI BaseRendererImpl_Run(IBaseFilter * iface, REFERENCE_TIME tStart) This->filter.rtStreamStart = tStart; if (This->filter.state == State_Running) goto out; + + SetEvent(This->evComplete); + if (This->pInputPin->pin.pConnectedTo) { This->pInputPin->end_of_stream = 0; @@ -376,7 +462,13 @@ HRESULT WINAPI BaseRendererImpl_Pause(IBaseFilter * iface) if (This->filter.state != State_Paused) { if (This->filter.state == State_Stopped) + { + if (This->pInputPin->pin.pConnectedTo) + ResetEvent(This->evComplete); This->pInputPin->end_of_stream = 0; + } + else if (This->pFuncsTable->pfnOnStopStreaming) + This->pFuncsTable->pfnOnStopStreaming(This); This->filter.state = State_Paused; } } @@ -385,6 +477,23 @@ HRESULT WINAPI BaseRendererImpl_Pause(IBaseFilter * iface) return S_OK; } +HRESULT WINAPI BaseRendererImpl_GetState(IBaseFilter * iface, DWORD dwMilliSecsTimeout, FILTER_STATE *pState) +{ + HRESULT hr; + BaseRenderer *This = impl_from_IBaseFilter(iface); + + TRACE("(%p)->(%d, %p)\n", This, dwMilliSecsTimeout, pState); + + if (WaitForSingleObject(This->evComplete, dwMilliSecsTimeout) == WAIT_TIMEOUT) + hr = VFW_S_STATE_INTERMEDIATE; + else + hr = S_OK; + + BaseFilterImpl_GetState(iface, dwMilliSecsTimeout, pState); + + return hr; +} + HRESULT WINAPI BaseRendererImpl_EndOfStream(BaseRenderer* iface) { IMediaEventSink* pEventSink; @@ -403,10 +512,17 @@ HRESULT WINAPI BaseRendererImpl_EndOfStream(BaseRenderer* iface) } } RendererPosPassThru_EOS(iface->pPosition); + SetEvent(iface->evComplete); return hr; } +HRESULT WINAPI BaseRendererImpl_BeginFlush(BaseRenderer* iface) +{ + TRACE("(%p)\n", iface); + return S_OK; +} + HRESULT WINAPI BaseRendererImpl_EndFlush(BaseRenderer* iface) { TRACE("(%p)\n", iface); diff --git a/include/wine/strmbase.h b/include/wine/strmbase.h index 5b7952848fe..46544ba1e18 100644 --- a/include/wine/strmbase.h +++ b/include/wine/strmbase.h @@ -582,6 +582,7 @@ typedef struct BaseRendererTag BaseInputPin *pInputPin; IUnknown *pPosition; CRITICAL_SECTION csRenderLock; + HANDLE evComplete; const struct BaseRendererFuncTable * pFuncsTable; } BaseRenderer; @@ -599,7 +600,10 @@ typedef VOID (WINAPI *BaseRenderer_PrepareRender)(BaseRenderer *This); typedef HRESULT (WINAPI *BaseRenderer_ShouldDrawSampleNow)(BaseRenderer *This, IMediaSample *pMediaSample, REFERENCE_TIME *pStartTime, REFERENCE_TIME *pEndTime); typedef HRESULT (WINAPI *BaseRenderer_PrepareReceive)(BaseRenderer *This, IMediaSample *pMediaSample); typedef HRESULT (WINAPI *BaseRenderer_EndOfStream)(BaseRenderer *This); +typedef HRESULT (WINAPI *BaseRenderer_BeginFlush) (BaseRenderer *This); typedef HRESULT (WINAPI *BaseRenderer_EndFlush) (BaseRenderer *This); +typedef HRESULT (WINAPI *BaseRenderer_BreakConnect) (BaseRenderer *This); +typedef HRESULT (WINAPI *BaseRenderer_CompleteConnect) (BaseRenderer *This, IPin *pReceivePin); typedef struct BaseRendererFuncTable { /* Required */ @@ -617,7 +621,10 @@ typedef struct BaseRendererFuncTable { BaseRenderer_ShouldDrawSampleNow pfnShouldDrawSampleNow; BaseRenderer_PrepareReceive pfnPrepareReceive; /* Optional, Input Pin */ + BaseRenderer_CompleteConnect pfnCompleteConnect; + BaseRenderer_BreakConnect pfnBreakConnect; BaseRenderer_EndOfStream pfnEndOfStream; + BaseRenderer_BeginFlush pfnBeginFlush; BaseRenderer_EndFlush pfnEndFlush; } BaseRendererFuncTable; @@ -628,7 +635,9 @@ HRESULT WINAPI BaseRendererImpl_FindPin(IBaseFilter * iface, LPCWSTR Id, IPin ** HRESULT WINAPI BaseRendererImpl_Stop(IBaseFilter * iface); HRESULT WINAPI BaseRendererImpl_Run(IBaseFilter * iface, REFERENCE_TIME tStart); HRESULT WINAPI BaseRendererImpl_Pause(IBaseFilter * iface); +HRESULT WINAPI BaseRendererImpl_GetState(IBaseFilter * iface, DWORD dwMilliSecsTimeout, FILTER_STATE *pState); HRESULT WINAPI BaseRendererImpl_EndOfStream(BaseRenderer* iface); +HRESULT WINAPI BaseRendererImpl_BeginFlush(BaseRenderer* iface); HRESULT WINAPI BaseRendererImpl_EndFlush(BaseRenderer* iface); HRESULT WINAPI BaseRenderer_Init(BaseRenderer *This, const IBaseFilterVtbl *Vtbl, IUnknown *pUnkOuter, const CLSID *pClsid, DWORD_PTR DebugInfo, const BaseRendererFuncTable* pBaseFuncsTable);