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;
|
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)
|
||||||
|
@ -612,6 +620,13 @@ 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
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue