From: Rémi Bernon rbernon@codeweavers.com
--- dlls/mf/async_transform.c | 197 +++++++++++++++++++++++++++++++++----- dlls/mf/session.c | 24 ++++- 2 files changed, 192 insertions(+), 29 deletions(-)
diff --git a/dlls/mf/async_transform.c b/dlls/mf/async_transform.c index 13ea6f26760..db8c299c0a0 100644 --- a/dlls/mf/async_transform.c +++ b/dlls/mf/async_transform.c @@ -30,6 +30,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(mfplat); struct async_transform { IMFTransform IMFTransform_iface; + IMFShutdown IMFShutdown_iface; LONG refcount;
CRITICAL_SECTION cs; @@ -50,6 +51,8 @@ static HRESULT WINAPI transform_QueryInterface(IMFTransform *iface, REFIID iid, if (IsEqualGUID(iid, &IID_IUnknown) || IsEqualGUID(iid, &IID_IMFTransform)) *out = &impl->IMFTransform_iface; + else if (IsEqualGUID(iid, &IID_IMFShutdown)) + *out = &impl->IMFShutdown_iface; else { *out = NULL; @@ -78,7 +81,7 @@ static ULONG WINAPI transform_Release(IMFTransform *iface)
if (!refcount) { - IMFTransform_Release(impl->transform); + IMFShutdown_Shutdown(&impl->IMFShutdown_iface); impl->cs.DebugInfo->Spare[0] = 0; DeleteCriticalSection(&impl->cs); free(impl); @@ -97,7 +100,10 @@ static HRESULT WINAPI transform_GetStreamLimits(IMFTransform *iface, DWORD *inpu iface, input_minimum, input_maximum, output_minimum, output_maximum);
EnterCriticalSection(&impl->cs); - hr = IMFTransform_GetStreamLimits(impl->transform, input_minimum, input_maximum, output_minimum, output_maximum); + if (!impl->transform) + hr = MF_E_SHUTDOWN; + else + hr = IMFTransform_GetStreamLimits(impl->transform, input_minimum, input_maximum, output_minimum, output_maximum); LeaveCriticalSection(&impl->cs); return hr; } @@ -110,7 +116,10 @@ static HRESULT WINAPI transform_GetStreamCount(IMFTransform *iface, DWORD *input TRACE("iface %p, inputs %p, outputs %p.\n", iface, inputs, outputs);
EnterCriticalSection(&impl->cs); - hr = IMFTransform_GetStreamCount(impl->transform, inputs, outputs); + if (!impl->transform) + hr = MF_E_SHUTDOWN; + else + hr = IMFTransform_GetStreamCount(impl->transform, inputs, outputs); LeaveCriticalSection(&impl->cs); return hr; } @@ -125,7 +134,10 @@ static HRESULT WINAPI transform_GetStreamIDs(IMFTransform *iface, DWORD input_si input_size, inputs, output_size, outputs);
EnterCriticalSection(&impl->cs); - hr = IMFTransform_GetStreamIDs(impl->transform, input_size, inputs, output_size, outputs); + if (!impl->transform) + hr = MF_E_SHUTDOWN; + else + hr = IMFTransform_GetStreamIDs(impl->transform, input_size, inputs, output_size, outputs); LeaveCriticalSection(&impl->cs); return hr; } @@ -138,7 +150,10 @@ static HRESULT WINAPI transform_GetInputStreamInfo(IMFTransform *iface, DWORD id TRACE("iface %p, id %#lx, info %p.\n", iface, id, info);
EnterCriticalSection(&impl->cs); - hr = IMFTransform_GetInputStreamInfo(impl->transform, id, info); + if (!impl->transform) + hr = MF_E_SHUTDOWN; + else + hr = IMFTransform_GetInputStreamInfo(impl->transform, id, info); LeaveCriticalSection(&impl->cs); return hr; } @@ -151,7 +166,10 @@ static HRESULT WINAPI transform_GetOutputStreamInfo(IMFTransform *iface, DWORD i TRACE("iface %p, id %#lx, info %p.\n", iface, id, info);
EnterCriticalSection(&impl->cs); - hr = IMFTransform_GetOutputStreamInfo(impl->transform, id, info); + if (!impl->transform) + hr = MF_E_SHUTDOWN; + else + hr = IMFTransform_GetOutputStreamInfo(impl->transform, id, info); LeaveCriticalSection(&impl->cs); return hr; } @@ -164,7 +182,10 @@ static HRESULT WINAPI transform_GetAttributes(IMFTransform *iface, IMFAttributes TRACE("iface %p, attributes %p.\n", iface, attributes);
EnterCriticalSection(&impl->cs); - hr = IMFTransform_GetAttributes(impl->transform, attributes); + if (!impl->transform) + hr = MF_E_SHUTDOWN; + else + hr = IMFTransform_GetAttributes(impl->transform, attributes); LeaveCriticalSection(&impl->cs); return hr; } @@ -177,7 +198,10 @@ static HRESULT WINAPI transform_GetInputStreamAttributes(IMFTransform *iface, DW TRACE("iface %p, id %#lx, attributes %p.\n", iface, id, attributes);
EnterCriticalSection(&impl->cs); - hr = IMFTransform_GetInputStreamAttributes(impl->transform, id, attributes); + if (!impl->transform) + hr = MF_E_SHUTDOWN; + else + hr = IMFTransform_GetInputStreamAttributes(impl->transform, id, attributes); LeaveCriticalSection(&impl->cs); return hr; } @@ -190,7 +214,10 @@ static HRESULT WINAPI transform_GetOutputStreamAttributes(IMFTransform *iface, D TRACE("iface %p, id %#lx, attributes %p.\n", iface, id, attributes);
EnterCriticalSection(&impl->cs); - hr = IMFTransform_GetOutputStreamAttributes(impl->transform, id, attributes); + if (!impl->transform) + hr = MF_E_SHUTDOWN; + else + hr = IMFTransform_GetOutputStreamAttributes(impl->transform, id, attributes); LeaveCriticalSection(&impl->cs); return hr; } @@ -203,7 +230,10 @@ static HRESULT WINAPI transform_DeleteInputStream(IMFTransform *iface, DWORD id) TRACE("iface %p, id %#lx.\n", iface, id);
EnterCriticalSection(&impl->cs); - hr = IMFTransform_DeleteInputStream(impl->transform, id); + if (!impl->transform) + hr = MF_E_SHUTDOWN; + else + hr = IMFTransform_DeleteInputStream(impl->transform, id); LeaveCriticalSection(&impl->cs); return hr; } @@ -216,7 +246,10 @@ static HRESULT WINAPI transform_AddInputStreams(IMFTransform *iface, DWORD strea TRACE("iface %p, streams %lu, ids %p.\n", iface, streams, ids);
EnterCriticalSection(&impl->cs); - hr = IMFTransform_AddInputStreams(impl->transform, streams, ids); + if (!impl->transform) + hr = MF_E_SHUTDOWN; + else + hr = IMFTransform_AddInputStreams(impl->transform, streams, ids); LeaveCriticalSection(&impl->cs); return hr; } @@ -230,7 +263,10 @@ static HRESULT WINAPI transform_GetInputAvailableType(IMFTransform *iface, DWORD TRACE("iface %p, id %#lx, index %#lx, type %p.\n", iface, id, index, type);
EnterCriticalSection(&impl->cs); - hr = IMFTransform_GetInputAvailableType(impl->transform, id, index, type); + if (!impl->transform) + hr = MF_E_SHUTDOWN; + else + hr = IMFTransform_GetInputAvailableType(impl->transform, id, index, type); LeaveCriticalSection(&impl->cs); return hr; } @@ -244,7 +280,10 @@ static HRESULT WINAPI transform_GetOutputAvailableType(IMFTransform *iface, DWOR TRACE("iface %p, id %#lx, index %#lx, type %p.\n", iface, id, index, type);
EnterCriticalSection(&impl->cs); - hr = IMFTransform_GetOutputAvailableType(impl->transform, id, index, type); + if (!impl->transform) + hr = MF_E_SHUTDOWN; + else + hr = IMFTransform_GetOutputAvailableType(impl->transform, id, index, type); LeaveCriticalSection(&impl->cs); return hr; } @@ -257,7 +296,10 @@ static HRESULT WINAPI transform_SetInputType(IMFTransform *iface, DWORD id, IMFM TRACE("iface %p, id %#lx, type %p, flags %#lx.\n", iface, id, type, flags);
EnterCriticalSection(&impl->cs); - hr = IMFTransform_SetInputType(impl->transform, id, type, flags); + if (!impl->transform) + hr = MF_E_SHUTDOWN; + else + hr = IMFTransform_SetInputType(impl->transform, id, type, flags); LeaveCriticalSection(&impl->cs); return hr; } @@ -270,7 +312,10 @@ static HRESULT WINAPI transform_SetOutputType(IMFTransform *iface, DWORD id, IMF TRACE("iface %p, id %#lx, type %p, flags %#lx.\n", iface, id, type, flags);
EnterCriticalSection(&impl->cs); - hr = IMFTransform_SetOutputType(impl->transform, id, type, flags); + if (!impl->transform) + hr = MF_E_SHUTDOWN; + else + hr = IMFTransform_SetOutputType(impl->transform, id, type, flags); LeaveCriticalSection(&impl->cs); return hr; } @@ -283,7 +328,10 @@ static HRESULT WINAPI transform_GetInputCurrentType(IMFTransform *iface, DWORD i TRACE("iface %p, id %#lx, type %p.\n", iface, id, type);
EnterCriticalSection(&impl->cs); - hr = IMFTransform_GetInputCurrentType(impl->transform, id, type); + if (!impl->transform) + hr = MF_E_SHUTDOWN; + else + hr = IMFTransform_GetInputCurrentType(impl->transform, id, type); LeaveCriticalSection(&impl->cs); return hr; } @@ -296,7 +344,10 @@ static HRESULT WINAPI transform_GetOutputCurrentType(IMFTransform *iface, DWORD TRACE("iface %p, id %#lx, type %p.\n", iface, id, type);
EnterCriticalSection(&impl->cs); - hr = IMFTransform_GetOutputCurrentType(impl->transform, id, type); + if (!impl->transform) + hr = MF_E_SHUTDOWN; + else + hr = IMFTransform_GetOutputCurrentType(impl->transform, id, type); LeaveCriticalSection(&impl->cs); return hr; } @@ -309,7 +360,10 @@ static HRESULT WINAPI transform_GetInputStatus(IMFTransform *iface, DWORD id, DW TRACE("iface %p, id %#lx, flags %p.\n", iface, id, flags);
EnterCriticalSection(&impl->cs); - hr = IMFTransform_GetInputStatus(impl->transform, id, flags); + if (!impl->transform) + hr = MF_E_SHUTDOWN; + else + hr = IMFTransform_GetInputStatus(impl->transform, id, flags); LeaveCriticalSection(&impl->cs); return hr; } @@ -322,7 +376,10 @@ static HRESULT WINAPI transform_GetOutputStatus(IMFTransform *iface, DWORD *flag TRACE("iface %p, flags %p.\n", iface, flags);
EnterCriticalSection(&impl->cs); - hr = IMFTransform_GetOutputStatus(impl->transform, flags); + if (!impl->transform) + hr = MF_E_SHUTDOWN; + else + hr = IMFTransform_GetOutputStatus(impl->transform, flags); LeaveCriticalSection(&impl->cs); return hr; } @@ -335,7 +392,10 @@ static HRESULT WINAPI transform_SetOutputBounds(IMFTransform *iface, LONGLONG lo TRACE("iface %p, lower %I64d, upper %I64d.\n", iface, lower, upper);
EnterCriticalSection(&impl->cs); - hr = IMFTransform_SetOutputBounds(impl->transform, lower, upper); + if (!impl->transform) + hr = MF_E_SHUTDOWN; + else + hr = IMFTransform_SetOutputBounds(impl->transform, lower, upper); LeaveCriticalSection(&impl->cs); return hr; } @@ -348,7 +408,10 @@ static HRESULT WINAPI transform_ProcessEvent(IMFTransform *iface, DWORD id, IMFM TRACE("iface %p, id %#lx, event %p.\n", iface, id, event);
EnterCriticalSection(&impl->cs); - hr = IMFTransform_ProcessEvent(impl->transform, id, event); + if (!impl->transform) + hr = MF_E_SHUTDOWN; + else + hr = IMFTransform_ProcessEvent(impl->transform, id, event); LeaveCriticalSection(&impl->cs); return hr; } @@ -361,7 +424,10 @@ static HRESULT WINAPI transform_ProcessMessage(IMFTransform *iface, MFT_MESSAGE_ TRACE("iface %p, message %#x, param %Ix.\n", iface, message, param);
EnterCriticalSection(&impl->cs); - hr = IMFTransform_ProcessMessage(impl->transform, message, param); + if (!impl->transform) + hr = MF_E_SHUTDOWN; + else + hr = IMFTransform_ProcessMessage(impl->transform, message, param); LeaveCriticalSection(&impl->cs); return hr; } @@ -374,7 +440,10 @@ static HRESULT WINAPI transform_ProcessInput(IMFTransform *iface, DWORD id, IMFS TRACE("iface %p, id %#lx, sample %p, flags %#lx.\n", iface, id, sample, flags);
EnterCriticalSection(&impl->cs); - hr = IMFTransform_ProcessInput(impl->transform, id, sample, flags); + if (!impl->transform) + hr = MF_E_SHUTDOWN; + else + hr = IMFTransform_ProcessInput(impl->transform, id, sample, flags); LeaveCriticalSection(&impl->cs); return hr; } @@ -388,7 +457,10 @@ static HRESULT WINAPI transform_ProcessOutput(IMFTransform *iface, DWORD flags, TRACE("iface %p, flags %#lx, count %lu, samples %p, status %p.\n", iface, flags, count, samples, status);
EnterCriticalSection(&impl->cs); - hr = IMFTransform_ProcessOutput(impl->transform, flags, count, samples, status); + if (!impl->transform) + hr = MF_E_SHUTDOWN; + else + hr = IMFTransform_ProcessOutput(impl->transform, flags, count, samples, status); LeaveCriticalSection(&impl->cs); return hr; } @@ -423,6 +495,82 @@ static const IMFTransformVtbl transform_vtbl = transform_ProcessOutput, };
+static struct async_transform *impl_from_IMFShutdown(IMFShutdown *iface) +{ + return CONTAINING_RECORD(iface, struct async_transform, IMFShutdown_iface); +} + +static HRESULT WINAPI shutdown_QueryInterface(IMFShutdown *iface, REFIID iid, void **out) +{ + struct async_transform *impl = impl_from_IMFShutdown(iface); + return IMFTransform_QueryInterface(&impl->IMFTransform_iface, iid, out); +} + +static ULONG WINAPI shutdown_AddRef(IMFShutdown *iface) +{ + struct async_transform *impl = impl_from_IMFShutdown(iface); + return IMFTransform_AddRef(&impl->IMFTransform_iface); +} + +static ULONG WINAPI shutdown_Release(IMFShutdown *iface) +{ + struct async_transform *impl = impl_from_IMFShutdown(iface); + return IMFTransform_Release(&impl->IMFTransform_iface); +} + +static HRESULT WINAPI shutdown_Shutdown(IMFShutdown *iface) +{ + struct async_transform *impl = impl_from_IMFShutdown(iface); + HRESULT hr; + + TRACE("iface %p.\n", iface); + + EnterCriticalSection(&impl->cs); + if (!impl->transform) + hr = MF_E_SHUTDOWN; + else + { + IMFTransform_Release(impl->transform); + impl->transform = NULL; + hr = S_OK; + } + LeaveCriticalSection(&impl->cs); + + return hr; +} + +static HRESULT WINAPI shutdown_GetShutdownStatus(IMFShutdown *iface, MFSHUTDOWN_STATUS *status) +{ + struct async_transform *impl = impl_from_IMFShutdown(iface); + HRESULT hr; + + TRACE("iface %p, status %p.\n", iface, status); + + if (!status) + return E_INVALIDARG; + + EnterCriticalSection(&impl->cs); + if (impl->transform) + hr = MF_E_INVALIDREQUEST; + else + { + *status = MFSHUTDOWN_COMPLETED; + hr = S_OK; + } + LeaveCriticalSection(&impl->cs); + + return hr; +} + +static const IMFShutdownVtbl shutdown_vtbl = +{ + shutdown_QueryInterface, + shutdown_AddRef, + shutdown_Release, + shutdown_Shutdown, + shutdown_GetShutdownStatus, +}; + HRESULT async_transform_create(IMFTransform *transform, IMFTransform **out) { struct async_transform *impl; @@ -430,6 +578,7 @@ HRESULT async_transform_create(IMFTransform *transform, IMFTransform **out) if (!(impl = calloc(1, sizeof(*impl)))) return E_OUTOFMEMORY; impl->IMFTransform_iface.lpVtbl = &transform_vtbl; + impl->IMFShutdown_iface.lpVtbl = &shutdown_vtbl; impl->refcount = 1;
InitializeCriticalSection(&impl->cs); diff --git a/dlls/mf/session.c b/dlls/mf/session.c index 7d74b665205..808ca5306ce 100644 --- a/dlls/mf/session.c +++ b/dlls/mf/session.c @@ -760,7 +760,8 @@ static void release_topo_node(struct topo_node *node)
static void session_shutdown_current_topology(struct media_session *session) { - unsigned int shutdown, force_shutdown; + unsigned int needs_shutdown, force_shutdown; + struct topo_node *topo_node; MF_TOPOLOGY_TYPE node_type; IMFStreamSink *stream_sink; IMFTopology *topology; @@ -773,17 +774,30 @@ static void session_shutdown_current_topology(struct media_session *session) topology = session->presentation.current_topology; force_shutdown = session->state == SESSION_STATE_SHUT_DOWN;
- /* FIXME: should handle async MFTs, but these are not supported by the rest of the pipeline currently. */ + LIST_FOR_EACH_ENTRY(topo_node, &session->presentation.nodes, struct topo_node, entry) + { + IMFShutdown *shutdown; + + if (topo_node->type != MF_TOPOLOGY_TRANSFORM_NODE) + continue; + + if (SUCCEEDED(IMFTransform_QueryInterface(topo_node->object.transform, &IID_IMFShutdown, (void **)&shutdown))) + { + if (FAILED(IMFShutdown_Shutdown(shutdown))) + WARN("Failed to shutdown async transform\n"); + IMFShutdown_Release(shutdown); + } + }
while (SUCCEEDED(IMFTopology_GetNode(topology, idx++, &node))) { if (SUCCEEDED(IMFTopologyNode_GetNodeType(node, &node_type)) && node_type == MF_TOPOLOGY_OUTPUT_NODE) { - shutdown = 1; - IMFTopologyNode_GetUINT32(node, &MF_TOPONODE_NOSHUTDOWN_ON_REMOVE, &shutdown); + if (FAILED(IMFTopologyNode_GetUINT32(node, &MF_TOPONODE_NOSHUTDOWN_ON_REMOVE, &needs_shutdown))) + needs_shutdown = 1;
- if (force_shutdown || shutdown) + if (force_shutdown || needs_shutdown) { if (SUCCEEDED(IMFTopologyNode_GetUnknown(node, &_MF_TOPONODE_IMFActivate, &IID_IMFActivate, (void **)&activate)))