From 8e71d879cd4c401ab14118244f166ccacb461b41 Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Fri, 4 Jul 2008 00:53:45 -0700 Subject: [PATCH] quartz: Implement state transitions in video renderer and make it block on pause --- dlls/quartz/videorenderer.c | 102 +++++++++++++++++++++++++++++++----------- 1 files changed, 75 insertions(+), 27 deletions(-) diff --git a/dlls/quartz/videorenderer.c b/dlls/quartz/videorenderer.c index 24e1afb..985060d 100644 --- a/dlls/quartz/videorenderer.c +++ b/dlls/quartz/videorenderer.c @@ -75,6 +75,8 @@ typedef struct VideoRendererImpl /* Synchronization handle for creating window and state changes */ HANDLE hEvent; + HANDLE blocked; + BOOL ThreadResult; HWND hWnd; HWND hWndMsgDrain; @@ -233,7 +235,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; @@ -413,15 +415,20 @@ 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; } - SetEvent(This->hEvent); if (This->pClock && This->state == State_Running) { @@ -614,7 +621,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; } @@ -793,13 +807,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); @@ -813,14 +822,17 @@ static HRESULT WINAPI VideoRenderer_Pause(IBaseFilter * iface) ERR("(%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); - if (!This->pInputPin->end_of_stream) - ResetEvent(This->hEvent); } LeaveCriticalSection(&This->csFilter); @@ -837,18 +849,14 @@ static HRESULT WINAPI VideoRenderer_Run(IBaseFilter * iface, REFERENCE_TIME tSta if (This->state != State_Running) { if (This->state == State_Stopped) + { + ResetEvent(This->hEvent); This->pInputPin->end_of_stream = 0; + } + SetEvent(This->blocked); This->rtStreamStart = tStart; This->state = State_Running; - - if (This->sample_held) - { - IMediaSample_Release(This->sample_held); - This->sample_held = NULL; - } - - ResetEvent(This->hEvent); } LeaveCriticalSection(&This->csFilter); @@ -858,17 +866,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); - WaitForSingleObject(This->hEvent, dwMilliSecsTimeout); + 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) @@ -1024,6 +1037,41 @@ 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, @@ -1041,8 +1089,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