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;
HRESULT hr;
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);
if (FAILED(hr))
{
ERR("Cannot get pointer to sample data (%x)\n", hr);
return hr;
LeaveCriticalSection(&pTransformFilter->csFilter);
return hr;
}
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);
hr = IPin_ConnectionMediaType(This->tf.ppPins[0], &amt);
if (FAILED(hr)) {
ERR("Unable to retrieve media type\n");
return hr;
if (FAILED(hr))
{
ERR("Unable to retrieve media type\n");
LeaveCriticalSection(&pTransformFilter->csFilter);
return hr;
}
ash.pbSrc = pbSrcStream;
@ -104,12 +121,14 @@ static HRESULT ACMWrapper_ProcessSampleData(TransformFilterImpl* pTransformFilte
while(hr == S_OK && ash.cbSrcLength)
{
hr = OutputPin_GetDeliveryBuffer((OutputPin*)This->tf.ppPins[1], &pOutSample, NULL, NULL, 0);
if (FAILED(hr)) {
ERR("Unable to get delivery buffer (%x)\n", hr);
return hr;
}
IMediaSample_SetPreroll(pOutSample, preroll);
hr = OutputPin_GetDeliveryBuffer((OutputPin*)This->tf.ppPins[1], &pOutSample, NULL, NULL, 0);
if (FAILED(hr))
{
ERR("Unable to get delivery buffer (%x)\n", hr);
LeaveCriticalSection(&pTransformFilter->csFilter);
return hr;
}
IMediaSample_SetPreroll(pOutSample, preroll);
hr = IMediaSample_SetActualDataLength(pOutSample, 0);
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));
LeaveCriticalSection(&This->tf.csFilter);
hr = OutputPin_SendSample((OutputPin*)This->tf.ppPins[1], pOutSample);
EnterCriticalSection(&This->tf.csFilter);
if (hr != S_OK && hr != VFW_E_NOT_CONNECTED) {
if (FAILED(hr))
@ -210,6 +231,7 @@ error:
This->lasttime_real = tStop;
This->lasttime_sent = tMed;
LeaveCriticalSection(&pTransformFilter->csFilter);
return hr;
}

View File

@ -80,12 +80,26 @@ static HRESULT AVIDec_ProcessSampleData(TransformFilterImpl* pTransformFilter, I
DWORD cbSrcStream;
LPBYTE pbSrcStream;
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);
if (FAILED(hr))
{
ERR("Cannot get pointer to sample data (%x)\n", hr);
return hr;
goto error;
}
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);
if (FAILED(hr)) {
ERR("Unable to get delivery buffer (%x)\n", hr);
goto error;
ERR("Unable to get delivery buffer (%x)\n", hr);
goto error;
}
hr = IMediaSample_SetActualDataLength(pOutSample, 0);
@ -137,16 +151,18 @@ static HRESULT AVIDec_ProcessSampleData(TransformFilterImpl* pTransformFilter, I
else
IMediaSample_SetTime(pOutSample, NULL, NULL);
LeaveCriticalSection(&This->tf.csFilter);
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);
goto error;
}
IMediaSample_Release(pOutSample);
return hr;
error:
if (pOutSample)
IMediaSample_Release(pOutSample);
LeaveCriticalSection(&This->tf.csFilter);
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
*/
EnterCriticalSection(&This->csFilter);
if (This->pInputPin->end_of_stream || This->pInputPin->flushing)
{
LeaveCriticalSection(&This->csFilter);
return S_FALSE;
}
if (This->state == State_Stopped)
{
LeaveCriticalSection(&This->csFilter);
return VFW_E_WRONG_STATE;
}
SetEvent(This->state_change);
@ -279,11 +290,15 @@ static HRESULT DSoundRender_Sample(LPVOID iface, IMediaSample * pSample)
WaitForSingleObject(This->blocked, INFINITE);
EnterCriticalSection(&This->csFilter);
if (This->state == State_Stopped)
{
LeaveCriticalSection(&This->csFilter);
return VFW_E_WRONG_STATE;
}
if (This->state == State_Paused)
{
/* Assuming we return because of flushing */
LeaveCriticalSection(&This->csFilter);
return S_OK;
}
}
@ -304,7 +319,9 @@ static HRESULT DSoundRender_Sample(LPVOID iface, IMediaSample * pSample)
}
#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)

View File

@ -82,29 +82,17 @@ static const IMemInputPinVtbl MemInputPin_Vtbl =
static HRESULT NullRenderer_Sample(LPVOID iface, IMediaSample * pSample)
{
LPBYTE pbSrcStream = NULL;
long cbSrcStream = 0;
REFERENCE_TIME tStart, tStop;
HRESULT hr;
NullRendererImpl *This = (NullRendererImpl *)iface;
HRESULT hr = S_OK;
TRACE("%p %p\n", iface, pSample);
hr = IMediaSample_GetPointer(pSample, &pbSrcStream);
if (FAILED(hr))
{
ERR("Cannot get pointer to sample data (%x)\n", hr);
return hr;
}
EnterCriticalSection(&This->csFilter);
if (This->pInputPin->flushing || This->pInputPin->end_of_stream)
hr = S_FALSE;
LeaveCriticalSection(&This->csFilter);
hr = IMediaSample_GetTime(pSample, &tStart, &tStop);
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;
return hr;
}
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 */
/*TRACE("(%p/%p)->(%p)\n", This, iface, 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);
hr = This->fnSampleProc(This->pin.pUserData, pSample);
return hr;
}

View File

@ -48,18 +48,6 @@ static const IPinVtbl TransformFilter_InputPin_Vtbl;
static const IMemInputPinVtbl MemInputPin_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)
{
TransformFilterImpl* This = (TransformFilterImpl*)iface;
@ -187,7 +175,7 @@ HRESULT TransformFilter_Create(TransformFilterImpl* pTransformFilter, const CLSI
piOutput.pFilter = (IBaseFilter *)pTransformFilter;
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))
{

View File

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