From: Conor McCarthy cmccarthy@codeweavers.com
--- dlls/mf/session.c | 58 +++++++++++++++++++++++++--------------------- dlls/mf/tests/mf.c | 11 --------- 2 files changed, 31 insertions(+), 38 deletions(-)
diff --git a/dlls/mf/session.c b/dlls/mf/session.c index 062f415364e..109ce6ccfbe 100644 --- a/dlls/mf/session.c +++ b/dlls/mf/session.c @@ -277,6 +277,7 @@ struct media_session BOOL thin_committed; } presentation; struct list topologies; + struct list removed_topologies; struct list commands; enum session_state state; enum command_state command_state; @@ -522,8 +523,7 @@ static void session_clear_queued_topologies(struct media_session *session) LIST_FOR_EACH_ENTRY_SAFE(ptr, next, &session->topologies, struct queued_topology, entry) { list_remove(&ptr->entry); - IMFTopology_Release(ptr->topology); - free(ptr); + list_add_tail(&session->removed_topologies, &ptr->entry); } }
@@ -819,21 +819,16 @@ static void release_topo_node(struct topo_node *node) free(node); }
-static void session_shutdown_current_topology(struct media_session *session) +static void topology_shutdown(IMFTopology *topology) { - unsigned int shutdown, force_shutdown; MF_TOPOLOGY_TYPE node_type; IMFStreamSink *stream_sink; - IMFTopology *topology; IMFTopologyNode *node; IMFActivate *activate; IMFMediaSink *sink; WORD idx = 0; HRESULT hr;
- 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. */
while (SUCCEEDED(IMFTopology_GetNode(topology, idx++, &node))) @@ -841,28 +836,24 @@ static void session_shutdown_current_topology(struct media_session *session) if (SUCCEEDED(IMFTopologyNode_GetNodeType(node, &node_type)) && node_type == MF_TOPOLOGY_OUTPUT_NODE) { - shutdown = 1; - IMFTopologyNode_GetUINT32(node, &MF_TOPONODE_NOSHUTDOWN_ON_REMOVE, &shutdown); + /* MF_TOPONODE_NOSHUTDOWN_ON_REMOVE is ignored, at least for sinks. */
- if (force_shutdown || shutdown) + if (SUCCEEDED(IMFTopologyNode_GetUnknown(node, &_MF_TOPONODE_IMFActivate, &IID_IMFActivate, + (void **)&activate))) { - if (SUCCEEDED(IMFTopologyNode_GetUnknown(node, &_MF_TOPONODE_IMFActivate, &IID_IMFActivate, - (void **)&activate))) + if (FAILED(hr = IMFActivate_ShutdownObject(activate))) + WARN("Failed to shut down activation object for the sink, hr %#lx.\n", hr); + IMFActivate_Release(activate); + } + if (SUCCEEDED(topology_node_get_object(node, &IID_IMFStreamSink, (void **)&stream_sink))) + { + if (SUCCEEDED(IMFStreamSink_GetMediaSink(stream_sink, &sink))) { - if (FAILED(hr = IMFActivate_ShutdownObject(activate))) - WARN("Failed to shut down activation object for the sink, hr %#lx.\n", hr); - IMFActivate_Release(activate); + IMFMediaSink_Shutdown(sink); + IMFMediaSink_Release(sink); } - else if (SUCCEEDED(topology_node_get_object(node, &IID_IMFStreamSink, (void **)&stream_sink))) - { - if (SUCCEEDED(IMFStreamSink_GetMediaSink(stream_sink, &sink))) - { - IMFMediaSink_Shutdown(sink); - IMFMediaSink_Release(sink); - }
- IMFStreamSink_Release(stream_sink); - } + IMFStreamSink_Release(stream_sink); } }
@@ -870,6 +861,19 @@ static void session_shutdown_current_topology(struct media_session *session) } }
+static void session_clear_removed_topologies(struct media_session *session) +{ + struct queued_topology *ptr, *next; + + LIST_FOR_EACH_ENTRY_SAFE(ptr, next, &session->removed_topologies, struct queued_topology, entry) + { + list_remove(&ptr->entry); + topology_shutdown(ptr->topology); + IMFTopology_Release(ptr->topology); + free(ptr); + } +} + static void session_clear_command_list(struct media_session *session) { struct session_op *op, *op2; @@ -891,8 +895,6 @@ static void session_clear_presentation(struct media_session *session) struct media_sink *sink, *sink2; struct topo_node *node, *node2;
- session_shutdown_current_topology(session); - IMFTopology_Clear(session->presentation.current_topology); session->presentation.topo_status = MF_TOPOSTATUS_INVALID; session->presentation.flags = 0; @@ -2479,6 +2481,7 @@ static HRESULT WINAPI mfsession_Shutdown(IMFMediaSession *iface) MFShutdownObject((IUnknown *)session->clock); session_clear_presentation(session); session_clear_queued_topologies(session); + session_clear_removed_topologies(session); session_submit_simple_command(session, SESSION_CMD_SHUTDOWN); } LeaveCriticalSection(&session->cs); @@ -4850,6 +4853,7 @@ HRESULT WINAPI MFCreateMediaSession(IMFAttributes *config, IMFMediaSession **ses object->sink_finalizer_callback.lpVtbl = &session_sink_finalizer_callback_vtbl; object->refcount = 1; list_init(&object->topologies); + list_init(&object->removed_topologies); list_init(&object->commands); list_init(&object->presentation.sources); list_init(&object->presentation.sinks); diff --git a/dlls/mf/tests/mf.c b/dlls/mf/tests/mf.c index 515a98f9aa6..61535cbdec9 100644 --- a/dlls/mf/tests/mf.c +++ b/dlls/mf/tests/mf.c @@ -4496,7 +4496,6 @@ static void test_sample_grabber_orientation(GUID subtype)
hr = IMFMediaSession_Shutdown(session); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); - todo_wine ok(grabber_callback->shutdown, "Media sink is not shut down.\n"); hr = IMFMediaSource_Shutdown(source); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); @@ -7126,7 +7125,6 @@ static void test_media_session_Start(void) ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); hr = IMFMediaSession_Shutdown(session); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); - todo_wine ok(grabber_callback->shutdown, "Media sink is not shut down.\n");
propvar.vt = VT_I8; @@ -7209,7 +7207,6 @@ static void test_media_session_Start(void) ok(!grabber_callback->shutdown, "Media sink was shut down.\n"); hr = IMFMediaSession_Shutdown(session); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); - todo_wine ok(grabber_callback->shutdown, "Media sink is not shut down.\n"); hr = IMFMediaSource_Shutdown(source); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); @@ -7656,7 +7653,6 @@ static void test_media_session_Close(void)
hr = IMFMediaSession_Shutdown(session); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); - todo_wine ok(grabber_callback->shutdown, "Media sink is not shut down.\n");
IMFPresentationClock_Release(presentation_clock); @@ -7800,7 +7796,6 @@ static void test_media_session_thinning(void) ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); hr = IMFMediaSession_Shutdown(session); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); - todo_wine ok(grabber_callback->shutdown, "Media sink is not shut down.\n"); hr = IMFMediaSource_Shutdown(source); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); @@ -8544,26 +8539,22 @@ static void test_media_session_sink_shutdown(void) hr = wait_media_event(session, callback, MESessionTopologySet, 1000, &propvar); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); PropVariantClear(&propvar); - todo_wine_if(i == 1) ok(!grabber_callback->shutdown, "Media sink was shut down.\n");
hr = IMFMediaSession_ClearTopologies(session); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); hr = wait_media_event(session, callback, MESessionTopologiesCleared, 1000, &propvar); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); - todo_wine_if(i == 1) ok(!grabber_callback->shutdown, "Media sink was shut down.\n");
hr = IMFMediaSession_Close(session); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); hr = wait_media_event(session, callback, MESessionClosed, 1000, &propvar); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); - todo_wine_if(i == 1) ok(!grabber_callback->shutdown, "Media sink was shut down.\n");
hr = IMFMediaSession_Shutdown(session); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); - todo_wine_if(i != 1) ok(grabber_callback->shutdown, "Media sink is not shut down.\n"); IMFSampleGrabberSinkCallback_Release(&grabber_callback->IMFSampleGrabberSinkCallback_iface);
@@ -8572,7 +8563,6 @@ static void test_media_session_sink_shutdown(void)
Sleep(20); ref = IMFMediaSession_Release(session); - todo_wine_if(i != 1) ok(!ref, "Unexpected refcount %ld.\n", ref); ref = IMFMediaSource_Release(source); ok(!ref, "Unexpected refcount %ld.\n", ref); @@ -8631,7 +8621,6 @@ static void test_media_session_sink_shutdown(void) ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); for (i = 0; i < ARRAY_SIZE(grabber_callbacks); ++i) { - todo_wine_if(i) ok(grabber_callbacks[i]->shutdown, "Media sink %u is not shut down.\n", i); IMFSampleGrabberSinkCallback_Release(&grabber_callbacks[i]->IMFSampleGrabberSinkCallback_iface); }