quartz: Fix deadlock with transform filter.

This commit is contained in:
Maarten Lankhorst 2008-07-04 16:59:22 -07:00 committed by Alexandre Julliard
parent ecc7b5fb18
commit 992fb02c73
7 changed files with 97 additions and 56 deletions

View File

@ -65,12 +65,27 @@ static HRESULT ACMWrapper_ProcessSampleData(TransformFilterImpl* pTransformFilte
MMRESULT res; MMRESULT res;
HRESULT hr; HRESULT hr;
LONGLONG tStart = -1, tStop = -1, tMed; LONGLONG tStart = -1, tStop = -1, tMed;
InputPin *pin = (InputPin *)pTransformFilter->ppPins[0];
EnterCriticalSection(&pTransformFilter->csFilter);
if (pTransformFilter->state == State_Stopped)
{
LeaveCriticalSection(&pTransformFilter->csFilter);
return VFW_E_WRONG_STATE;
}
if (pin->end_of_stream || pin->flushing)
{
LeaveCriticalSection(&pTransformFilter->csFilter);
return S_FALSE;
}
hr = IMediaSample_GetPointer(pSample, &pbSrcStream); hr = IMediaSample_GetPointer(pSample, &pbSrcStream);
if (FAILED(hr)) if (FAILED(hr))
{ {
ERR("Cannot get pointer to sample data (%x)\n", hr); ERR("Cannot get pointer to sample data (%x)\n", hr);
return hr; LeaveCriticalSection(&pTransformFilter->csFilter);
return hr;
} }
preroll = (IMediaSample_IsPreroll(pSample) == S_OK); preroll = (IMediaSample_IsPreroll(pSample) == S_OK);
@ -94,9 +109,11 @@ static HRESULT ACMWrapper_ProcessSampleData(TransformFilterImpl* pTransformFilte
TRACE("Sample data ptr = %p, size = %ld\n", pbSrcStream, (long)cbSrcStream); TRACE("Sample data ptr = %p, size = %ld\n", pbSrcStream, (long)cbSrcStream);
hr = IPin_ConnectionMediaType(This->tf.ppPins[0], &amt); hr = IPin_ConnectionMediaType(This->tf.ppPins[0], &amt);
if (FAILED(hr)) { if (FAILED(hr))
ERR("Unable to retrieve media type\n"); {
return hr; ERR("Unable to retrieve media type\n");
LeaveCriticalSection(&pTransformFilter->csFilter);
return hr;
} }
ash.pbSrc = pbSrcStream; ash.pbSrc = pbSrcStream;
@ -104,12 +121,14 @@ static HRESULT ACMWrapper_ProcessSampleData(TransformFilterImpl* pTransformFilte
while(hr == S_OK && ash.cbSrcLength) while(hr == S_OK && ash.cbSrcLength)
{ {
hr = OutputPin_GetDeliveryBuffer((OutputPin*)This->tf.ppPins[1], &pOutSample, NULL, NULL, 0); hr = OutputPin_GetDeliveryBuffer((OutputPin*)This->tf.ppPins[1], &pOutSample, NULL, NULL, 0);
if (FAILED(hr)) { if (FAILED(hr))
ERR("Unable to get delivery buffer (%x)\n", hr); {
return hr; ERR("Unable to get delivery buffer (%x)\n", hr);
} LeaveCriticalSection(&pTransformFilter->csFilter);
IMediaSample_SetPreroll(pOutSample, preroll); return hr;
}
IMediaSample_SetPreroll(pOutSample, preroll);
hr = IMediaSample_SetActualDataLength(pOutSample, 0); hr = IMediaSample_SetActualDataLength(pOutSample, 0);
assert(hr == S_OK); assert(hr == S_OK);
@ -186,7 +205,9 @@ static HRESULT ACMWrapper_ProcessSampleData(TransformFilterImpl* pTransformFilte
} }
TRACE("Sample stop time: %u.%03u\n", (DWORD)(tStart/10000000), (DWORD)((tStart/10000)%1000)); TRACE("Sample stop time: %u.%03u\n", (DWORD)(tStart/10000000), (DWORD)((tStart/10000)%1000));
LeaveCriticalSection(&This->tf.csFilter);
hr = OutputPin_SendSample((OutputPin*)This->tf.ppPins[1], pOutSample); hr = OutputPin_SendSample((OutputPin*)This->tf.ppPins[1], pOutSample);
EnterCriticalSection(&This->tf.csFilter);
if (hr != S_OK && hr != VFW_E_NOT_CONNECTED) { if (hr != S_OK && hr != VFW_E_NOT_CONNECTED) {
if (FAILED(hr)) if (FAILED(hr))
@ -210,6 +231,7 @@ error:
This->lasttime_real = tStop; This->lasttime_real = tStop;
This->lasttime_sent = tMed; This->lasttime_sent = tMed;
LeaveCriticalSection(&pTransformFilter->csFilter);
return hr; return hr;
} }

View File

@ -80,12 +80,26 @@ static HRESULT AVIDec_ProcessSampleData(TransformFilterImpl* pTransformFilter, I
DWORD cbSrcStream; DWORD cbSrcStream;
LPBYTE pbSrcStream; LPBYTE pbSrcStream;
LONGLONG tStart, tStop; LONGLONG tStart, tStop;
InputPin *pin = (InputPin *)pTransformFilter->ppPins[0];
EnterCriticalSection(&This->tf.csFilter);
if (This->tf.state == State_Stopped)
{
LeaveCriticalSection(&This->tf.csFilter);
return VFW_E_WRONG_STATE;
}
if (pin->end_of_stream || pin->flushing)
{
LeaveCriticalSection(&This->tf.csFilter);
return S_FALSE;
}
hr = IMediaSample_GetPointer(pSample, &pbSrcStream); hr = IMediaSample_GetPointer(pSample, &pbSrcStream);
if (FAILED(hr)) if (FAILED(hr))
{ {
ERR("Cannot get pointer to sample data (%x)\n", hr); ERR("Cannot get pointer to sample data (%x)\n", hr);
return hr; goto error;
} }
cbSrcStream = IMediaSample_GetActualDataLength(pSample); cbSrcStream = IMediaSample_GetActualDataLength(pSample);
@ -103,8 +117,8 @@ static HRESULT AVIDec_ProcessSampleData(TransformFilterImpl* pTransformFilter, I
hr = OutputPin_GetDeliveryBuffer((OutputPin*)This->tf.ppPins[1], &pOutSample, NULL, NULL, 0); hr = OutputPin_GetDeliveryBuffer((OutputPin*)This->tf.ppPins[1], &pOutSample, NULL, NULL, 0);
if (FAILED(hr)) { if (FAILED(hr)) {
ERR("Unable to get delivery buffer (%x)\n", hr); ERR("Unable to get delivery buffer (%x)\n", hr);
goto error; goto error;
} }
hr = IMediaSample_SetActualDataLength(pOutSample, 0); hr = IMediaSample_SetActualDataLength(pOutSample, 0);
@ -137,16 +151,18 @@ static HRESULT AVIDec_ProcessSampleData(TransformFilterImpl* pTransformFilter, I
else else
IMediaSample_SetTime(pOutSample, NULL, NULL); IMediaSample_SetTime(pOutSample, NULL, NULL);
LeaveCriticalSection(&This->tf.csFilter);
hr = OutputPin_SendSample((OutputPin*)This->tf.ppPins[1], pOutSample); hr = OutputPin_SendSample((OutputPin*)This->tf.ppPins[1], pOutSample);
if (hr != S_OK && hr != VFW_E_NOT_CONNECTED) { if (hr != S_OK && hr != VFW_E_NOT_CONNECTED)
ERR("Error sending sample (%x)\n", hr); ERR("Error sending sample (%x)\n", hr);
goto error; IMediaSample_Release(pOutSample);
} return hr;
error: error:
if (pOutSample) if (pOutSample)
IMediaSample_Release(pOutSample); IMediaSample_Release(pOutSample);
LeaveCriticalSection(&This->tf.csFilter);
return hr; return hr;
} }

View File

@ -245,8 +245,19 @@ static HRESULT DSoundRender_Sample(LPVOID iface, IMediaSample * pSample)
* pause completion here, but for sound playing a single frame doesn't make sense * pause completion here, but for sound playing a single frame doesn't make sense
*/ */
EnterCriticalSection(&This->csFilter);
if (This->pInputPin->end_of_stream || This->pInputPin->flushing)
{
LeaveCriticalSection(&This->csFilter);
return S_FALSE;
}
if (This->state == State_Stopped) if (This->state == State_Stopped)
{
LeaveCriticalSection(&This->csFilter);
return VFW_E_WRONG_STATE; return VFW_E_WRONG_STATE;
}
SetEvent(This->state_change); SetEvent(This->state_change);
@ -279,11 +290,15 @@ static HRESULT DSoundRender_Sample(LPVOID iface, IMediaSample * pSample)
WaitForSingleObject(This->blocked, INFINITE); WaitForSingleObject(This->blocked, INFINITE);
EnterCriticalSection(&This->csFilter); EnterCriticalSection(&This->csFilter);
if (This->state == State_Stopped) if (This->state == State_Stopped)
{
LeaveCriticalSection(&This->csFilter);
return VFW_E_WRONG_STATE; return VFW_E_WRONG_STATE;
}
if (This->state == State_Paused) if (This->state == State_Paused)
{ {
/* Assuming we return because of flushing */ /* Assuming we return because of flushing */
LeaveCriticalSection(&This->csFilter);
return S_OK; return S_OK;
} }
} }
@ -304,7 +319,9 @@ static HRESULT DSoundRender_Sample(LPVOID iface, IMediaSample * pSample)
} }
#endif #endif
return DSoundRender_SendSampleData(This, pbSrcStream, cbSrcStream); hr = DSoundRender_SendSampleData(This, pbSrcStream, cbSrcStream);
LeaveCriticalSection(&This->csFilter);
return hr;
} }
static HRESULT DSoundRender_QueryAccept(LPVOID iface, const AM_MEDIA_TYPE * pmt) static HRESULT DSoundRender_QueryAccept(LPVOID iface, const AM_MEDIA_TYPE * pmt)

View File

@ -82,29 +82,17 @@ static const IMemInputPinVtbl MemInputPin_Vtbl =
static HRESULT NullRenderer_Sample(LPVOID iface, IMediaSample * pSample) static HRESULT NullRenderer_Sample(LPVOID iface, IMediaSample * pSample)
{ {
LPBYTE pbSrcStream = NULL; NullRendererImpl *This = (NullRendererImpl *)iface;
long cbSrcStream = 0; HRESULT hr = S_OK;
REFERENCE_TIME tStart, tStop;
HRESULT hr;
TRACE("%p %p\n", iface, pSample); TRACE("%p %p\n", iface, pSample);
hr = IMediaSample_GetPointer(pSample, &pbSrcStream); EnterCriticalSection(&This->csFilter);
if (FAILED(hr)) if (This->pInputPin->flushing || This->pInputPin->end_of_stream)
{ hr = S_FALSE;
ERR("Cannot get pointer to sample data (%x)\n", hr); LeaveCriticalSection(&This->csFilter);
return hr;
}
hr = IMediaSample_GetTime(pSample, &tStart, &tStop); return hr;
if (FAILED(hr))
ERR("Cannot get sample time (%x)\n", hr);
cbSrcStream = IMediaSample_GetActualDataLength(pSample);
TRACE("val %p %ld\n", pbSrcStream, cbSrcStream);
return S_OK;
} }
static HRESULT NullRenderer_QueryAccept(LPVOID iface, const AM_MEDIA_TYPE * pmt) static HRESULT NullRenderer_QueryAccept(LPVOID iface, const AM_MEDIA_TYPE * pmt)

View File

@ -803,13 +803,7 @@ HRESULT WINAPI MemInputPin_Receive(IMemInputPin * iface, IMediaSample * pSample)
/* this trace commented out for performance reasons */ /* this trace commented out for performance reasons */
/*TRACE("(%p/%p)->(%p)\n", This, iface, pSample);*/ /*TRACE("(%p/%p)->(%p)\n", This, iface, pSample);*/
hr = This->fnSampleProc(This->pin.pUserData, pSample);
EnterCriticalSection(This->pin.pCritSec);
if (!This->end_of_stream && !This->flushing)
hr = This->fnSampleProc(This->pin.pUserData, pSample);
else
hr = S_FALSE;
LeaveCriticalSection(This->pin.pCritSec);
return hr; return hr;
} }

View File

@ -48,18 +48,6 @@ static const IPinVtbl TransformFilter_InputPin_Vtbl;
static const IMemInputPinVtbl MemInputPin_Vtbl; static const IMemInputPinVtbl MemInputPin_Vtbl;
static const IPinVtbl TransformFilter_OutputPin_Vtbl; static const IPinVtbl TransformFilter_OutputPin_Vtbl;
static HRESULT TransformFilter_Sample(LPVOID iface, IMediaSample * pSample)
{
TransformFilterImpl *This = (TransformFilterImpl *)iface;
TRACE("%p %p\n", iface, pSample);
if (This->state == State_Stopped)
return S_FALSE;
return This->pFuncsTable->pfnProcessSampleData(This, pSample);
}
static HRESULT TransformFilter_Input_QueryAccept(LPVOID iface, const AM_MEDIA_TYPE * pmt) static HRESULT TransformFilter_Input_QueryAccept(LPVOID iface, const AM_MEDIA_TYPE * pmt)
{ {
TransformFilterImpl* This = (TransformFilterImpl*)iface; TransformFilterImpl* This = (TransformFilterImpl*)iface;
@ -187,7 +175,7 @@ HRESULT TransformFilter_Create(TransformFilterImpl* pTransformFilter, const CLSI
piOutput.pFilter = (IBaseFilter *)pTransformFilter; piOutput.pFilter = (IBaseFilter *)pTransformFilter;
lstrcpynW(piOutput.achName, wcsOutputPinName, sizeof(piOutput.achName) / sizeof(piOutput.achName[0])); lstrcpynW(piOutput.achName, wcsOutputPinName, sizeof(piOutput.achName) / sizeof(piOutput.achName[0]));
hr = InputPin_Construct(&TransformFilter_InputPin_Vtbl, &piInput, TransformFilter_Sample, pTransformFilter, TransformFilter_Input_QueryAccept, NULL, &pTransformFilter->csFilter, NULL, &pTransformFilter->ppPins[0]); hr = InputPin_Construct(&TransformFilter_InputPin_Vtbl, &piInput, (SAMPLEPROC_PUSH)pFuncsTable->pfnProcessSampleData, pTransformFilter, TransformFilter_Input_QueryAccept, NULL, &pTransformFilter->csFilter, NULL, &pTransformFilter->ppPins[0]);
if (SUCCEEDED(hr)) if (SUCCEEDED(hr))
{ {

View File

@ -362,9 +362,15 @@ static HRESULT VideoRenderer_Sample(LPVOID iface, IMediaSample * pSample)
long cbSrcStream = 0; long cbSrcStream = 0;
REFERENCE_TIME tStart, tStop; REFERENCE_TIME tStart, tStop;
HRESULT hr; HRESULT hr;
EnterCriticalSection(&This->csFilter);
if (This->pInputPin->flushing || This->pInputPin->end_of_stream)
hr = S_FALSE;
if (This->state == State_Stopped) if (This->state == State_Stopped)
{
LeaveCriticalSection(&This->csFilter);
return VFW_E_WRONG_STATE; return VFW_E_WRONG_STATE;
}
TRACE("%p %p\n", iface, pSample); TRACE("%p %p\n", iface, pSample);
@ -386,6 +392,7 @@ static HRESULT VideoRenderer_Sample(LPVOID iface, IMediaSample * pSample)
if (IMediaSample_IsPreroll(pSample) == S_OK) if (IMediaSample_IsPreroll(pSample) == S_OK)
{ {
This->rtLastStop = tStop; This->rtLastStop = tStop;
LeaveCriticalSection(&This->csFilter);
return S_OK; return S_OK;
} }
@ -393,6 +400,7 @@ static HRESULT VideoRenderer_Sample(LPVOID iface, IMediaSample * pSample)
if (FAILED(hr)) if (FAILED(hr))
{ {
ERR("Cannot get pointer to sample data (%x)\n", hr); ERR("Cannot get pointer to sample data (%x)\n", hr);
LeaveCriticalSection(&This->csFilter);
return hr; return hr;
} }
@ -422,10 +430,16 @@ static HRESULT VideoRenderer_Sample(LPVOID iface, IMediaSample * pSample)
EnterCriticalSection(&This->csFilter); EnterCriticalSection(&This->csFilter);
This->sample_held = NULL; This->sample_held = NULL;
if (This->state == State_Paused) if (This->state == State_Paused)
{
/* Flushing */ /* Flushing */
LeaveCriticalSection(&This->csFilter);
return S_OK; return S_OK;
}
if (This->state == State_Stopped) if (This->state == State_Stopped)
{
LeaveCriticalSection(&This->csFilter);
return VFW_E_WRONG_STATE; return VFW_E_WRONG_STATE;
}
} }
if (This->pClock && This->state == State_Running) if (This->pClock && This->state == State_Running)
@ -456,6 +470,7 @@ static HRESULT VideoRenderer_Sample(LPVOID iface, IMediaSample * pSample)
(DWORD)(time / 10000000), (DWORD)((time / 10000)%1000), (DWORD)(time / 10000000), (DWORD)((time / 10000)%1000),
(DWORD)(trefstop / 10000000), (DWORD)((trefstop / 10000)%1000) ); (DWORD)(trefstop / 10000000), (DWORD)((trefstop / 10000)%1000) );
This->rtLastStop = tStop; This->rtLastStop = tStop;
LeaveCriticalSection(&This->csFilter);
return S_OK; return S_OK;
} }
} }
@ -463,6 +478,7 @@ static HRESULT VideoRenderer_Sample(LPVOID iface, IMediaSample * pSample)
VideoRenderer_SendSampleData(This, pbSrcStream, cbSrcStream); VideoRenderer_SendSampleData(This, pbSrcStream, cbSrcStream);
LeaveCriticalSection(&This->csFilter);
return S_OK; return S_OK;
} }