Signed-off-by: Rémi Bernon rbernon@codeweavers.com ---
This should fix a few leaks and potential race condition.
I'm not 100% sure about the last patch, as there's some questions about who's supposed to be shuting down the object. I think we set the _MF_TOPONODE_IMFActivate node when we activated the object, and after we called IMFTopologyNode_SetObject, so my understanding is that when they are set we should shutdown both the activation object and the object itself.
For the sample grabber, the tests show that shutting down the activation object should not automatically shutdown the sink, so it needs to be done separately.
dlls/mfplat/main.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/dlls/mfplat/main.c b/dlls/mfplat/main.c index 6fb8661dba4..9078702c854 100644 --- a/dlls/mfplat/main.c +++ b/dlls/mfplat/main.c @@ -7109,7 +7109,7 @@ static void queue_notify_subscriber(struct event_queue *queue) static HRESULT WINAPI eventqueue_BeginGetEvent(IMFMediaEventQueue *iface, IMFAsyncCallback *callback, IUnknown *state) { struct event_queue *queue = impl_from_IMFMediaEventQueue(iface); - MFASYNCRESULT *result_data = (MFASYNCRESULT *)queue->subscriber; + MFASYNCRESULT *result_data; HRESULT hr;
TRACE("%p, %p, %p.\n", iface, callback, state); @@ -7121,7 +7121,7 @@ static HRESULT WINAPI eventqueue_BeginGetEvent(IMFMediaEventQueue *iface, IMFAsy
if (queue->is_shut_down) hr = MF_E_SHUTDOWN; - else if (result_data) + else if ((result_data = (MFASYNCRESULT *)queue->subscriber)) { if (result_data->pCallback == callback) hr = IRtwqAsyncResult_GetStateNoAddRef(queue->subscriber) == state ?
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/mfplat/main.c | 3 +++ 1 file changed, 3 insertions(+)
diff --git a/dlls/mfplat/main.c b/dlls/mfplat/main.c index 9078702c854..412d7d1de43 100644 --- a/dlls/mfplat/main.c +++ b/dlls/mfplat/main.c @@ -7258,6 +7258,9 @@ static HRESULT WINAPI eventqueue_Shutdown(IMFMediaEventQueue *iface) if (!queue->is_shut_down) { event_queue_cleanup(queue); + if (queue->subscriber) + IRtwqAsyncResult_Release(queue->subscriber); + queue->subscriber = NULL; queue->is_shut_down = TRUE; }
I think we also need to release in eventqueue_Release(). Having that release/reset in event_queue_cleanup() is an option, or maybe another helper event_release_subscriber() to use in all three places - Release, Shutdown, EndGetEvent.
ShutdownObject doesn't alway call Shutdown on the activated object, for instance sample grabbers, and we are then leaking some resources.
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/mf/session.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/dlls/mf/session.c b/dlls/mf/session.c index 20ccdd0535e..bcf8ad5ba71 100644 --- a/dlls/mf/session.c +++ b/dlls/mf/session.c @@ -838,7 +838,7 @@ static void session_shutdown_current_topology(struct media_session *session) WARN("Failed to shut down activation object for the sink, hr %#x.\n", hr); IMFActivate_Release(activate); } - else if (SUCCEEDED(topology_node_get_object(node, &IID_IMFStreamSink, (void **)&stream_sink))) + if (SUCCEEDED(topology_node_get_object(node, &IID_IMFStreamSink, (void **)&stream_sink))) { if (SUCCEEDED(IMFStreamSink_GetMediaSink(stream_sink, &sink))) {