quartz: Fix deadlock with transform filter.
This commit is contained in:
parent
ecc7b5fb18
commit
992fb02c73
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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))
|
||||||
{
|
{
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue