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