From 7eedb858f1211aa9c204f7fd2b819e6df735b675 Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Fri, 4 Jul 2008 01:33:04 -0700 Subject: [PATCH] quartz: Implement state transitions in video renderer and make it block on pause --- dlls/quartz/videorenderer.c | 101 +++++++++++++++++++++++++++++++++--------- 1 files changed, 79 insertions(+), 22 deletions(-) diff --git a/dlls/quartz/videorenderer.c b/dlls/quartz/videorenderer.c index 23a5cd9..1ade1c8 100644 --- a/dlls/quartz/videorenderer.c +++ b/dlls/quartz/videorenderer.c @@ -71,6 +71,8 @@ typedef struct VideoRendererImpl BOOL init; HANDLE hThread; + HANDLE blocked; + DWORD ThreadID; HANDLE hEvent; BOOL ThreadResult; @@ -231,7 +233,7 @@ static DWORD WINAPI MessageLoop(LPVOID lpParameter) static BOOL CreateRenderingSubsystem(VideoRendererImpl* This) { - This->hEvent = CreateEventW(NULL, FALSE, FALSE, NULL); + This->hEvent = CreateEventW(NULL, TRUE, FALSE, NULL); if (!This->hEvent) return FALSE; @@ -243,10 +245,10 @@ static BOOL CreateRenderingSubsystem(VideoRendererImpl* This) } WaitForSingleObject(This->hEvent, INFINITE); - CloseHandle(This->hEvent); if (!This->ThreadResult) { + CloseHandle(This->hEvent); CloseHandle(This->hThread); return FALSE; } @@ -411,13 +413,19 @@ static HRESULT VideoRenderer_Sample(LPVOID iface, IMediaSample * pSample) } #endif + SetEvent(This->hEvent); if (This->state == State_Paused) { - if (This->sample_held) - IMediaSample_Release(This->sample_held); - This->sample_held = pSample; - IMediaSample_AddRef(pSample); + LeaveCriticalSection(&This->csFilter); + WaitForSingleObject(This->blocked, INFINITE); + EnterCriticalSection(&This->csFilter); + This->sample_held = NULL; + if (This->state == State_Paused) + /* Flushing */ + return S_OK; + if (This->state == State_Stopped) + return VFW_E_WRONG_STATE; } if (This->pClock && This->state == State_Running) @@ -611,7 +619,14 @@ HRESULT VideoRenderer_create(IUnknown * pUnkOuter, LPVOID * ppv) if (!CreateRenderingSubsystem(pVideoRenderer)) return E_FAIL; - + + pVideoRenderer->blocked = CreateEventW(NULL, FALSE, FALSE, NULL); + if (!pVideoRenderer->blocked) + { + hr = HRESULT_FROM_WIN32(GetLastError()); + IUnknown_Release((IUnknown *)pVideoRenderer); + } + return hr; } @@ -683,6 +698,7 @@ static ULONG WINAPI VideoRendererInner_Release(IUnknown * iface) PostThreadMessageA(This->ThreadID, WM_QUIT, 0, 0); WaitForSingleObject(This->hThread, INFINITE); CloseHandle(This->hThread); + CloseHandle(This->hEvent); if (This->pClock) IReferenceClock_Release(This->pClock); @@ -789,12 +805,8 @@ static HRESULT WINAPI VideoRenderer_Stop(IBaseFilter * iface) EnterCriticalSection(&This->csFilter); { This->state = State_Stopped; - - if (This->sample_held) - { - IMediaSample_Release(This->sample_held); - This->sample_held = NULL; - } + SetEvent(This->hEvent); + SetEvent(This->blocked); } LeaveCriticalSection(&This->csFilter); @@ -808,11 +820,16 @@ static HRESULT WINAPI VideoRenderer_Pause(IBaseFilter * iface) TRACE("(%p/%p)->()\n", This, iface); EnterCriticalSection(&This->csFilter); + if (This->state != State_Paused) { if (This->state == State_Stopped) + { This->pInputPin->end_of_stream = 0; + ResetEvent(This->hEvent); + } This->state = State_Paused; + ResetEvent(This->blocked); } LeaveCriticalSection(&This->csFilter); @@ -829,16 +846,14 @@ static HRESULT WINAPI VideoRenderer_Run(IBaseFilter * iface, REFERENCE_TIME tSta if (This->state != State_Running) { if (This->state == State_Stopped) + { This->pInputPin->end_of_stream = 0; + ResetEvent(This->hEvent); + } + SetEvent(This->blocked); This->rtStreamStart = tStart; This->state = State_Running; - - if (This->sample_held) - { - IMediaSample_Release(This->sample_held); - This->sample_held = NULL; - } } LeaveCriticalSection(&This->csFilter); @@ -848,16 +863,22 @@ static HRESULT WINAPI VideoRenderer_Run(IBaseFilter * iface, REFERENCE_TIME tSta static HRESULT WINAPI VideoRenderer_GetState(IBaseFilter * iface, DWORD dwMilliSecsTimeout, FILTER_STATE *pState) { VideoRendererImpl *This = (VideoRendererImpl *)iface; + HRESULT hr; TRACE("(%p/%p)->(%d, %p)\n", This, iface, dwMilliSecsTimeout, pState); + if (WaitForSingleObject(This->hEvent, dwMilliSecsTimeout) == WAIT_TIMEOUT) + hr = VFW_S_STATE_INTERMEDIATE; + else + hr = S_OK; + EnterCriticalSection(&This->csFilter); { *pState = This->state; } LeaveCriticalSection(&This->csFilter); - return S_OK; + return hr; } static HRESULT WINAPI VideoRenderer_SetSyncSource(IBaseFilter * iface, IReferenceClock *pClock) @@ -1013,6 +1034,42 @@ static HRESULT WINAPI VideoRenderer_InputPin_EndOfStream(IPin * iface) return hr; } +static HRESULT WINAPI VideoRenderer_InputPin_BeginFlush(IPin * iface) +{ + InputPin* This = (InputPin*)iface; + VideoRendererImpl *pVideoRenderer = (VideoRendererImpl *)This->pin.pinInfo.pFilter; + HRESULT hr; + + TRACE("(%p/%p)->()\n", This, iface); + + EnterCriticalSection(This->pin.pCritSec); + if (pVideoRenderer->state == State_Paused) + SetEvent(pVideoRenderer->blocked); + + hr = InputPin_BeginFlush(iface); + LeaveCriticalSection(This->pin.pCritSec); + + return hr; +} + +static HRESULT WINAPI VideoRenderer_InputPin_EndFlush(IPin * iface) +{ + InputPin* This = (InputPin*)iface; + VideoRendererImpl *pVideoRenderer = (VideoRendererImpl *)This->pin.pinInfo.pFilter; + HRESULT hr; + + TRACE("(%p/%p)->()\n", This, iface); + + EnterCriticalSection(This->pin.pCritSec); + if (pVideoRenderer->state == State_Paused) + ResetEvent(pVideoRenderer->blocked); + + hr = InputPin_EndFlush(iface); + LeaveCriticalSection(This->pin.pCritSec); + + return hr; +} + static const IPinVtbl VideoRenderer_InputPin_Vtbl = { InputPin_QueryInterface, @@ -1030,8 +1087,8 @@ static const IPinVtbl VideoRenderer_InputPin_Vtbl = IPinImpl_EnumMediaTypes, IPinImpl_QueryInternalConnections, VideoRenderer_InputPin_EndOfStream, - InputPin_BeginFlush, - InputPin_EndFlush, + VideoRenderer_InputPin_BeginFlush, + VideoRenderer_InputPin_EndFlush, InputPin_NewSegment }; -- 1.5.4.1