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;
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
};