[PATCH 1/2] mf/topology: Setting tee node input type does not create input stream.

Nikolay Sivov nsivov at codeweavers.com
Fri May 22 09:15:09 CDT 2020


Signed-off-by: Nikolay Sivov <nsivov at codeweavers.com>
---
 dlls/mf/tests/mf.c |  91 +++++++++++++++++++++++++++++++++++-
 dlls/mf/topology.c | 114 ++++++++++++++++++++++++++++-----------------
 2 files changed, 162 insertions(+), 43 deletions(-)

diff --git a/dlls/mf/tests/mf.c b/dlls/mf/tests/mf.c
index bf14ccf0feb..c79ae69f91d 100644
--- a/dlls/mf/tests/mf.c
+++ b/dlls/mf/tests/mf.c
@@ -114,11 +114,11 @@ static const IUnknownVtbl test_unk_vtbl =
 
 static void test_topology(void)
 {
+    IMFMediaType *mediatype, *mediatype2, *mediatype3;
     IMFCollection *collection, *collection2;
     IUnknown test_unk2 = { &test_unk_vtbl };
     IUnknown test_unk = { &test_unk_vtbl };
     IMFTopologyNode *node, *node2, *node3;
-    IMFMediaType *mediatype, *mediatype2;
     IMFTopology *topology, *topology2;
     MF_TOPOLOGY_TYPE node_type;
     UINT32 count, index;
@@ -516,6 +516,9 @@ static void test_topology(void)
     ok(mediatype2 == mediatype, "Unexpected mediatype instance.\n");
     IMFMediaType_Release(mediatype2);
 
+    hr = IMFTopologyNode_GetOutputPrefType(node, 0, &mediatype2);
+    ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
+
     hr = IMFTopologyNode_GetInputCount(node, &count);
     ok(hr == S_OK, "Failed to get output count, hr %#x.\n", hr);
     ok(count == 0, "Unexpected count %u.\n", count);
@@ -529,6 +532,23 @@ static void test_topology(void)
     hr = IMFTopologyNode_SetOutputPrefType(node, 4, mediatype);
     ok(hr == S_OK, "Failed to set preferred type, hr %#x.\n", hr);
 
+    hr = IMFTopologyNode_GetOutputPrefType(node, 0, &mediatype2);
+    ok(hr == E_FAIL, "Unexpected hr %#x.\n", hr);
+
+    hr = MFCreateMediaType(&mediatype2);
+    ok(hr == S_OK, "Failed to create media type, hr %#x.\n", hr);
+
+    /* Changing output type does not change input type. */
+    hr = IMFTopologyNode_SetOutputPrefType(node, 4, mediatype2);
+    ok(hr == S_OK, "Failed to set preferred type, hr %#x.\n", hr);
+
+    hr = IMFTopologyNode_GetInputPrefType(node, 0, &mediatype3);
+    ok(hr == S_OK, "Failed to get preferred type, hr %#x.\n", hr);
+    ok(mediatype3 == mediatype, "Unexpected mediatype instance.\n");
+    IMFMediaType_Release(mediatype3);
+
+    IMFMediaType_Release(mediatype2);
+
     hr = IMFTopologyNode_GetInputCount(node, &count);
     ok(hr == S_OK, "Failed to get output count, hr %#x.\n", hr);
     ok(count == 0, "Unexpected count %u.\n", count);
@@ -546,6 +566,10 @@ static void test_topology(void)
     hr = IMFTopologyNode_SetInputPrefType(node, 3, mediatype);
     ok(hr == S_OK, "Failed to set preferred type, hr %#x.\n", hr);
 
+    hr = IMFTopologyNode_GetInputCount(node, &count);
+    ok(hr == S_OK, "Failed to get input count, hr %#x.\n", hr);
+    ok(count == 4, "Unexpected count %u.\n", count);
+
     hr = IMFTopologyNode_SetOutputPrefType(node, 4, mediatype);
     ok(hr == S_OK, "Failed to set preferred type, hr %#x.\n", hr);
 
@@ -800,6 +824,70 @@ static void test_topology(void)
     IMFTopology_Release(topology);
 }
 
+static void test_topology_tee_node(void)
+{
+    IMFTopologyNode *src_node, *tee_node;
+    IMFMediaType *mediatype, *mediatype2;
+    IMFTopology *topology;
+    unsigned int count;
+    HRESULT hr;
+
+    hr = MFCreateTopology(&topology);
+    ok(hr == S_OK, "Failed to create topology, hr %#x.\n", hr);
+
+    hr = MFCreateMediaType(&mediatype);
+    ok(hr == S_OK, "Failed to create media type, hr %#x.\n", hr);
+
+    hr = MFCreateTopologyNode(MF_TOPOLOGY_TEE_NODE, &tee_node);
+    ok(hr == S_OK, "Failed to create topology node, hr %#x.\n", hr);
+
+    hr = MFCreateTopologyNode(MF_TOPOLOGY_SOURCESTREAM_NODE, &src_node);
+    ok(hr == S_OK, "Failed to create topology node, hr %#x.\n", hr);
+
+    hr = IMFTopologyNode_SetInputPrefType(tee_node, 0, mediatype);
+    ok(hr == S_OK, "Failed to set type, hr %#x.\n", hr);
+
+    /* Even though tee node has only one input and source has only one output,
+       it's possible to connect to higher inputs/outputs. */
+
+    /* SRC(0) -> TEE(0) */
+    hr = IMFTopologyNode_ConnectOutput(src_node, 0, tee_node, 0);
+    ok(hr == S_OK, "Failed to connect nodes, hr %#x.\n", hr);
+
+    hr = IMFTopologyNode_GetInputCount(tee_node, &count);
+    ok(hr == S_OK, "Failed to get count, hr %#x.\n", hr);
+    ok(count == 1, "Unexpected count %u.\n", count);
+
+    hr = IMFTopologyNode_GetInputPrefType(tee_node, 0, &mediatype2);
+    ok(hr == S_OK, "Failed to get type, hr %#x.\n", hr);
+    ok(mediatype2 == mediatype, "Unexpected type.\n");
+    IMFMediaType_Release(mediatype2);
+
+    /* SRC(0) -> TEE(1) */
+    hr = IMFTopologyNode_ConnectOutput(src_node, 0, tee_node, 1);
+    ok(hr == S_OK, "Failed to connect nodes, hr %#x.\n", hr);
+
+    hr = IMFTopologyNode_GetInputCount(tee_node, &count);
+    ok(hr == S_OK, "Failed to get count, hr %#x.\n", hr);
+    ok(count == 2, "Unexpected count %u.\n", count);
+
+    hr = IMFTopologyNode_SetInputPrefType(tee_node, 1, mediatype);
+    ok(hr == MF_E_INVALIDTYPE, "Unexpected hr %#x.\n", hr);
+
+    /* SRC(1) -> TEE(1) */
+    hr = IMFTopologyNode_ConnectOutput(src_node, 1, tee_node, 1);
+    ok(hr == S_OK, "Failed to connect nodes, hr %#x.\n", hr);
+
+    hr = IMFTopologyNode_GetOutputCount(src_node, &count);
+    ok(hr == S_OK, "Failed to get count, hr %#x.\n", hr);
+    ok(count == 2, "Unexpected count %u.\n", count);
+
+    IMFMediaType_Release(mediatype);
+    IMFTopologyNode_Release(src_node);
+    IMFTopologyNode_Release(tee_node);
+    IMFTopology_Release(topology);
+}
+
 static HRESULT WINAPI test_getservice_QI(IMFGetService *iface, REFIID riid, void **obj)
 {
     if (IsEqualIID(riid, &IID_IMFGetService) || IsEqualIID(riid, &IID_IUnknown))
@@ -3725,6 +3813,7 @@ static void test_MFGetTopoNodeCurrentType(void)
 START_TEST(mf)
 {
     test_topology();
+    test_topology_tee_node();
     test_topology_loader();
     test_MFGetService();
     test_sequencer_source();
diff --git a/dlls/mf/topology.c b/dlls/mf/topology.c
index 0b4d7344422..91635fd6b8b 100644
--- a/dlls/mf/topology.c
+++ b/dlls/mf/topology.c
@@ -61,6 +61,7 @@ struct topology_node
     MF_TOPOLOGY_TYPE node_type;
     TOPOID id;
     IUnknown *object;
+    IMFMediaType *input_type; /* Only for tee nodes. */
     struct node_streams inputs;
     struct node_streams outputs;
     CRITICAL_SECTION cs;
@@ -950,6 +951,8 @@ static ULONG WINAPI topology_node_Release(IMFTopologyNode *iface)
     {
         if (node->object)
             IUnknown_Release(node->object);
+        if (node->input_type)
+            IMFMediaType_Release(node->input_type);
         for (i = 0; i < node->inputs.count; ++i)
         {
             if (node->inputs.streams[i].preferred_type)
@@ -1361,14 +1364,7 @@ static HRESULT WINAPI topology_node_GetInputCount(IMFTopologyNode *iface, DWORD
 
     TRACE("%p, %p.\n", iface, count);
 
-    switch (node->node_type)
-    {
-        case MF_TOPOLOGY_TEE_NODE:
-            *count = 0;
-            break;
-        default:
-            *count = node->inputs.count;
-    }
+    *count = node->inputs.count;
 
     return S_OK;
 }
@@ -1384,6 +1380,15 @@ static HRESULT WINAPI topology_node_GetOutputCount(IMFTopologyNode *iface, DWORD
     return S_OK;
 }
 
+static void topology_node_set_stream_type(struct node_stream *stream, IMFMediaType *mediatype)
+{
+    if (stream->preferred_type)
+        IMFMediaType_Release(stream->preferred_type);
+    stream->preferred_type = mediatype;
+    if (stream->preferred_type)
+        IMFMediaType_AddRef(stream->preferred_type);
+}
+
 static HRESULT topology_node_connect_output(struct topology_node *node, DWORD output_index,
         struct topology_node *connection, DWORD input_index)
 {
@@ -1406,7 +1411,16 @@ static HRESULT topology_node_connect_output(struct topology_node *node, DWORD ou
 
     hr = topology_node_reserve_streams(&node->outputs, output_index);
     if (SUCCEEDED(hr))
+    {
+        size_t old_count = connection->inputs.count;
         hr = topology_node_reserve_streams(&connection->inputs, input_index);
+        if (SUCCEEDED(hr) && !old_count && connection->input_type)
+        {
+            topology_node_set_stream_type(connection->inputs.streams, connection->input_type);
+            IMFMediaType_Release(connection->input_type);
+            connection->input_type = NULL;
+        }
+    }
 
     if (SUCCEEDED(hr))
     {
@@ -1524,13 +1538,7 @@ static HRESULT WINAPI topology_node_SetOutputPrefType(IMFTopologyNode *iface, DW
     if (node->node_type != MF_TOPOLOGY_OUTPUT_NODE)
     {
         if (SUCCEEDED(hr = topology_node_reserve_streams(&node->outputs, index)))
-        {
-            if (node->outputs.streams[index].preferred_type)
-                IMFMediaType_Release(node->outputs.streams[index].preferred_type);
-            node->outputs.streams[index].preferred_type = mediatype;
-            if (node->outputs.streams[index].preferred_type)
-                IMFMediaType_AddRef(node->outputs.streams[index].preferred_type);
-        }
+            topology_node_set_stream_type(&node->outputs.streams[index], mediatype);
     }
     else
         hr = E_NOTIMPL;
@@ -1540,6 +1548,18 @@ static HRESULT WINAPI topology_node_SetOutputPrefType(IMFTopologyNode *iface, DW
     return hr;
 }
 
+static HRESULT topology_node_get_pref_type(struct node_streams *streams, unsigned int index, IMFMediaType **mediatype)
+{
+    *mediatype = streams->streams[index].preferred_type;
+    if (*mediatype)
+    {
+        IMFMediaType_AddRef(*mediatype);
+        return S_OK;
+    }
+
+    return E_FAIL;
+}
+
 static HRESULT WINAPI topology_node_GetOutputPrefType(IMFTopologyNode *iface, DWORD index, IMFMediaType **mediatype)
 {
     struct topology_node *node = impl_from_IMFTopologyNode(iface);
@@ -1550,13 +1570,7 @@ static HRESULT WINAPI topology_node_GetOutputPrefType(IMFTopologyNode *iface, DW
     EnterCriticalSection(&node->cs);
 
     if (index < node->outputs.count)
-    {
-        *mediatype = node->outputs.streams[index].preferred_type;
-        if (*mediatype)
-            IMFMediaType_AddRef(*mediatype);
-        else
-            hr = E_FAIL;
-    }
+        hr = topology_node_get_pref_type(&node->outputs, index, mediatype);
     else
         hr = E_INVALIDARG;
 
@@ -1574,25 +1588,40 @@ static HRESULT WINAPI topology_node_SetInputPrefType(IMFTopologyNode *iface, DWO
 
     EnterCriticalSection(&node->cs);
 
-    if (node->node_type != MF_TOPOLOGY_SOURCESTREAM_NODE && !(index > 0 && node->node_type == MF_TOPOLOGY_TEE_NODE))
+    switch (node->node_type)
     {
-        if (SUCCEEDED(hr = topology_node_reserve_streams(&node->inputs, index)))
-        {
-            if (index >= node->inputs.count)
+        case MF_TOPOLOGY_TEE_NODE:
+            if (index)
             {
-                memset(&node->inputs.streams[node->inputs.count], 0,
-                        (index - node->inputs.count + 1) * sizeof(*node->inputs.streams));
-                node->inputs.count = index + 1;
+                hr = MF_E_INVALIDTYPE;
+                break;
+            }
+            if (node->inputs.count)
+                topology_node_set_stream_type(&node->inputs.streams[index], mediatype);
+            else
+            {
+                if (node->input_type)
+                    IMFMediaType_Release(node->input_type);
+                node->input_type = mediatype;
+                if (node->input_type)
+                    IMFMediaType_AddRef(node->input_type);
+            }
+            break;
+        case MF_TOPOLOGY_SOURCESTREAM_NODE:
+            hr = E_NOTIMPL;
+            break;
+        default:
+            if (SUCCEEDED(hr = topology_node_reserve_streams(&node->inputs, index)))
+            {
+                if (index >= node->inputs.count)
+                {
+                    memset(&node->inputs.streams[node->inputs.count], 0,
+                            (index - node->inputs.count + 1) * sizeof(*node->inputs.streams));
+                    node->inputs.count = index + 1;
+                }
+                topology_node_set_stream_type(&node->inputs.streams[index], mediatype);
             }
-            if (node->inputs.streams[index].preferred_type)
-                IMFMediaType_Release(node->inputs.streams[index].preferred_type);
-            node->inputs.streams[index].preferred_type = mediatype;
-            if (node->inputs.streams[index].preferred_type)
-                IMFMediaType_AddRef(node->inputs.streams[index].preferred_type);
-        }
     }
-    else
-        hr = node->node_type == MF_TOPOLOGY_TEE_NODE ? MF_E_INVALIDTYPE : E_NOTIMPL;
 
     LeaveCriticalSection(&node->cs);
 
@@ -1610,11 +1639,12 @@ static HRESULT WINAPI topology_node_GetInputPrefType(IMFTopologyNode *iface, DWO
 
     if (index < node->inputs.count)
     {
-        *mediatype = node->inputs.streams[index].preferred_type;
-        if (*mediatype)
-            IMFMediaType_AddRef(*mediatype);
-        else
-            hr = E_FAIL;
+        hr = topology_node_get_pref_type(&node->inputs, index, mediatype);
+    }
+    else if (node->node_type == MF_TOPOLOGY_TEE_NODE && node->input_type)
+    {
+        *mediatype = node->input_type;
+        IMFMediaType_AddRef(*mediatype);
     }
     else
         hr = E_INVALIDARG;
-- 
2.26.2




More information about the wine-devel mailing list