quartz: Fix parser and pins logic to no longer deadlock.
This commit is contained in:
parent
855e3a08b5
commit
0e9ed6b402
|
@ -259,11 +259,11 @@ static HRESULT WINAPI Parser_Stop(IBaseFilter * iface)
|
|||
LeaveCriticalSection(&This->csFilter);
|
||||
return S_OK;
|
||||
}
|
||||
hr = PullPin_StopProcessing(This->pInputPin);
|
||||
This->state = State_Stopped;
|
||||
}
|
||||
LeaveCriticalSection(&This->csFilter);
|
||||
|
||||
|
||||
hr = PullPin_StopProcessing(This->pInputPin);
|
||||
return hr;
|
||||
}
|
||||
|
||||
|
@ -291,8 +291,6 @@ static HRESULT WINAPI Parser_Pause(IBaseFilter * iface)
|
|||
{
|
||||
unsigned int i;
|
||||
|
||||
hr = PullPin_Seek(This->pInputPin, 0, ((LONGLONG)0x7fffffff << 32) | 0xffffffff);
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
hr = PullPin_InitProcessing(This->pInputPin);
|
||||
|
||||
|
@ -342,11 +340,11 @@ static HRESULT WINAPI Parser_Run(IBaseFilter * iface, REFERENCE_TIME tStart)
|
|||
|
||||
This->rtStreamStart = tStart;
|
||||
|
||||
hr = PullPin_Seek(This->pInputPin, 0, ((LONGLONG)0x7fffffff << 32) | 0xffffffff);
|
||||
|
||||
if (SUCCEEDED(hr) && (This->state == State_Stopped))
|
||||
{
|
||||
LeaveCriticalSection(&This->csFilter);
|
||||
hr = PullPin_InitProcessing(This->pInputPin);
|
||||
EnterCriticalSection(&This->csFilter);
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
|
@ -358,7 +356,11 @@ static HRESULT WINAPI Parser_Run(IBaseFilter * iface, REFERENCE_TIME tStart)
|
|||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
LeaveCriticalSection(&This->csFilter);
|
||||
hr = PullPin_StartProcessing(This->pInputPin);
|
||||
EnterCriticalSection(&This->csFilter);
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
This->state = State_Running;
|
||||
|
|
|
@ -1195,11 +1195,12 @@ HRESULT PullPin_Init(const PIN_INFO * pPinInfo, SAMPLEPROC pSampleProc, LPVOID p
|
|||
pPinImpl->pAlloc = NULL;
|
||||
pPinImpl->pReader = NULL;
|
||||
pPinImpl->hThread = NULL;
|
||||
pPinImpl->hEventStateChanged = CreateEventW(NULL, FALSE, TRUE, NULL);
|
||||
pPinImpl->hEventStateChanged = CreateEventW(NULL, TRUE, TRUE, NULL);
|
||||
|
||||
pPinImpl->rtStart = 0;
|
||||
pPinImpl->rtCurrent = 0;
|
||||
pPinImpl->rtStop = ((LONGLONG)0x7fffffff << 32) | 0xffffffff;
|
||||
pPinImpl->state = State_Stopped;
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
@ -1337,8 +1338,11 @@ static void CALLBACK PullPin_Thread_Process(ULONG_PTR iface)
|
|||
ALLOCATOR_PROPERTIES allocProps;
|
||||
|
||||
CoInitializeEx(NULL, COINIT_MULTITHREADED);
|
||||
|
||||
|
||||
EnterCriticalSection(This->pin.pCritSec);
|
||||
SetEvent(This->hEventStateChanged);
|
||||
This->state = State_Running;
|
||||
LeaveCriticalSection(This->pin.pCritSec);
|
||||
|
||||
hr = IMemAllocator_GetProperties(This->pAlloc, &allocProps);
|
||||
|
||||
|
@ -1347,7 +1351,7 @@ static void CALLBACK PullPin_Thread_Process(ULONG_PTR iface)
|
|||
|
||||
TRACE("Start\n");
|
||||
|
||||
while (This->rtCurrent < This->rtStop && hr == S_OK)
|
||||
while (This->rtCurrent < This->rtStop && hr == S_OK && !This->stop_playback)
|
||||
{
|
||||
/* FIXME: to improve performance by quite a bit this should be changed
|
||||
* so that one sample is processed while one sample is fetched. However,
|
||||
|
@ -1375,7 +1379,7 @@ static void CALLBACK PullPin_Thread_Process(ULONG_PTR iface)
|
|||
hr = IAsyncReader_Request(This->pReader, pSample, (ULONG_PTR)0);
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
hr = IAsyncReader_WaitForNext(This->pReader, 10000, &pSample, &dwUser);
|
||||
hr = IAsyncReader_WaitForNext(This->pReader, 1000, &pSample, &dwUser);
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
|
@ -1395,10 +1399,27 @@ static void CALLBACK PullPin_Thread_Process(ULONG_PTR iface)
|
|||
}
|
||||
|
||||
CoUninitialize();
|
||||
|
||||
EnterCriticalSection(This->pin.pCritSec);
|
||||
This->state = State_Paused;
|
||||
LeaveCriticalSection(This->pin.pCritSec);
|
||||
TRACE("End\n");
|
||||
}
|
||||
|
||||
static void CALLBACK PullPin_Thread_Pause(ULONG_PTR iface)
|
||||
{
|
||||
PullPin *This = (PullPin *)iface;
|
||||
|
||||
TRACE("(%p/%p)->()\n", This, (LPVOID)iface);
|
||||
|
||||
EnterCriticalSection(This->pin.pCritSec);
|
||||
{
|
||||
This->state = State_Paused;
|
||||
SetEvent(This->hEventStateChanged);
|
||||
}
|
||||
LeaveCriticalSection(This->pin.pCritSec);
|
||||
}
|
||||
|
||||
|
||||
static void CALLBACK PullPin_Thread_Stop(ULONG_PTR iface)
|
||||
{
|
||||
PullPin *This = (PullPin *)iface;
|
||||
|
@ -1413,11 +1434,12 @@ static void CALLBACK PullPin_Thread_Stop(ULONG_PTR iface)
|
|||
This->hThread = NULL;
|
||||
if (FAILED(hr = IMemAllocator_Decommit(This->pAlloc)))
|
||||
ERR("Allocator decommit failed with error %x. Possible memory leak\n", hr);
|
||||
|
||||
SetEvent(This->hEventStateChanged);
|
||||
This->state = State_Stopped;
|
||||
}
|
||||
LeaveCriticalSection(This->pin.pCritSec);
|
||||
|
||||
SetEvent(This->hEventStateChanged);
|
||||
|
||||
IBaseFilter_Release(This->pin.pinInfo.pFilter);
|
||||
|
||||
ExitThread(0);
|
||||
|
@ -1429,16 +1451,16 @@ HRESULT PullPin_InitProcessing(PullPin * This)
|
|||
|
||||
TRACE("(%p)->()\n", This);
|
||||
|
||||
assert(!This->hThread);
|
||||
|
||||
/* if we are connected */
|
||||
if (This->pAlloc)
|
||||
{
|
||||
WaitForSingleObject(This->hEventStateChanged, INFINITE);
|
||||
EnterCriticalSection(This->pin.pCritSec);
|
||||
if (This->state == State_Stopped)
|
||||
{
|
||||
DWORD dwThreadId;
|
||||
assert(!This->hThread);
|
||||
|
||||
|
||||
/* AddRef the filter to make sure it and it's pins will be around
|
||||
* as long as the thread */
|
||||
IBaseFilter_AddRef(This->pin.pinInfo.pFilter);
|
||||
|
@ -1451,8 +1473,13 @@ HRESULT PullPin_InitProcessing(PullPin * This)
|
|||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = IMemAllocator_Commit(This->pAlloc);
|
||||
This->state = State_Paused;
|
||||
SetEvent(This->hEventStateChanged);
|
||||
}
|
||||
}
|
||||
else assert(This->hThread);
|
||||
LeaveCriticalSection(This->pin.pCritSec);
|
||||
}
|
||||
|
||||
|
@ -1468,8 +1495,10 @@ HRESULT PullPin_StartProcessing(PullPin * This)
|
|||
if(This->pAlloc)
|
||||
{
|
||||
assert(This->hThread);
|
||||
|
||||
|
||||
PullPin_WaitForStateChange(This, INFINITE);
|
||||
ResetEvent(This->hEventStateChanged);
|
||||
This->stop_playback = 0;
|
||||
|
||||
if (!QueueUserAPC(PullPin_Thread_Process, This->hThread, (ULONG_PTR)This))
|
||||
return HRESULT_FROM_WIN32(GetLastError());
|
||||
|
@ -1480,8 +1509,21 @@ HRESULT PullPin_StartProcessing(PullPin * This)
|
|||
|
||||
HRESULT PullPin_PauseProcessing(PullPin * This)
|
||||
{
|
||||
/* make the processing function exit its loop */
|
||||
This->rtStop = 0;
|
||||
/* if we are connected */
|
||||
TRACE("(%p)->()\n", This);
|
||||
if(This->pAlloc)
|
||||
{
|
||||
assert(This->hThread);
|
||||
|
||||
PullPin_WaitForStateChange(This, INFINITE);
|
||||
EnterCriticalSection(This->pin.pCritSec);
|
||||
This->stop_playback = 0;
|
||||
LeaveCriticalSection(This->pin.pCritSec);
|
||||
ResetEvent(This->hEventStateChanged);
|
||||
|
||||
if (!QueueUserAPC(PullPin_Thread_Pause, This->hThread, (ULONG_PTR)This))
|
||||
return HRESULT_FROM_WIN32(GetLastError());
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
@ -1489,14 +1531,13 @@ HRESULT PullPin_PauseProcessing(PullPin * This)
|
|||
HRESULT PullPin_StopProcessing(PullPin * This)
|
||||
{
|
||||
/* if we are connected */
|
||||
if (This->pAlloc)
|
||||
if (This->pAlloc && This->hThread)
|
||||
{
|
||||
assert(This->hThread);
|
||||
PullPin_WaitForStateChange(This, INFINITE);
|
||||
|
||||
This->stop_playback = 0;
|
||||
ResetEvent(This->hEventStateChanged);
|
||||
|
||||
PullPin_PauseProcessing(This);
|
||||
|
||||
if (!QueueUserAPC(PullPin_Thread_Stop, This->hThread, (ULONG_PTR)This))
|
||||
return HRESULT_FROM_WIN32(GetLastError());
|
||||
}
|
||||
|
@ -1511,19 +1552,6 @@ HRESULT PullPin_WaitForStateChange(PullPin * This, DWORD dwMilliseconds)
|
|||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT PullPin_Seek(PullPin * This, REFERENCE_TIME rtStart, REFERENCE_TIME rtStop)
|
||||
{
|
||||
FIXME("(%p)->(%x%08x, %x%08x)\n", This, (LONG)(rtStart >> 32), (LONG)rtStart, (LONG)(rtStop >> 32), (LONG)rtStop);
|
||||
|
||||
PullPin_BeginFlush((IPin *)This);
|
||||
/* FIXME: need critical section? */
|
||||
This->rtStart = rtStart;
|
||||
This->rtStop = rtStop;
|
||||
PullPin_EndFlush((IPin *)This);
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT WINAPI PullPin_EndOfStream(IPin * iface)
|
||||
{
|
||||
FIXME("(%p)->() stub\n", iface);
|
||||
|
@ -1533,23 +1561,37 @@ HRESULT WINAPI PullPin_EndOfStream(IPin * iface)
|
|||
|
||||
HRESULT WINAPI PullPin_BeginFlush(IPin * iface)
|
||||
{
|
||||
PullPin *This = (PullPin *)iface;
|
||||
FIXME("(%p)->() stub\n", iface);
|
||||
|
||||
return SendFurther( iface, deliver_beginflush, NULL, NULL );
|
||||
SendFurther( iface, deliver_beginflush, NULL, NULL );
|
||||
|
||||
if (This->state == State_Running)
|
||||
return PullPin_PauseProcessing(This);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT WINAPI PullPin_EndFlush(IPin * iface)
|
||||
{
|
||||
FIXME("(%p)->() stub\n", iface);
|
||||
FILTER_STATE state;
|
||||
PullPin *This = (PullPin *)iface;
|
||||
|
||||
return SendFurther( iface, deliver_endflush, NULL, NULL );
|
||||
FIXME("(%p)->() stub\n", iface);
|
||||
SendFurther( iface, deliver_endflush, NULL, NULL );
|
||||
|
||||
return IBaseFilter_GetState(This->pin.pinInfo.pFilter, INFINITE, &state);
|
||||
}
|
||||
|
||||
HRESULT WINAPI PullPin_NewSegment(IPin * iface, REFERENCE_TIME tStart, REFERENCE_TIME tStop, double dRate)
|
||||
{
|
||||
newsegmentargs args;
|
||||
FIXME("(%p)->(%s, %s, %g) stub\n", iface, wine_dbgstr_longlong(tStart), wine_dbgstr_longlong(tStop), dRate);
|
||||
|
||||
return SendFurther( iface, deliver_newsegment, NULL, NULL );
|
||||
args.tStart = tStart;
|
||||
args.tStop = tStop;
|
||||
args.rate = dRate;
|
||||
|
||||
return SendFurther( iface, deliver_newsegment, &args, NULL );
|
||||
}
|
||||
|
||||
static const IPinVtbl PullPin_Vtbl =
|
||||
|
|
|
@ -85,6 +85,9 @@ typedef struct PullPin
|
|||
REFERENCE_TIME rtStart;
|
||||
REFERENCE_TIME rtStop;
|
||||
REFERENCE_TIME rtCurrent;
|
||||
FILTER_STATE state;
|
||||
BOOL stop_playback;
|
||||
double dRate;
|
||||
} PullPin;
|
||||
|
||||
/*** Initializers ***/
|
||||
|
@ -161,7 +164,6 @@ HRESULT PullPin_InitProcessing(PullPin * This);
|
|||
HRESULT PullPin_StartProcessing(PullPin * This);
|
||||
HRESULT PullPin_StopProcessing(PullPin * This);
|
||||
HRESULT PullPin_PauseProcessing(PullPin * This);
|
||||
HRESULT PullPin_Seek(PullPin * This, REFERENCE_TIME rtStart, REFERENCE_TIME rtStop);
|
||||
HRESULT WINAPI PullPin_EndOfStream(IPin * iface);
|
||||
HRESULT WINAPI PullPin_BeginFlush(IPin * iface);
|
||||
HRESULT WINAPI PullPin_EndFlush(IPin * iface);
|
||||
|
|
|
@ -58,6 +58,17 @@ static void rungraph(void)
|
|||
hr = IMediaControl_Run(pmc);
|
||||
ok(hr==S_FALSE, "Cannot run the graph returned: %x\n", hr);
|
||||
|
||||
Sleep(100);
|
||||
/* Crash fun */
|
||||
hr = IMediaControl_Stop(pmc);
|
||||
ok(hr==S_OK || hr == S_FALSE, "Cannot stop the graph returned: %x\n", hr);
|
||||
hr = IMediaControl_Run(pmc);
|
||||
ok(hr==S_OK || hr == S_FALSE, "Cannot start the graph returned: %x\n", hr);
|
||||
hr = IMediaControl_Pause(pmc);
|
||||
ok(hr==S_OK || hr == S_FALSE, "Cannot pause the graph returned: %x\n", hr);
|
||||
hr = IMediaControl_Run(pmc);
|
||||
ok(hr==S_OK || hr == S_FALSE, "Cannot start the graph returned: %x\n", hr);
|
||||
|
||||
hr = IGraphBuilder_QueryInterface(pgraph, &IID_IMediaEvent, (LPVOID*)&pme);
|
||||
ok(hr==S_OK, "Cannot get IMediaEvent interface returned: %x\n", hr);
|
||||
|
||||
|
|
Loading…
Reference in New Issue