Module: wine Branch: master Commit: 9985f2efc9d1e92932dd3d7f351ded3ae1db0b80 URL: http://source.winehq.org/git/wine.git/?a=commit;h=9985f2efc9d1e92932dd3d7f35...
Author: Maarten Lankhorst m.b.lankhorst@gmail.com Date: Fri Jul 4 01:33:04 2008 -0700
quartz: Implement state transitions in video renderer.
---
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 };