From: Rémi Bernon rbernon@codeweavers.com
--- dlls/mf/session.c | 126 ++++++++++++++++++++++++++++++++++++++++++--- dlls/mf/tests/mf.c | 17 ------ 2 files changed, 120 insertions(+), 23 deletions(-)
diff --git a/dlls/mf/session.c b/dlls/mf/session.c index b410a5fe861..bc147d2ec88 100644 --- a/dlls/mf/session.c +++ b/dlls/mf/session.c @@ -1938,20 +1938,134 @@ static HRESULT WINAPI mfsession_QueueEvent(IMFMediaSession *iface, MediaEventTyp return IMFMediaEventQueue_QueueEventParamVar(session->event_queue, event_type, ext_type, hr, value); }
+static HRESULT session_check_stream_descriptor(IMFPresentationDescriptor *pd, IMFStreamDescriptor *sd) +{ + IMFStreamDescriptor *selected_sd; + DWORD i, count; + BOOL selected; + HRESULT hr; + + if (FAILED(hr = IMFPresentationDescriptor_GetStreamDescriptorCount(pd, &count))) + { + WARN("Failed to get stream descriptor count, hr %#lx.\n", hr); + return MF_E_TOPO_STREAM_DESCRIPTOR_NOT_SELECTED; + } + + for (i = 0; i < count; ++i) + { + if (FAILED(hr = IMFPresentationDescriptor_GetStreamDescriptorByIndex(pd, i, + &selected, &selected_sd))) + { + WARN("Failed to get stream descriptor %lu, hr %#lx.\n", i, hr); + return MF_E_TOPO_STREAM_DESCRIPTOR_NOT_SELECTED; + } + IMFStreamDescriptor_Release(selected_sd); + + if (selected_sd == sd) + { + if (selected) + return S_OK; + + WARN("Presentation descriptor %p stream %p is not selected.\n", pd, sd); + return MF_E_TOPO_STREAM_DESCRIPTOR_NOT_SELECTED; + } + } + + WARN("Failed to find stream descriptor %lu, hr %#lx.\n", i, hr); + return MF_E_TOPO_STREAM_DESCRIPTOR_NOT_SELECTED; +} + +static HRESULT session_check_topology(IMFTopology *topology) +{ + MF_TOPOLOGY_TYPE node_type; + IMFTopologyNode *node; + WORD node_count, i; + HRESULT hr; + + if (!topology) + return S_OK; + + if (FAILED(IMFTopology_GetNodeCount(topology, &node_count)) + || node_count == 0) + return E_INVALIDARG; + + for (i = 0; i < node_count; ++i) + { + if (FAILED(hr = IMFTopology_GetNode(topology, i, &node))) + break; + + if (FAILED(hr = IMFTopologyNode_GetNodeType(node, &node_type))) + { + IMFTopologyNode_Release(node); + break; + } + + switch (node_type) + { + case MF_TOPOLOGY_SOURCESTREAM_NODE: + { + IMFPresentationDescriptor *pd; + IMFStreamDescriptor *sd; + IMFMediaSource *source; + + if (FAILED(hr = IMFTopologyNode_GetUnknown(node, &MF_TOPONODE_SOURCE, &IID_IMFMediaSource, + (void **)&source))) + { + WARN("Missing MF_TOPONODE_SOURCE, hr %#lx.\n", hr); + IMFTopologyNode_Release(node); + return MF_E_TOPO_MISSING_SOURCE; + } + IMFMediaSource_Release(source); + + if (FAILED(hr = IMFTopologyNode_GetUnknown(node, &MF_TOPONODE_PRESENTATION_DESCRIPTOR, + &IID_IMFPresentationDescriptor, (void **)&pd))) + { + WARN("Missing MF_TOPONODE_PRESENTATION_DESCRIPTOR, hr %#lx.\n", hr); + IMFTopologyNode_Release(node); + return MF_E_TOPO_MISSING_PRESENTATION_DESCRIPTOR; + } + + if (FAILED(hr = IMFTopologyNode_GetUnknown(node, &MF_TOPONODE_STREAM_DESCRIPTOR, + &IID_IMFStreamDescriptor, (void **)&sd))) + { + WARN("Missing MF_TOPONODE_STREAM_DESCRIPTOR, hr %#lx.\n", hr); + IMFPresentationDescriptor_Release(pd); + IMFTopologyNode_Release(node); + return MF_E_TOPO_MISSING_STREAM_DESCRIPTOR; + } + + hr = session_check_stream_descriptor(pd, sd); + IMFPresentationDescriptor_Release(pd); + IMFStreamDescriptor_Release(sd); + if (FAILED(hr)) + { + IMFTopologyNode_Release(node); + return hr; + } + + break; + } + + default: + break; + } + + IMFTopologyNode_Release(node); + } + + return hr; +} + static HRESULT WINAPI mfsession_SetTopology(IMFMediaSession *iface, DWORD flags, IMFTopology *topology) { struct media_session *session = impl_from_IMFMediaSession(iface); struct session_op *op; - WORD node_count = 0; HRESULT hr;
TRACE("%p, %#lx, %p.\n", iface, flags, topology);
- if (topology) - { - if (FAILED(IMFTopology_GetNodeCount(topology, &node_count)) || node_count == 0) - return E_INVALIDARG; - } + if (FAILED(hr = session_check_topology(topology))) + return hr;
if (FAILED(hr = create_session_op(SESSION_CMD_SET_TOPOLOGY, &op))) return hr; diff --git a/dlls/mf/tests/mf.c b/dlls/mf/tests/mf.c index 004f7b50f59..ba4afddc7d2 100644 --- a/dlls/mf/tests/mf.c +++ b/dlls/mf/tests/mf.c @@ -2145,29 +2145,13 @@ static void test_media_session_events(void) ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
hr = IMFMediaSession_SetTopology(session, 0, topology); - todo_wine ok(hr == MF_E_TOPO_MISSING_SOURCE, "Unexpected hr %#lx.\n", hr); - if (hr == S_OK) - { - hr = wait_media_event(session, callback, MESessionTopologySet, 1000, &propvar); - ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); - PropVariantClear(&propvar); - handler.enum_count = handler.set_current_count = 0; - }
source = create_test_source(pd); init_source_node(source, -1, src_node, pd, sd);
hr = IMFMediaSession_SetTopology(session, 0, topology); - todo_wine ok(hr == MF_E_TOPO_STREAM_DESCRIPTOR_NOT_SELECTED, "Unexpected hr %#lx.\n", hr); - if (hr == S_OK) - { - hr = wait_media_event(session, callback, MESessionTopologySet, 1000, &propvar); - ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); - PropVariantClear(&propvar); - handler.enum_count = handler.set_current_count = 0; - }
hr = IMFMediaSession_ClearTopologies(session); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); @@ -2177,7 +2161,6 @@ static void test_media_session_events(void)
hr = IMFMediaSession_Shutdown(session); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); - todo_wine ok(!media_sink.shutdown, "media sink is shutdown.\n"); media_sink.shutdown = FALSE;