quartz: Implement state transitions in video renderer.
This commit is contained in:
parent
b6b67f698a
commit
9985f2efc9
|
@ -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
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in New Issue