-- v4: mf: Release topologies when shutting down the session.
From: Santino Mazza smazza@codeweavers.com
--- dlls/mf/session.c | 193 ++++++++++++++++++++-------------- dlls/mf/tests/mf.c | 254 ++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 368 insertions(+), 79 deletions(-)
diff --git a/dlls/mf/session.c b/dlls/mf/session.c index 865399488ae..04ee4a3b5cd 100644 --- a/dlls/mf/session.c +++ b/dlls/mf/session.c @@ -80,11 +80,11 @@ struct session_op struct list entry; };
-struct queued_topology +struct topology_entry { struct list entry; + TOPOID topoid; IMFTopology *topology; - MF_TOPOSTATUS status; };
enum session_state @@ -256,6 +256,7 @@ struct media_session BOOL thin; float rate; } presentation; + struct list topologies_queue; /* Topologies queued for playing. */ struct list topologies; struct list commands; enum session_state state; @@ -491,9 +492,9 @@ static HRESULT session_submit_simple_command(struct media_session *session, enum
static void session_clear_queued_topologies(struct media_session *session) { - struct queued_topology *ptr, *next; + struct topology_entry *ptr, *next;
- LIST_FOR_EACH_ENTRY_SAFE(ptr, next, &session->topologies, struct queued_topology, entry) + LIST_FOR_EACH_ENTRY_SAFE(ptr, next, &session->topologies_queue, struct topology_entry, entry) { list_remove(&ptr->entry); IMFTopology_Release(ptr->topology); @@ -501,6 +502,69 @@ static void session_clear_queued_topologies(struct media_session *session) } }
+ +static void session_shutdown_topology(struct media_session *session, IMFTopology *topology) +{ + unsigned int shutdown, force_shutdown; + MF_TOPOLOGY_TYPE node_type; + IMFStreamSink *stream_sink; + IMFTopologyNode *node; + IMFActivate *activate; + IMFMediaSink *sink; + WORD idx = 0; + HRESULT hr; + + 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))) + { + 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 (force_shutdown || shutdown) + { + 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); + } + 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); + } + } + } + + IMFTopologyNode_Release(node); + } +} + +static void session_release_topologies(struct media_session *session) +{ + struct topology_entry *ptr, *next; + + LIST_FOR_EACH_ENTRY_SAFE(ptr, next, &session->topologies, struct topology_entry, entry) + { + list_remove(&ptr->entry); + session_shutdown_topology(session, ptr->topology); + IMFTopology_Release(ptr->topology); + free(ptr); + } +} + static void session_set_topo_status(struct media_session *session, HRESULT status, MF_TOPOSTATUS topo_status) { @@ -510,7 +574,7 @@ static void session_set_topo_status(struct media_session *session, HRESULT statu if (topo_status == MF_TOPOSTATUS_INVALID) return;
- if (list_empty(&session->topologies)) + if (list_empty(&session->topologies_queue)) { FIXME("Unexpectedly empty topology queue.\n"); return; @@ -518,7 +582,7 @@ static void session_set_topo_status(struct media_session *session, HRESULT statu
if (topo_status > session->presentation.topo_status) { - struct queued_topology *topology = LIST_ENTRY(list_head(&session->topologies), struct queued_topology, entry); + struct topology_entry *topology = LIST_ENTRY(list_head(&session->topologies_queue), struct topology_entry, entry);
param.vt = VT_UNKNOWN; param.punkVal = (IUnknown *)topology->topology; @@ -793,57 +857,6 @@ static void release_topo_node(struct topo_node *node) free(node); }
-static void session_shutdown_current_topology(struct media_session *session) -{ - 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))) - { - 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 (force_shutdown || shutdown) - { - 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); - } - 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); - } - } - } - - IMFTopologyNode_Release(node); - } -} - static void session_clear_command_list(struct media_session *session) { struct session_op *op, *op2; @@ -861,9 +874,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;
@@ -1900,11 +1910,11 @@ static HRESULT session_set_current_topology(struct media_session *session, IMFTo IMFMediaEvent *event; HRESULT hr;
- if (FAILED(hr = IMFTopology_CloneFrom(session->presentation.current_topology, topology))) - { - WARN("Failed to clone topology, hr %#lx.\n", hr); - return hr; - } + if (session->presentation.current_topology) + IMFTopology_Release(session->presentation.current_topology); + + session->presentation.current_topology = topology; + IMFTopology_AddRef(topology);
session_collect_nodes(session);
@@ -1972,9 +1982,25 @@ static HRESULT session_set_current_topology(struct media_session *session, IMFTo return S_OK; }
+/* Get a topology from the topologies list by it's id. */ +static struct topology_entry *get_topology_entry_by_id(struct media_session *session, TOPOID id) +{ + struct topology_entry *entry; + + LIST_FOR_EACH_ENTRY(entry, &session->topologies, struct topology_entry, entry) + { + if (entry->topoid == id) + return entry; + } + + return NULL; +} + static void session_set_topology(struct media_session *session, DWORD flags, IMFTopology *topology) { + TOPOID topo_id; IMFTopology *resolved_topology = NULL; + struct topology_entry *topology_entry = NULL; HRESULT hr = S_OK;
/* Resolve unless claimed to be full. */ @@ -1982,12 +2008,18 @@ static void session_set_topology(struct media_session *session, DWORD flags, IMF { if (!(flags & MFSESSION_SETTOPOLOGY_NORESOLUTION)) { - hr = session_bind_output_nodes(topology); + IMFTopology_GetTopologyID(topology, &topo_id); + if (!(topology_entry = get_topology_entry_by_id(session, topo_id))) + { + hr = session_bind_output_nodes(topology);
- if (SUCCEEDED(hr)) - hr = IMFTopoLoader_Load(session->topo_loader, topology, &resolved_topology, NULL /* FIXME? */); - if (SUCCEEDED(hr)) - hr = session_init_media_types(resolved_topology); + if (SUCCEEDED(hr)) + hr = IMFTopoLoader_Load(session->topo_loader, topology, &resolved_topology, NULL /* FIXME? */); + if (SUCCEEDED(hr)) + hr = session_init_media_types(resolved_topology); + } + else + resolved_topology = topology_entry->topology;
if (SUCCEEDED(hr)) { @@ -2019,14 +2051,22 @@ static void session_set_topology(struct media_session *session, DWORD flags, IMF /* With no current topology set it right away, otherwise queue. */ if (topology) { - struct queued_topology *queued_topology; + struct topology_entry *queued_topology; + + if (!topology_entry && (topology_entry = calloc(1, sizeof(*topology_entry)))) + { + topology_entry->topology = topology; + IMFTopology_AddRef(topology_entry->topology); + + list_add_tail(&session->topologies, &topology_entry->entry); + }
if ((queued_topology = calloc(1, sizeof(*queued_topology)))) { queued_topology->topology = topology; IMFTopology_AddRef(queued_topology->topology);
- list_add_tail(&session->topologies, &queued_topology->entry); + list_add_tail(&session->topologies_queue, &queued_topology->entry); }
if (session->presentation.topo_status == MF_TOPOSTATUS_INVALID) @@ -2381,6 +2421,7 @@ static HRESULT WINAPI mfsession_Shutdown(IMFMediaSession *iface) session->clock = NULL; session_clear_presentation(session); session_clear_queued_topologies(session); + session_release_topologies(session); session_submit_simple_command(session, SESSION_CMD_SHUTDOWN); } LeaveCriticalSection(&session->cs); @@ -2427,7 +2468,7 @@ static HRESULT WINAPI mfsession_GetSessionCapabilities(IMFMediaSession *iface, D static HRESULT WINAPI mfsession_GetFullTopology(IMFMediaSession *iface, DWORD flags, TOPOID id, IMFTopology **topology) { struct media_session *session = impl_from_IMFMediaSession(iface); - struct queued_topology *queued; + struct topology_entry *queued; TOPOID topo_id; HRESULT hr;
@@ -2448,7 +2489,7 @@ static HRESULT WINAPI mfsession_GetFullTopology(IMFMediaSession *iface, DWORD fl } else { - LIST_FOR_EACH_ENTRY(queued, &session->topologies, struct queued_topology, entry) + LIST_FOR_EACH_ENTRY(queued, &session->topologies_queue, struct topology_entry, entry) { if (SUCCEEDED(IMFTopology_GetTopologyID(queued->topology, &topo_id)) && topo_id == id) { @@ -4587,15 +4628,13 @@ 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->topologies_queue); list_init(&object->commands); list_init(&object->presentation.sources); list_init(&object->presentation.sinks); list_init(&object->presentation.nodes); InitializeCriticalSection(&object->cs);
- if (FAILED(hr = MFCreateTopology(&object->presentation.current_topology))) - goto failed; - if (FAILED(hr = MFCreateEventQueue(&object->event_queue))) goto failed;
diff --git a/dlls/mf/tests/mf.c b/dlls/mf/tests/mf.c index a2f183e5cc4..60bdd3fd71d 100644 --- a/dlls/mf/tests/mf.c +++ b/dlls/mf/tests/mf.c @@ -1169,9 +1169,10 @@ static HRESULT wait_media_event_(int line, IMFMediaSession *session, IMFAsyncCal return status; }
-#define wait_media_event_until_blocking(a, b, c, d, e) wait_media_event_until_blocking_(__LINE__, a, b, c, d, e) +#define get_media_event(a, b, c, d, e, f) wait_media_event_until_blocking_(__LINE__, a, b, c, d, e, f) +#define wait_media_event_until_blocking(a, b, c, d, e) wait_media_event_until_blocking_(__LINE__, a, b, c, d, e, NULL) static HRESULT wait_media_event_until_blocking_(int line, IMFMediaSession *session, IMFAsyncCallback *callback, - MediaEventType expect_type, DWORD timeout, PROPVARIANT *value) + MediaEventType expect_type, DWORD timeout, PROPVARIANT *value, IMFMediaEvent **media_event) { struct test_callback *impl = impl_from_IMFAsyncCallback(callback); MediaEventType type; @@ -1179,6 +1180,9 @@ static HRESULT wait_media_event_until_blocking_(int line, IMFMediaSession *sessi DWORD ret; GUID guid;
+ if (media_event) + *media_event = NULL; + do { hr = IMFMediaSession_BeginGetEvent(session, &impl->IMFAsyncCallback_iface, (IUnknown *)session); @@ -1201,6 +1205,12 @@ static HRESULT wait_media_event_until_blocking_(int line, IMFMediaSession *sessi hr = IMFMediaEvent_GetStatus(impl->media_event, &status); ok_(__FILE__, line)(hr == S_OK, "Unexpected hr %#lx.\n", hr);
+ if (media_event) + { + IMFMediaEvent_AddRef(impl->media_event); + *media_event = impl->media_event; + } + return status; }
@@ -2615,6 +2625,245 @@ static void test_media_session_rate_control(void) ok(hr == S_OK, "Shutdown failure, hr %#lx.\n", hr); }
+#define check_topologyid(a, b) check_topologyid_(__LINE__, a, b) +static void check_topologyid_(unsigned int line, IMFMediaEvent *event, TOPOID expected_topoid) +{ + PROPVARIANT pv; + TOPOID topoid; + IMFTopology *topology; + + IMFMediaEvent_GetValue(event, &pv); + IUnknown_QueryInterface(pv.punkVal, &IID_IMFTopology, (void**)&topology); + IMFTopology_GetTopologyID(topology, &topoid); + ok_(__FILE__, line)(topoid == expected_topoid, "Expected topoid %I64u, got %I64u\n", expected_topoid, topoid); + IMFTopology_Release(topology); +} + +#define check_topostatus(a, b) check_topostatus_(__LINE__, a, b) +static void check_topostatus_(unsigned int line, IMFMediaEvent *event, UINT32 expected_status) +{ + UINT32 topostatus; + IMFMediaEvent_GetUINT32(event, &MF_EVENT_TOPOLOGY_STATUS, &topostatus); + ok_(__FILE__, line)(topostatus == expected_status, "Expected MF_TOPOSTATUS_READY got %d\n", topostatus); +} + +static IMFTopologyNode *get_sink_node(IMFTopology *topology, DWORD index) +{ + IMFCollection *output_nodes; + IMFTopologyNode *node; + IUnknown *nodeunk; + + IMFTopology_GetOutputNodeCollection(topology, &output_nodes); + IMFCollection_GetElement(output_nodes, index, &nodeunk); + IMFCollection_Release(output_nodes); + IUnknown_QueryInterface(nodeunk, &IID_IMFTopologyNode, (void**)&node); + IUnknown_Release(nodeunk); + + return node; +} + +static IMFTopology *create_topology_from_file(LPCWSTR file, LPCWSTR mime) +{ + IMFTopologyNode *src_node, *sink_node; + IMFPresentationDescriptor *pd; + IMFActivate *sar_activate; + IMFStreamDescriptor *sd; + IMFMediaSource *source; + IMFTopology *topology; + BOOL selected; + HRESULT hr; + + if(!(source = create_media_source(file, mime))) + return NULL; + + hr = MFCreateTopology(&topology); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + + hr = MFCreateTopologyNode(MF_TOPOLOGY_SOURCESTREAM_NODE, &src_node); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + + IMFMediaSource_CreatePresentationDescriptor(source, &pd); + hr = IMFPresentationDescriptor_GetStreamDescriptorByIndex(pd, 0, &selected, &sd); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + init_source_node(source, -1, src_node, pd, sd); + + hr = MFCreateTopologyNode(MF_TOPOLOGY_OUTPUT_NODE, &sink_node); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + + hr = MFCreateAudioRendererActivate(&sar_activate); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + + IMFTopologyNode_SetObject(sink_node, (IUnknown *)sar_activate); + + IMFTopology_AddNode(topology, src_node); + IMFTopology_AddNode(topology, sink_node); + IMFTopologyNode_ConnectOutput(src_node, 0, sink_node, 0); + + IMFTopologyNode_Release(src_node); + IMFTopologyNode_Release(sink_node); + IMFActivate_Release(sar_activate); + IMFPresentationDescriptor_Release(pd); + IMFStreamDescriptor_Release(sd); + + return topology; +} + +static void test_media_session_topologies(void) +{ + IMFTopology *topology; + IUnknown *nodeunk; + IMFStreamSink *stream_sink; + IMFTopologyNode *node; + IMFAsyncCallback *callback; + IMFMediaSession *session; + IMFMediaEvent *event; + TOPOID topoid; + PROPVARIANT pv; + HRESULT hr; + + hr = MFStartup(MF_VERSION, MFSTARTUP_FULL); + ok(hr == S_OK, "Startup failure, hr %#lx.\n", hr); + + if (!(topology = create_topology_from_file(L"mp3encdata.bin", L"audio/mpeg"))) + { + win_skip("MP3 not supported.\n"); + MFShutdown(); + return; + } + + IMFTopology_GetTopologyID(topology, &topoid); + + + callback = create_test_callback(TRUE); + hr = MFCreateMediaSession(NULL, &session); + ok(hr == S_OK, "Failed to create media session, hr %#lx.\n", hr); + + node = get_sink_node(topology, 0); + IMFTopologyNode_GetObject(node, &nodeunk); + check_interface(nodeunk, &IID_IMFActivate, TRUE); + IUnknown_Release(nodeunk); + + hr = IMFMediaSession_SetTopology(session, 0, topology); + ok(hr == S_OK, "Unexpected hr %#lx\n", hr); + hr = wait_media_event(session, callback, MESessionTopologySet, 1000, &pv); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(pv.vt == VT_UNKNOWN, "got vt %u\n", pv.vt); + ok(pv.punkVal != (IUnknown *)topology, "got punkVal %p\n", pv.punkVal); + PropVariantClear(&pv); + + hr = get_media_event(session, callback, MESessionTopologyStatus, 1000, &pv, &event); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + todo_wine check_topologyid(event, topoid); + check_topostatus(event, MF_TOPOSTATUS_READY); + IMFMediaEvent_Release(event); + + node = get_sink_node(topology, 0); + IMFTopologyNode_GetObject(node, &nodeunk); + check_interface(nodeunk, &IID_IMFActivate, FALSE); + check_interface(nodeunk, &IID_IMFStreamSink, TRUE); + IUnknown_QueryInterface(nodeunk, &IID_IMFStreamSink, (void**)&stream_sink); + IUnknown_Release(nodeunk); + + pv.vt = VT_EMPTY; + hr = IMFMediaSession_Start(session, &GUID_NULL, &pv); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + hr = wait_media_event(session, callback, MESessionStarted, 1000, &pv); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(pv.vt == VT_EMPTY, "got vt %u\n", pv.vt); + ok(pv.punkVal != (IUnknown *)topology, "got punkVal %p\n", pv.punkVal); + PropVariantClear(&pv); + + hr = get_media_event(session, callback, MESessionTopologyStatus, 1000, &pv, &event); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + todo_wine check_topologyid(event, topoid); + check_topostatus(event, MF_TOPOSTATUS_ENDED); + IMFMediaEvent_Release(event); + + hr = wait_media_event(session, callback, MESessionEnded, 1000, &pv); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(pv.vt == VT_EMPTY, "got vt %u\n", pv.vt); + ok(pv.punkVal != (IUnknown *)topology, "got punkVal %p\n", pv.punkVal); + PropVariantClear(&pv); + + hr = IMFMediaSession_SetTopology(session, 0, topology); + ok(hr == S_OK, "Unexpected hr %#lx\n", hr); + hr = wait_media_event(session, callback, MESessionTopologySet, 1000, &pv); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(pv.vt == VT_UNKNOWN, "got vt %u\n", pv.vt); + ok(pv.punkVal != (IUnknown *)topology, "got punkVal %p\n", pv.punkVal); + PropVariantClear(&pv); + + pv.vt = VT_EMPTY; + hr = IMFMediaSession_Start(session, &GUID_NULL, &pv); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + hr = wait_media_event(session, callback, MESessionStarted, 1000, &pv); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(pv.vt == VT_EMPTY, "got vt %u\n", pv.vt); + ok(pv.punkVal != (IUnknown *)topology, "got punkVal %p\n", pv.punkVal); + PropVariantClear(&pv); + + hr = get_media_event(session, callback, MESessionTopologyStatus, 1000, &pv, &event); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + todo_wine check_topologyid(event, topoid); + check_topostatus(event, MF_TOPOSTATUS_ENDED); + IMFMediaEvent_Release(event); + + hr = wait_media_event(session, callback, MESessionEnded, 1000, &pv); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(pv.vt == VT_EMPTY, "got vt %u\n", pv.vt); + ok(pv.punkVal != (IUnknown *)topology, "got punkVal %p\n", pv.punkVal); + PropVariantClear(&pv); + + hr = IMFStreamSink_Flush(stream_sink); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + + hr = IMFMediaSession_SetTopology(session, MFSESSION_SETTOPOLOGY_IMMEDIATE, topology); + ok(hr == S_OK, "Unexpected hr %#lx\n", hr); + hr = wait_media_event(session, callback, MESessionTopologySet, 1000, &pv); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(pv.vt == VT_UNKNOWN, "got vt %u\n", pv.vt); + ok(pv.punkVal != (IUnknown *)topology, "got punkVal %p\n", pv.punkVal); + PropVariantClear(&pv); + + hr = IMFStreamSink_Flush(stream_sink); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + + pv.vt = VT_EMPTY; + hr = IMFMediaSession_Start(session, &GUID_NULL, &pv); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + hr = wait_media_event(session, callback, MESessionStarted, 1000, &pv); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(pv.vt == VT_EMPTY, "got vt %u\n", pv.vt); + ok(pv.punkVal != (IUnknown *)topology, "got punkVal %p\n", pv.punkVal); + PropVariantClear(&pv); + + hr = wait_media_event(session, callback, MESessionEnded, 1000, &pv); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(pv.vt == VT_EMPTY, "got vt %u\n", pv.vt); + ok(pv.punkVal != (IUnknown *)topology, "got punkVal %p\n", pv.punkVal); + PropVariantClear(&pv); + + IMFMediaSession_Close(session); + hr = wait_media_event(session, callback, MESessionClosed, 2000, &pv); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(pv.vt == VT_EMPTY, "got vt %u\n", pv.vt); + ok(pv.punkVal != (IUnknown *)topology, "got punkVal %p\n", pv.punkVal); + PropVariantClear(&pv); + hr = IMFStreamSink_Flush(stream_sink); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + + IMFMediaSession_Shutdown(session); + hr = IMFStreamSink_Flush(stream_sink); + ok(hr == MF_E_STREAMSINK_REMOVED, "Unexpected hr %#lx.\n", hr); + IMFStreamSink_Release(stream_sink); + + IMFMediaSession_Release(session); + IMFAsyncCallback_Release(callback); + IMFTopology_Release(topology); + + MFShutdown(); +} + struct test_grabber_callback { IMFSampleGrabberSinkCallback IMFSampleGrabberSinkCallback_iface; @@ -6549,6 +6798,7 @@ START_TEST(mf) test_media_session(); test_media_session_events(); test_media_session_rate_control(); + test_media_session_topologies(); test_MFShutdownObject(); test_presentation_clock(); test_sample_grabber();
Hi,
It looks like your patch introduced the new failures shown below. Please investigate and fix them before resubmitting your patch. If they are not new, fixing them anyway would help a lot. Otherwise please ask for the known failures list to be updated.
The tests also ran into some preexisting test failures. If you know how to fix them that would be helpful. See the TestBot job for the details:
The full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=146197
Your paranoid android.
=== w11pro64_amd (64 bit report) ===
mf: mf.c:2749: Test failed: Unexpected hr 0xc00d36fa. mf.c:2751: Test failed: got punkVal 00000000013D3D00 mf.c:2755: Test failed: Unexpected hr 0x102.
=== debian11 (32 bit report) ===
mf: mf.c:2756: Test succeeded inside todo block: Expected topoid 2, got 2 mf.c:2778: Test succeeded inside todo block: Expected topoid 2, got 2 mf.c:2807: Test succeeded inside todo block: Expected topoid 2, got 2
=== debian11 (32 bit ar:MA report) ===
mf: mf.c:2756: Test succeeded inside todo block: Expected topoid 2, got 2 mf.c:2778: Test succeeded inside todo block: Expected topoid 2, got 2 mf.c:2807: Test succeeded inside todo block: Expected topoid 2, got 2
=== debian11 (32 bit de report) ===
mf: mf.c:2756: Test succeeded inside todo block: Expected topoid 2, got 2 mf.c:2778: Test succeeded inside todo block: Expected topoid 2, got 2 mf.c:2807: Test succeeded inside todo block: Expected topoid 2, got 2
=== debian11 (32 bit fr report) ===
mf: mf.c:2756: Test succeeded inside todo block: Expected topoid 2, got 2 mf.c:2778: Test succeeded inside todo block: Expected topoid 2, got 2 mf.c:2807: Test succeeded inside todo block: Expected topoid 2, got 2
=== debian11 (32 bit he:IL report) ===
mf: mf.c:2756: Test succeeded inside todo block: Expected topoid 2, got 2 mf.c:2778: Test succeeded inside todo block: Expected topoid 2, got 2 mf.c:2807: Test succeeded inside todo block: Expected topoid 2, got 2
=== debian11 (32 bit hi:IN report) ===
mf: mf.c:2756: Test succeeded inside todo block: Expected topoid 2, got 2 mf.c:2778: Test succeeded inside todo block: Expected topoid 2, got 2 mf.c:2807: Test succeeded inside todo block: Expected topoid 2, got 2
=== debian11 (32 bit ja:JP report) ===
mf: mf.c:2756: Test succeeded inside todo block: Expected topoid 2, got 2 mf.c:2778: Test succeeded inside todo block: Expected topoid 2, got 2 mf.c:2807: Test succeeded inside todo block: Expected topoid 2, got 2
=== debian11 (32 bit zh:CN report) ===
mf: mf.c:2756: Test succeeded inside todo block: Expected topoid 2, got 2 mf.c:2778: Test succeeded inside todo block: Expected topoid 2, got 2 mf.c:2807: Test succeeded inside todo block: Expected topoid 2, got 2
=== debian11b (32 bit WoW report) ===
mf: mf.c:2756: Test succeeded inside todo block: Expected topoid 2, got 2 mf.c:2778: Test succeeded inside todo block: Expected topoid 2, got 2 mf.c:2807: Test succeeded inside todo block: Expected topoid 2, got 2
=== debian11b (64 bit WoW report) ===
mf: mf.c:2756: Test succeeded inside todo block: Expected topoid 2, got 2 mf.c:2778: Test succeeded inside todo block: Expected topoid 2, got 2 mf.c:2807: Test succeeded inside todo block: Expected topoid 2, got 2
Rebased with master and removed the changes related with TopoLoader topology id's