[PATCH 3/4] mf: Set preferred media types for nodes.

Nikolay Sivov nsivov at codeweavers.com
Tue May 7 07:25:44 CDT 2019


Signed-off-by: Nikolay Sivov <nsivov at codeweavers.com>
---
 dlls/mf/mf_private.h |  29 +++++++
 dlls/mf/tests/mf.c   | 163 +++++++++++++++++++++++++++++++++------
 dlls/mf/topology.c   | 176 ++++++++++++++++++++++++++++++++++++++-----
 3 files changed, 330 insertions(+), 38 deletions(-)

diff --git a/dlls/mf/mf_private.h b/dlls/mf/mf_private.h
index b5b4e84bba..45a3834eec 100644
--- a/dlls/mf/mf_private.h
+++ b/dlls/mf/mf_private.h
@@ -18,6 +18,35 @@
 
 #include "mfidl.h"
 
+#include "wine/heap.h"
+
+static inline BOOL mf_array_reserve(void **elements, size_t *capacity, size_t count, size_t size)
+{
+    size_t new_capacity, max_capacity;
+    void *new_elements;
+
+    if (count <= *capacity)
+        return TRUE;
+
+    max_capacity = ~(SIZE_T)0 / size;
+    if (count > max_capacity)
+        return FALSE;
+
+    new_capacity = max(4, *capacity);
+    while (new_capacity < count && new_capacity <= max_capacity / 2)
+        new_capacity *= 2;
+    if (new_capacity < count)
+        new_capacity = max_capacity;
+
+    if (!(new_elements = heap_realloc(*elements, new_capacity * size)))
+        return FALSE;
+
+    *elements = new_elements;
+    *capacity = new_capacity;
+
+    return TRUE;
+}
+
 struct activate_funcs
 {
     HRESULT (*create_object)(void *context, IUnknown **object);
diff --git a/dlls/mf/tests/mf.c b/dlls/mf/tests/mf.c
index cea5f98f6e..4974e043af 100644
--- a/dlls/mf/tests/mf.c
+++ b/dlls/mf/tests/mf.c
@@ -77,11 +77,12 @@ static void test_topology(void)
     IUnknown test_unk2 = { &test_unk_vtbl };
     IUnknown test_unk = { &test_unk_vtbl };
     IMFTopologyNode *node, *node2, *node3;
+    IMFMediaType *mediatype, *mediatype2;
     IMFTopology *topology, *topology2;
-    UINT32 attr_count;
     IUnknown *object;
+    WORD node_count;
+    UINT32 count;
     DWORD size;
-    WORD count;
     HRESULT hr;
     TOPOID id;
 
@@ -132,19 +133,19 @@ static void test_topology(void)
     hr = IMFTopology_AddNode(topology, NULL);
     ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr);
 
-    count = 1;
-    hr = IMFTopology_GetNodeCount(topology, &count);
+    node_count = 1;
+    hr = IMFTopology_GetNodeCount(topology, &node_count);
     ok(hr == S_OK, "Failed to get node count, hr %#x.\n", hr);
-    ok(count == 0, "Unexpected node count %u.\n", count);
+    ok(node_count == 0, "Unexpected node count %u.\n", node_count);
 
     /* Same id, different nodes. */
     hr = IMFTopology_AddNode(topology, node);
     ok(hr == S_OK, "Failed to add a node, hr %#x.\n", hr);
 
-    count = 0;
-    hr = IMFTopology_GetNodeCount(topology, &count);
+    node_count = 0;
+    hr = IMFTopology_GetNodeCount(topology, &node_count);
     ok(hr == S_OK, "Failed to get node count, hr %#x.\n", hr);
-    ok(count == 1, "Unexpected node count %u.\n", count);
+    ok(node_count == 1, "Unexpected node count %u.\n", node_count);
 
     hr = IMFTopology_AddNode(topology, node2);
     ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
@@ -190,10 +191,10 @@ static void test_topology(void)
     ok(hr == S_OK, "Failed to add a node, hr %#x.\n", hr);
     IMFTopologyNode_Release(node2);
 
-    count = 0;
-    hr = IMFTopology_GetNodeCount(topology, &count);
+    node_count = 0;
+    hr = IMFTopology_GetNodeCount(topology, &node_count);
     ok(hr == S_OK, "Failed to get node count, hr %#x.\n", hr);
-    ok(count == 2, "Unexpected node count %u.\n", count);
+    ok(node_count == 2, "Unexpected node count %u.\n", node_count);
 
     /* Remove with detached node, existing id. */
     hr = MFCreateTopologyNode(MF_TOPOLOGY_TEE_NODE, &node2);
@@ -207,18 +208,18 @@ static void test_topology(void)
     hr = IMFTopology_RemoveNode(topology, node);
     ok(hr == S_OK, "Failed to remove a node, hr %#x.\n", hr);
 
-    count = 0;
-    hr = IMFTopology_GetNodeCount(topology, &count);
+    node_count = 0;
+    hr = IMFTopology_GetNodeCount(topology, &node_count);
     ok(hr == S_OK, "Failed to get node count, hr %#x.\n", hr);
-    ok(count == 1, "Unexpected node count %u.\n", count);
+    ok(node_count == 1, "Unexpected node count %u.\n", node_count);
 
     hr = IMFTopology_Clear(topology);
     ok(hr == S_OK, "Failed to clear topology, hr %#x.\n", hr);
 
-    count = 1;
-    hr = IMFTopology_GetNodeCount(topology, &count);
+    node_count = 1;
+    hr = IMFTopology_GetNodeCount(topology, &node_count);
     ok(hr == S_OK, "Failed to get node count, hr %#x.\n", hr);
-    ok(count == 0, "Unexpected node count %u.\n", count);
+    ok(node_count == 0, "Unexpected node count %u.\n", node_count);
 
     hr = IMFTopology_Clear(topology);
     ok(hr == S_OK, "Failed to clear topology, hr %#x.\n", hr);
@@ -366,9 +367,9 @@ static void test_topology(void)
     hr = IMFTopologyNode_SetObject(node, &test_unk2);
     ok(hr == S_OK, "Failed to set object, hr %#x.\n", hr);
 
-    hr = IMFTopologyNode_GetCount(node, &attr_count);
+    hr = IMFTopologyNode_GetCount(node, &count);
     ok(hr == S_OK, "Failed to get attribute count, hr %#x.\n", hr);
-    ok(attr_count == 0, "Unexpected attribute count %u.\n", attr_count);
+    ok(count == 0, "Unexpected attribute count %u.\n", count);
 
     hr = IMFTopologyNode_SetGUID(node, &MF_TOPONODE_TRANSFORM_OBJECTID, &MF_TOPONODE_TRANSFORM_OBJECTID);
     ok(hr == S_OK, "Failed to set attribute, hr %#x.\n", hr);
@@ -381,12 +382,132 @@ static void test_topology(void)
     ok(hr == E_FAIL, "Unexpected hr %#x.\n", hr);
     ok(!object, "Unexpected object %p.\n", object);
 
-    hr = IMFTopologyNode_GetCount(node, &attr_count);
+    hr = IMFTopologyNode_GetCount(node, &count);
     ok(hr == S_OK, "Failed to get attribute count, hr %#x.\n", hr);
-    ok(attr_count == 1, "Unexpected attribute count %u.\n", attr_count);
+    ok(count == 1, "Unexpected attribute count %u.\n", count);
+
+    /* Preferred stream types. */
+    hr = IMFTopologyNode_GetInputCount(node, &count);
+    ok(hr == S_OK, "Failed to get input count, hr %#x.\n", hr);
+    ok(count == 0, "Unexpected count %u.\n", count);
+
+    hr = IMFTopologyNode_GetInputPrefType(node, 0, &mediatype);
+    ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
+
+    hr = MFCreateMediaType(&mediatype);
+    ok(hr == S_OK, "Failed to create media type, hr %#x.\n", hr);
+
+    hr = IMFTopologyNode_SetInputPrefType(node, 0, mediatype);
+    ok(hr == S_OK, "Failed to set preferred type, hr %#x.\n", hr);
+
+    hr = IMFTopologyNode_GetInputPrefType(node, 0, &mediatype2);
+    ok(hr == S_OK, "Failed to get preferred type, hr %#x.\n", hr);
+    ok(mediatype2 == mediatype, "Unexpected mediatype instance.\n");
+    IMFMediaType_Release(mediatype2);
+
+    hr = IMFTopologyNode_SetInputPrefType(node, 0, NULL);
+    ok(hr == S_OK, "Failed to set preferred type, hr %#x.\n", hr);
+
+    hr = IMFTopologyNode_GetInputPrefType(node, 0, &mediatype2);
+    ok(hr == E_FAIL, "Unexpected hr %#x.\n", hr);
+    ok(!mediatype2, "Unexpected mediatype instance.\n");
+
+    hr = IMFTopologyNode_SetInputPrefType(node, 1, mediatype);
+    ok(hr == S_OK, "Failed to set preferred type, hr %#x.\n", hr);
+
+    hr = IMFTopologyNode_SetInputPrefType(node, 1, 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 == 2, "Unexpected count %u.\n", count);
+
+    hr = IMFTopologyNode_GetOutputCount(node, &count);
+    ok(hr == S_OK, "Failed to get input count, hr %#x.\n", hr);
+    ok(count == 0, "Unexpected count %u.\n", count);
+
+    hr = IMFTopologyNode_SetOutputPrefType(node, 0, mediatype);
+    ok(hr == E_NOTIMPL, "Unexpected hr %#x.\n", hr);
+
+    IMFTopologyNode_Release(node);
+
+    /* Source node. */
+    hr = MFCreateTopologyNode(MF_TOPOLOGY_SOURCESTREAM_NODE, &node);
+    ok(hr == S_OK, "Failed to create a node, hr %#x.\n", hr);
+
+    hr = IMFTopologyNode_SetInputPrefType(node, 0, mediatype);
+    ok(hr == E_NOTIMPL, "Unexpected hr %#x.\n", hr);
+
+    hr = IMFTopologyNode_SetOutputPrefType(node, 2, mediatype);
+    ok(hr == S_OK, "Failed to set preferred type, hr %#x.\n", hr);
+
+    hr = IMFTopologyNode_GetOutputPrefType(node, 0, &mediatype2);
+    ok(hr == E_FAIL, "Failed to get preferred type, hr %#x.\n", hr);
+    ok(!mediatype2, "Unexpected mediatype instance.\n");
+
+    hr = IMFTopologyNode_GetOutputCount(node, &count);
+    ok(hr == S_OK, "Failed to get output count, hr %#x.\n", hr);
+    ok(count == 3, "Unexpected count %u.\n", count);
 
     IMFTopologyNode_Release(node);
 
+    /* Tee node. */
+    hr = MFCreateTopologyNode(MF_TOPOLOGY_TEE_NODE, &node);
+    ok(hr == S_OK, "Failed to create a node, hr %#x.\n", hr);
+
+    hr = IMFTopologyNode_SetInputPrefType(node, 0, mediatype);
+    ok(hr == S_OK, "Failed to set preferred type, hr %#x.\n", hr);
+
+    hr = IMFTopologyNode_GetInputPrefType(node, 0, &mediatype2);
+    ok(hr == S_OK, "Failed to get preferred type, hr %#x.\n", hr);
+    ok(mediatype2 == mediatype, "Unexpected mediatype instance.\n");
+    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);
+
+    hr = IMFTopologyNode_SetInputPrefType(node, 1, mediatype);
+    ok(hr == MF_E_INVALIDTYPE, "Unexpected hr %#x.\n", hr);
+
+    hr = IMFTopologyNode_SetInputPrefType(node, 3, mediatype);
+    ok(hr == MF_E_INVALIDTYPE, "Unexpected hr %#x.\n", hr);
+
+    hr = IMFTopologyNode_SetOutputPrefType(node, 4, 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 output count, hr %#x.\n", hr);
+    ok(count == 0, "Unexpected count %u.\n", count);
+
+    hr = IMFTopologyNode_GetOutputCount(node, &count);
+    ok(hr == S_OK, "Failed to get output count, hr %#x.\n", hr);
+    ok(count == 5, "Unexpected count %u.\n", count);
+
+    IMFTopologyNode_Release(node);
+
+    /* Transform node. */
+    hr = MFCreateTopologyNode(MF_TOPOLOGY_TRANSFORM_NODE, &node);
+    ok(hr == S_OK, "Failed to create a node, hr %#x.\n", hr);
+
+    hr = IMFTopologyNode_SetInputPrefType(node, 3, mediatype);
+    ok(hr == S_OK, "Failed to set preferred type, hr %#x.\n", hr);
+
+    hr = IMFTopologyNode_SetOutputPrefType(node, 4, 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 output count, hr %#x.\n", hr);
+    ok(count == 4, "Unexpected count %u.\n", count);
+
+    hr = IMFTopologyNode_GetOutputCount(node, &count);
+    ok(hr == S_OK, "Failed to get output count, hr %#x.\n", hr);
+    ok(count == 5, "Unexpected count %u.\n", count);
+
+    IMFTopologyNode_Release(node);
+
+    IMFMediaType_Release(mediatype);
+
     hr = IMFTopology_GetOutputNodeCollection(topology, &collection);
     ok(hr == S_OK || broken(hr == E_FAIL) /* before Win8 */, "Failed to get output node collection, hr %#x.\n", hr);
     if (SUCCEEDED(hr))
diff --git a/dlls/mf/topology.c b/dlls/mf/topology.c
index e01444b8ce..f40fe00c17 100644
--- a/dlls/mf/topology.c
+++ b/dlls/mf/topology.c
@@ -37,7 +37,8 @@
 #include "mfidl.h"
 
 #include "wine/debug.h"
-#include "wine/heap.h"
+
+#include "mf_private.h"
 
 WINE_DEFAULT_DEBUG_CHANNEL(mfplat);
 
@@ -53,6 +54,11 @@ struct topology
     TOPOID id;
 };
 
+struct node_stream
+{
+    IMFMediaType *preferred_type;
+};
+
 struct topology_node
 {
     IMFTopologyNode IMFTopologyNode_iface;
@@ -61,6 +67,18 @@ struct topology_node
     MF_TOPOLOGY_TYPE node_type;
     TOPOID id;
     IUnknown *object;
+    struct
+    {
+        struct node_stream *streams;
+        size_t size;
+        size_t count;
+    } inputs;
+    struct
+    {
+        struct node_stream *streams;
+        size_t size;
+        size_t count;
+    } outputs;
     CRITICAL_SECTION cs;
 };
 
@@ -758,6 +776,7 @@ static ULONG WINAPI topology_node_Release(IMFTopologyNode *iface)
 {
     struct topology_node *node = impl_from_IMFTopologyNode(iface);
     ULONG refcount = InterlockedDecrement(&node->refcount);
+    unsigned int i;
 
     TRACE("(%p) refcount=%u\n", iface, refcount);
 
@@ -765,6 +784,18 @@ static ULONG WINAPI topology_node_Release(IMFTopologyNode *iface)
     {
         if (node->object)
             IUnknown_Release(node->object);
+        for (i = 0; i < node->inputs.count; ++i)
+        {
+            if (node->inputs.streams[i].preferred_type)
+                IMFMediaType_Release(node->inputs.streams[i].preferred_type);
+        }
+        for (i = 0; i < node->outputs.count; ++i)
+        {
+            if (node->outputs.streams[i].preferred_type)
+                IMFMediaType_Release(node->outputs.streams[i].preferred_type);
+        }
+        heap_free(node->inputs.streams);
+        heap_free(node->outputs.streams);
         IMFAttributes_Release(node->attributes);
         DeleteCriticalSection(&node->cs);
         heap_free(node);
@@ -1154,16 +1185,31 @@ static HRESULT WINAPI topology_node_SetTopoNodeID(IMFTopologyNode *iface, TOPOID
 
 static HRESULT WINAPI topology_node_GetInputCount(IMFTopologyNode *iface, DWORD *count)
 {
-    FIXME("(%p)->(%p)\n", iface, count);
+    struct topology_node *node = impl_from_IMFTopologyNode(iface);
 
-    return E_NOTIMPL;
+    TRACE("%p, %p.\n", iface, count);
+
+    switch (node->node_type)
+    {
+        case MF_TOPOLOGY_TEE_NODE:
+            *count = 0;
+            break;
+        default:
+            *count = node->inputs.count;
+    }
+
+    return S_OK;
 }
 
 static HRESULT WINAPI topology_node_GetOutputCount(IMFTopologyNode *iface, DWORD *count)
 {
-    FIXME("(%p)->(%p)\n", iface, count);
+    struct topology_node *node = impl_from_IMFTopologyNode(iface);
 
-    return E_NOTIMPL;
+    TRACE("%p, %p.\n", iface, count);
+
+    *count = node->outputs.count;
+
+    return S_OK;
 }
 
 static HRESULT WINAPI topology_node_ConnectOutput(IMFTopologyNode *iface, DWORD output_index,
@@ -1197,32 +1243,128 @@ static HRESULT WINAPI topology_node_GetOutput(IMFTopologyNode *iface, DWORD outp
     return E_NOTIMPL;
 }
 
-static HRESULT WINAPI topology_node_SetOutputPrefType(IMFTopologyNode *iface, DWORD index, IMFMediaType *type)
+static HRESULT WINAPI topology_node_SetOutputPrefType(IMFTopologyNode *iface, DWORD index, IMFMediaType *mediatype)
 {
-    FIXME("(%p)->(%u, %p)\n", iface, index, type);
+    struct topology_node *node = impl_from_IMFTopologyNode(iface);
+    HRESULT hr = S_OK;
 
-    return E_NOTIMPL;
+    TRACE("%p, %u, %p.\n", iface, index, mediatype);
+
+    EnterCriticalSection(&node->cs);
+
+    if (node->node_type != MF_TOPOLOGY_OUTPUT_NODE)
+    {
+        if (mf_array_reserve((void **)&node->outputs.streams, &node->outputs.size, index + 1,
+                sizeof(*node->outputs.streams)))
+        {
+            if (index >= node->outputs.count)
+            {
+                memset(&node->outputs.streams[node->outputs.count], 0,
+                        (index - node->outputs.count + 1) * sizeof(*node->outputs.streams));
+                node->outputs.count = index + 1;
+            }
+            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);
+        }
+        else
+            hr = E_OUTOFMEMORY;
+    }
+    else
+        hr = E_NOTIMPL;
+
+    LeaveCriticalSection(&node->cs);
+
+    return hr;
 }
 
-static HRESULT WINAPI topology_node_GetOutputPrefType(IMFTopologyNode *iface, DWORD output_index, IMFMediaType **type)
+static HRESULT WINAPI topology_node_GetOutputPrefType(IMFTopologyNode *iface, DWORD index, IMFMediaType **mediatype)
 {
-    FIXME("(%p)->(%u, %p)\n", iface, output_index, type);
+    struct topology_node *node = impl_from_IMFTopologyNode(iface);
+    HRESULT hr = S_OK;
 
-    return E_NOTIMPL;
+    TRACE("%p, %u, %p.\n", iface, index, mediatype);
+
+    EnterCriticalSection(&node->cs);
+
+    if (index < node->outputs.count)
+    {
+        *mediatype = node->outputs.streams[index].preferred_type;
+        if (*mediatype)
+            IMFMediaType_AddRef(*mediatype);
+        else
+            hr = E_FAIL;
+    }
+    else
+        hr = E_INVALIDARG;
+
+    LeaveCriticalSection(&node->cs);
+
+    return hr;
 }
 
-static HRESULT WINAPI topology_node_SetInputPrefType(IMFTopologyNode *iface, DWORD index, IMFMediaType *type)
+static HRESULT WINAPI topology_node_SetInputPrefType(IMFTopologyNode *iface, DWORD index, IMFMediaType *mediatype)
 {
-    FIXME("(%p)->(%u, %p)\n", iface, index, type);
+    struct topology_node *node = impl_from_IMFTopologyNode(iface);
+    HRESULT hr = S_OK;
 
-    return E_NOTIMPL;
+    TRACE("%p, %u, %p.\n", iface, index, mediatype);
+
+    EnterCriticalSection(&node->cs);
+
+    if (node->node_type != MF_TOPOLOGY_SOURCESTREAM_NODE && !(index > 0 && node->node_type == MF_TOPOLOGY_TEE_NODE))
+    {
+        if (mf_array_reserve((void **)&node->inputs.streams, &node->inputs.size, index + 1,
+                sizeof(*node->inputs.streams)))
+        {
+            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;
+            }
+            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 = E_OUTOFMEMORY;
+    }
+    else
+        hr = node->node_type == MF_TOPOLOGY_TEE_NODE ? MF_E_INVALIDTYPE : E_NOTIMPL;
+
+    LeaveCriticalSection(&node->cs);
+
+    return hr;
 }
 
-static HRESULT WINAPI topology_node_GetInputPrefType(IMFTopologyNode *iface, DWORD index, IMFMediaType **type)
+static HRESULT WINAPI topology_node_GetInputPrefType(IMFTopologyNode *iface, DWORD index, IMFMediaType **mediatype)
 {
-    FIXME("(%p)->(%u, %p)\n", iface, index, type);
+    struct topology_node *node = impl_from_IMFTopologyNode(iface);
+    HRESULT hr = S_OK;
 
-    return E_NOTIMPL;
+    TRACE("%p, %u, %p.\n", iface, index, mediatype);
+
+    EnterCriticalSection(&node->cs);
+
+    if (index < node->inputs.count)
+    {
+        *mediatype = node->inputs.streams[index].preferred_type;
+        if (*mediatype)
+            IMFMediaType_AddRef(*mediatype);
+        else
+            hr = E_FAIL;
+    }
+    else
+        hr = E_INVALIDARG;
+
+    LeaveCriticalSection(&node->cs);
+
+    return hr;
 }
 
 static HRESULT WINAPI topology_node_CloneFrom(IMFTopologyNode *iface, IMFTopologyNode *node)
-- 
2.20.1




More information about the wine-devel mailing list