Signed-off-by: Zebediah Figura z.figura12@gmail.com --- The goal is essentially to get rid of BaseOutputPinImpl_Deliver(). This function is mostly a wrapper around IMemInputPin::Receive(), but which also takes the filter lock while checking if the pin is connected.
This is not particularly necessary, according to DirectShow conventions: a filter should only receive data while the graph is running, and pins cannot be connected or disconnected while the graph is running. Even in the case of dynamic reconnection, the DirectX SDK documentation specifies that the upstream filter should be manually prevented (or prevent itself) from delivering samples.
Besides this, taking the filter lock in the streaming thread can lead to temporary or permanent deadlock. We currently wait in IMediaFilter::GetState() while holding the filter lock, and the SDK documentation states that methods such as IMediaFilter::Stop() and IPin::BeginFlush() should hold the filter lock while waiting for the streaming thread to complete. One can conclude from this that the filter lock should never be taken from the streaming thread.
dlls/strmbase/transform.c | 10 ++++++++++ 1 file changed, 10 insertions(+)
diff --git a/dlls/strmbase/transform.c b/dlls/strmbase/transform.c index e7d4d66164..29c385793a 100644 --- a/dlls/strmbase/transform.c +++ b/dlls/strmbase/transform.c @@ -59,6 +59,16 @@ static HRESULT WINAPI TransformFilter_Input_Receive(struct strmbase_sink *This,
TRACE("%p\n", This);
+ /* We do not expect pin connection state to change while the filter is + * running. This guarantee is necessary, since otherwise we would have to + * take the filter lock, and we can't take the filter lock from a streaming + * thread. */ + if (!pTransform->source.pMemInputPin) + { + WARN("Source is not connected, returning VFW_E_NOT_CONNECTED.\n"); + return VFW_E_NOT_CONNECTED; + } + EnterCriticalSection(&pTransform->csReceive); if (pTransform->filter.state == State_Stopped) {