quartz: Implement state transitions in video renderer.

This commit is contained in:
Maarten Lankhorst 2008-07-04 01:33:04 -07:00 committed by Alexandre Julliard
parent b6b67f698a
commit 9985f2efc9
1 changed files with 79 additions and 22 deletions

View File

@ -71,6 +71,8 @@ typedef struct VideoRendererImpl
BOOL init; BOOL init;
HANDLE hThread; HANDLE hThread;
HANDLE blocked;
DWORD ThreadID; DWORD ThreadID;
HANDLE hEvent; HANDLE hEvent;
BOOL ThreadResult; BOOL ThreadResult;
@ -231,7 +233,7 @@ static DWORD WINAPI MessageLoop(LPVOID lpParameter)
static BOOL CreateRenderingSubsystem(VideoRendererImpl* This) static BOOL CreateRenderingSubsystem(VideoRendererImpl* This)
{ {
This->hEvent = CreateEventW(NULL, FALSE, FALSE, NULL); This->hEvent = CreateEventW(NULL, TRUE, FALSE, NULL);
if (!This->hEvent) if (!This->hEvent)
return FALSE; return FALSE;
@ -243,10 +245,10 @@ static BOOL CreateRenderingSubsystem(VideoRendererImpl* This)
} }
WaitForSingleObject(This->hEvent, INFINITE); WaitForSingleObject(This->hEvent, INFINITE);
CloseHandle(This->hEvent);
if (!This->ThreadResult) if (!This->ThreadResult)
{ {
CloseHandle(This->hEvent);
CloseHandle(This->hThread); CloseHandle(This->hThread);
return FALSE; return FALSE;
} }
@ -411,13 +413,19 @@ static HRESULT VideoRenderer_Sample(LPVOID iface, IMediaSample * pSample)
} }
#endif #endif
SetEvent(This->hEvent);
if (This->state == State_Paused) if (This->state == State_Paused)
{ {
if (This->sample_held)
IMediaSample_Release(This->sample_held);
This->sample_held = pSample; 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) if (This->pClock && This->state == State_Running)
@ -611,7 +619,14 @@ HRESULT VideoRenderer_create(IUnknown * pUnkOuter, LPVOID * ppv)
if (!CreateRenderingSubsystem(pVideoRenderer)) if (!CreateRenderingSubsystem(pVideoRenderer))
return E_FAIL; return E_FAIL;
pVideoRenderer->blocked = CreateEventW(NULL, FALSE, FALSE, NULL);
if (!pVideoRenderer->blocked)
{
hr = HRESULT_FROM_WIN32(GetLastError());
IUnknown_Release((IUnknown *)pVideoRenderer);
}
return hr; return hr;
} }
@ -683,6 +698,7 @@ static ULONG WINAPI VideoRendererInner_Release(IUnknown * iface)
PostThreadMessageA(This->ThreadID, WM_QUIT, 0, 0); PostThreadMessageA(This->ThreadID, WM_QUIT, 0, 0);
WaitForSingleObject(This->hThread, INFINITE); WaitForSingleObject(This->hThread, INFINITE);
CloseHandle(This->hThread); CloseHandle(This->hThread);
CloseHandle(This->hEvent);
if (This->pClock) if (This->pClock)
IReferenceClock_Release(This->pClock); IReferenceClock_Release(This->pClock);
@ -789,12 +805,8 @@ static HRESULT WINAPI VideoRenderer_Stop(IBaseFilter * iface)
EnterCriticalSection(&This->csFilter); EnterCriticalSection(&This->csFilter);
{ {
This->state = State_Stopped; This->state = State_Stopped;
SetEvent(This->hEvent);
if (This->sample_held) SetEvent(This->blocked);
{
IMediaSample_Release(This->sample_held);
This->sample_held = NULL;
}
} }
LeaveCriticalSection(&This->csFilter); LeaveCriticalSection(&This->csFilter);
@ -808,11 +820,16 @@ static HRESULT WINAPI VideoRenderer_Pause(IBaseFilter * iface)
TRACE("(%p/%p)->()\n", This, iface); TRACE("(%p/%p)->()\n", This, iface);
EnterCriticalSection(&This->csFilter); EnterCriticalSection(&This->csFilter);
if (This->state != State_Paused)
{ {
if (This->state == State_Stopped) if (This->state == State_Stopped)
{
This->pInputPin->end_of_stream = 0; This->pInputPin->end_of_stream = 0;
ResetEvent(This->hEvent);
}
This->state = State_Paused; This->state = State_Paused;
ResetEvent(This->blocked);
} }
LeaveCriticalSection(&This->csFilter); 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_Running)
{ {
if (This->state == State_Stopped) if (This->state == State_Stopped)
{
This->pInputPin->end_of_stream = 0; This->pInputPin->end_of_stream = 0;
ResetEvent(This->hEvent);
}
SetEvent(This->blocked);
This->rtStreamStart = tStart; This->rtStreamStart = tStart;
This->state = State_Running; This->state = State_Running;
if (This->sample_held)
{
IMediaSample_Release(This->sample_held);
This->sample_held = NULL;
}
} }
LeaveCriticalSection(&This->csFilter); 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) static HRESULT WINAPI VideoRenderer_GetState(IBaseFilter * iface, DWORD dwMilliSecsTimeout, FILTER_STATE *pState)
{ {
VideoRendererImpl *This = (VideoRendererImpl *)iface; VideoRendererImpl *This = (VideoRendererImpl *)iface;
HRESULT hr;
TRACE("(%p/%p)->(%d, %p)\n", This, iface, dwMilliSecsTimeout, pState); 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); EnterCriticalSection(&This->csFilter);
{ {
*pState = This->state; *pState = This->state;
} }
LeaveCriticalSection(&This->csFilter); LeaveCriticalSection(&This->csFilter);
return S_OK; return hr;
} }
static HRESULT WINAPI VideoRenderer_SetSyncSource(IBaseFilter * iface, IReferenceClock *pClock) static HRESULT WINAPI VideoRenderer_SetSyncSource(IBaseFilter * iface, IReferenceClock *pClock)
@ -1013,6 +1034,42 @@ static HRESULT WINAPI VideoRenderer_InputPin_EndOfStream(IPin * iface)
return hr; 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 = static const IPinVtbl VideoRenderer_InputPin_Vtbl =
{ {
InputPin_QueryInterface, InputPin_QueryInterface,
@ -1030,8 +1087,8 @@ static const IPinVtbl VideoRenderer_InputPin_Vtbl =
IPinImpl_EnumMediaTypes, IPinImpl_EnumMediaTypes,
IPinImpl_QueryInternalConnections, IPinImpl_QueryInternalConnections,
VideoRenderer_InputPin_EndOfStream, VideoRenderer_InputPin_EndOfStream,
InputPin_BeginFlush, VideoRenderer_InputPin_BeginFlush,
InputPin_EndFlush, VideoRenderer_InputPin_EndFlush,
InputPin_NewSegment InputPin_NewSegment
}; };