Nikolay Sivov : mf: Rework node collection implementation.

Alexandre Julliard julliard at winehq.org
Wed May 8 18:22:47 CDT 2019


Module: wine
Branch: master
Commit: 184f99945975728d0ac4a3c544b13f1b40bf1c9c
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=184f99945975728d0ac4a3c544b13f1b40bf1c9c

Author: Nikolay Sivov <nsivov at codeweavers.com>
Date:   Wed May  8 14:46:41 2019 +0300

mf: Rework node collection implementation.

Signed-off-by: Nikolay Sivov <nsivov at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/mf/topology.c | 193 +++++++++++++++++++++++++++--------------------------
 1 file changed, 99 insertions(+), 94 deletions(-)

diff --git a/dlls/mf/topology.c b/dlls/mf/topology.c
index eaae7c9..c10bc6a 100644
--- a/dlls/mf/topology.c
+++ b/dlls/mf/topology.c
@@ -45,15 +45,6 @@ WINE_DEFAULT_DEBUG_CHANNEL(mfplat);
 static LONG next_node_id;
 static TOPOID next_topology_id;
 
-struct topology
-{
-    IMFTopology IMFTopology_iface;
-    LONG refcount;
-    IMFAttributes *attributes;
-    IMFCollection *nodes;
-    TOPOID id;
-};
-
 struct node_stream
 {
     IMFMediaType *preferred_type;
@@ -81,6 +72,20 @@ struct topology_node
     CRITICAL_SECTION cs;
 };
 
+struct topology
+{
+    IMFTopology IMFTopology_iface;
+    LONG refcount;
+    IMFAttributes *attributes;
+    struct
+    {
+        struct topology_node **nodes;
+        size_t size;
+        size_t count;
+    } nodes;
+    TOPOID id;
+};
+
 struct topology_loader
 {
     IMFTopoLoader IMFTopoLoader_iface;
@@ -169,19 +174,32 @@ static ULONG WINAPI topology_AddRef(IMFTopology *iface)
     return refcount;
 }
 
+static void topology_clear(struct topology *topology)
+{
+    size_t i;
+
+    for (i = 0; i < topology->nodes.count; ++i)
+    {
+        IMFTopologyNode_Release(&topology->nodes.nodes[i]->IMFTopologyNode_iface);
+    }
+    heap_free(topology->nodes.nodes);
+    topology->nodes.nodes = NULL;
+    topology->nodes.count = 0;
+    topology->nodes.size = 0;
+}
+
 static ULONG WINAPI topology_Release(IMFTopology *iface)
 {
     struct topology *topology = impl_from_IMFTopology(iface);
     ULONG refcount = InterlockedDecrement(&topology->refcount);
 
-    TRACE("(%p) refcount=%u\n", iface, refcount);
+    TRACE("%p, refcount %u.\n", iface, refcount);
 
     if (!refcount)
     {
         if (topology->attributes)
             IMFAttributes_Release(topology->attributes);
-        if (topology->nodes)
-            IMFCollection_Release(topology->nodes);
+        topology_clear(topology);
         heap_free(topology);
     }
 
@@ -476,80 +494,72 @@ static HRESULT WINAPI topology_GetTopologyID(IMFTopology *iface, TOPOID *id)
     return S_OK;
 }
 
-static HRESULT topology_get_node_by_id(const struct topology *topology, TOPOID id, IMFTopologyNode **node)
+static HRESULT topology_get_node_by_id(const struct topology *topology, TOPOID id, struct topology_node **node)
 {
-    IMFTopologyNode *iter;
-    unsigned int i = 0;
+    size_t i = 0;
 
-    while (IMFCollection_GetElement(topology->nodes, i++, (IUnknown **)&iter) == S_OK)
+    for (i = 0; i < topology->nodes.count; ++i)
     {
-        TOPOID node_id;
-        HRESULT hr;
-
-        hr = IMFTopologyNode_GetTopoNodeID(iter, &node_id);
-        if (FAILED(hr))
-        {
-            IMFTopologyNode_Release(iter);
-            return hr;
-        }
-
-        if (node_id == id)
+        if (topology->nodes.nodes[i]->id == id)
         {
-            *node = iter;
+            *node = topology->nodes.nodes[i];
+            IMFTopologyNode_AddRef(&(*node)->IMFTopologyNode_iface);
             return S_OK;
         }
-
-        IMFTopologyNode_Release(iter);
     }
 
     return MF_E_NOT_FOUND;
 }
 
-static HRESULT WINAPI topology_AddNode(IMFTopology *iface, IMFTopologyNode *node)
+static HRESULT WINAPI topology_AddNode(IMFTopology *iface, IMFTopologyNode *node_iface)
 {
     struct topology *topology = impl_from_IMFTopology(iface);
-    IMFTopologyNode *match;
-    HRESULT hr;
-    TOPOID id;
+    struct topology_node *node = unsafe_impl_from_IMFTopologyNode(node_iface);
+    struct topology_node *match;
 
-    TRACE("(%p)->(%p)\n", iface, node);
+    TRACE("%p, %p.\n", iface, node_iface);
 
     if (!node)
         return E_POINTER;
 
-    if (FAILED(hr = IMFTopologyNode_GetTopoNodeID(node, &id)))
-        return hr;
+    if (SUCCEEDED(topology_get_node_by_id(topology, node->id, &match)))
+    {
+        IMFTopologyNode_Release(&match->IMFTopologyNode_iface);
+        return E_INVALIDARG;
+    }
 
-    if (FAILED(topology_get_node_by_id(topology, id, &match)))
-        return IMFCollection_AddElement(topology->nodes, (IUnknown *)node);
+    if (!mf_array_reserve((void **)&topology->nodes.nodes, &topology->nodes.size, topology->nodes.count + 1,
+            sizeof(*topology->nodes.nodes)))
+    {
+        return E_OUTOFMEMORY;
+    }
 
-    IMFTopologyNode_Release(match);
+    topology->nodes.nodes[topology->nodes.count++] = node;
+    IMFTopologyNode_AddRef(&node->IMFTopologyNode_iface);
 
-    return E_INVALIDARG;
+    return S_OK;
 }
 
 static HRESULT WINAPI topology_RemoveNode(IMFTopology *iface, IMFTopologyNode *node)
 {
     struct topology *topology = impl_from_IMFTopology(iface);
-    unsigned int i = 0;
-    IUnknown *element;
+    size_t i, count;
 
-    TRACE("(%p)->(%p)\n", iface, node);
+    TRACE("%p, %p.\n", iface, node);
 
-    while (IMFCollection_GetElement(topology->nodes, i, &element) == S_OK)
+    for (i = 0; i < topology->nodes.count; ++i)
     {
-        BOOL match = element == (IUnknown *)node;
-
-        IUnknown_Release(element);
-
-        if (match)
+        if (&topology->nodes.nodes[i]->IMFTopologyNode_iface == node)
         {
-            IMFCollection_RemoveElement(topology->nodes, i, &element);
-            IUnknown_Release(element);
+            count = topology->nodes.count - i - 1;
+            if (count)
+            {
+                memmove(&topology->nodes.nodes[i], &topology->nodes.nodes[i + 1],
+                        count * sizeof(*topology->nodes.nodes));
+            }
+            topology->nodes.count--;
             return S_OK;
         }
-
-        ++i;
     }
 
     return E_INVALIDARG;
@@ -558,38 +568,43 @@ static HRESULT WINAPI topology_RemoveNode(IMFTopology *iface, IMFTopologyNode *n
 static HRESULT WINAPI topology_GetNodeCount(IMFTopology *iface, WORD *count)
 {
     struct topology *topology = impl_from_IMFTopology(iface);
-    DWORD nodecount;
-    HRESULT hr;
 
-    TRACE("(%p)->(%p)\n", iface, count);
+    TRACE("%p, %p.\n", iface, count);
 
-    hr = IMFCollection_GetElementCount(topology->nodes, count ? &nodecount : NULL);
-    if (count)
-        *count = nodecount;
+    if (!count)
+        return E_POINTER;
 
-    return hr;
+    *count = topology->nodes.count;
+
+    return S_OK;
 }
 
 static HRESULT WINAPI topology_GetNode(IMFTopology *iface, WORD index, IMFTopologyNode **node)
 {
     struct topology *topology = impl_from_IMFTopology(iface);
 
-    TRACE("(%p)->(%u, %p)\n", iface, index, node);
+    TRACE("%p, %u, %p.\n", iface, index, node);
 
     if (!node)
         return E_POINTER;
 
-    return SUCCEEDED(IMFCollection_GetElement(topology->nodes, index, (IUnknown **)node)) ?
-            S_OK : MF_E_INVALIDINDEX;
+    if (index >= topology->nodes.count)
+        return MF_E_INVALIDINDEX;
+
+    *node = &topology->nodes.nodes[index]->IMFTopologyNode_iface;
+    IMFTopologyNode_AddRef(*node);
+
+    return S_OK;
 }
 
 static HRESULT WINAPI topology_Clear(IMFTopology *iface)
 {
     struct topology *topology = impl_from_IMFTopology(iface);
 
-    TRACE("(%p)\n", iface);
+    TRACE("%p.\n", iface);
 
-    return IMFCollection_RemoveAllElements(topology->nodes);
+    topology_clear(topology);
+    return S_OK;
 }
 
 static HRESULT WINAPI topology_CloneFrom(IMFTopology *iface, IMFTopology *src_topology)
@@ -599,36 +614,27 @@ static HRESULT WINAPI topology_CloneFrom(IMFTopology *iface, IMFTopology *src_to
     return E_NOTIMPL;
 }
 
-static HRESULT WINAPI topology_GetNodeByID(IMFTopology *iface, TOPOID id, IMFTopologyNode **node)
+static HRESULT WINAPI topology_GetNodeByID(IMFTopology *iface, TOPOID id, IMFTopologyNode **ret)
 {
     struct topology *topology = impl_from_IMFTopology(iface);
-
-    TRACE("(%p)->(%p)\n", iface, node);
-
-    return topology_get_node_by_id(topology, id, node);
-}
-
-static HRESULT topology_add_node_of_type(const struct topology *topology, IMFTopologyNode *node,
-        MF_TOPOLOGY_TYPE filter, IMFCollection *collection)
-{
-    MF_TOPOLOGY_TYPE node_type;
+    struct topology_node *node;
     HRESULT hr;
 
-    if (FAILED(hr = IMFTopologyNode_GetNodeType(node, &node_type)))
-        return hr;
+    TRACE("%p, %p.\n", iface, ret);
 
-    if (node_type != filter)
-        return S_OK;
+    if (SUCCEEDED(hr = topology_get_node_by_id(topology, id, &node)))
+        *ret = &node->IMFTopologyNode_iface;
+    else
+        *ret = NULL;
 
-    return IMFCollection_AddElement(collection, (IUnknown *)node);
+    return hr;
 }
 
 static HRESULT topology_get_node_collection(const struct topology *topology, MF_TOPOLOGY_TYPE node_type,
         IMFCollection **collection)
 {
-    IMFTopologyNode *node;
-    unsigned int i = 0;
     HRESULT hr;
+    size_t i;
 
     if (!collection)
         return E_POINTER;
@@ -636,15 +642,17 @@ static HRESULT topology_get_node_collection(const struct topology *topology, MF_
     if (FAILED(hr = MFCreateCollection(collection)))
         return hr;
 
-    while (IMFCollection_GetElement(topology->nodes, i++, (IUnknown **)&node) == S_OK)
+    for (i = 0; i < topology->nodes.count; ++i)
     {
-        hr = topology_add_node_of_type(topology, node, node_type, *collection);
-        IMFTopologyNode_Release(node);
-        if (FAILED(hr))
+        if (topology->nodes.nodes[i]->node_type == node_type)
         {
-            IMFCollection_Release(*collection);
-            *collection = NULL;
-            break;
+            if (FAILED(hr = IMFCollection_AddElement(*collection,
+                    (IUnknown *)&topology->nodes.nodes[i]->IMFTopologyNode_iface)))
+            {
+                IMFCollection_Release(*collection);
+                *collection = NULL;
+                break;
+            }
         }
     }
 
@@ -750,9 +758,6 @@ HRESULT WINAPI MFCreateTopology(IMFTopology **topology)
     object->refcount = 1;
 
     hr = MFCreateAttributes(&object->attributes, 0);
-    if (SUCCEEDED(hr))
-        hr = MFCreateCollection(&object->nodes);
-
     if (FAILED(hr))
     {
         IMFTopology_Release(&object->IMFTopology_iface);




More information about the wine-cvs mailing list