mf: Clone node connections when cloning topology.

Signed-off-by: Nikolay Sivov <nsivov@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Nikolay Sivov 2019-10-07 15:57:01 +03:00 committed by Alexandre Julliard
parent 88c8578459
commit bc7ae4d83c
1 changed files with 81 additions and 45 deletions

View File

@ -111,6 +111,10 @@ static struct topology_node *unsafe_impl_from_IMFTopologyNode(IMFTopologyNode *i
return impl_from_IMFTopologyNode(iface);
}
static HRESULT create_topology_node(MF_TOPOLOGY_TYPE node_type, struct topology_node **node);
static HRESULT topology_node_connect_output(struct topology_node *node, DWORD output_index,
struct topology_node *connection, DWORD input_index);
static struct topology *unsafe_impl_from_IMFTopology(IMFTopology *iface);
static struct topology_loader *impl_from_IMFTopoLoader(IMFTopoLoader *iface)
@ -568,7 +572,6 @@ static HRESULT topology_get_node_by_id(const struct topology *topology, TOPOID i
if (topology->nodes.nodes[i]->id == id)
{
*node = topology->nodes.nodes[i];
IMFTopologyNode_AddRef(&(*node)->IMFTopologyNode_iface);
return S_OK;
}
}
@ -576,19 +579,15 @@ static HRESULT topology_get_node_by_id(const struct topology *topology, TOPOID i
return MF_E_NOT_FOUND;
}
static HRESULT topology_add_node(struct topology *topology, IMFTopologyNode *node_iface)
static HRESULT topology_add_node(struct topology *topology, struct topology_node *node)
{
struct topology_node *node = unsafe_impl_from_IMFTopologyNode(node_iface);
struct topology_node *match;
if (!node)
return E_POINTER;
if (SUCCEEDED(topology_get_node_by_id(topology, node->id, &match)))
{
IMFTopologyNode_Release(&match->IMFTopologyNode_iface);
return E_INVALIDARG;
}
if (!mf_array_reserve((void **)&topology->nodes.nodes, &topology->nodes.size, topology->nodes.count + 1,
sizeof(*topology->nodes.nodes)))
@ -602,11 +601,12 @@ static HRESULT topology_add_node(struct topology *topology, IMFTopologyNode *nod
return S_OK;
}
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);
struct topology_node *node = unsafe_impl_from_IMFTopologyNode(node_iface);
TRACE("%p, %p.\n", iface, node);
TRACE("%p, %p.\n", iface, node_iface);
return topology_add_node(topology, node);
}
@ -684,9 +684,9 @@ static HRESULT WINAPI topology_CloneFrom(IMFTopology *iface, IMFTopology *src)
{
struct topology *topology = impl_from_IMFTopology(iface);
struct topology *src_topology = unsafe_impl_from_IMFTopology(src);
IMFTopologyNode *node;
struct topology_node *node;
size_t i, j;
HRESULT hr;
size_t i;
TRACE("%p, %p.\n", iface, src);
@ -695,19 +695,36 @@ static HRESULT WINAPI topology_CloneFrom(IMFTopology *iface, IMFTopology *src)
/* Clone nodes. */
for (i = 0; i < src_topology->nodes.count; ++i)
{
if (FAILED(hr = MFCreateTopologyNode(src_topology->nodes.nodes[i]->node_type, &node)))
if (FAILED(hr = create_topology_node(src_topology->nodes.nodes[i]->node_type, &node)))
{
WARN("Failed to create a node, hr %#x.\n", hr);
break;
}
if (SUCCEEDED(hr = IMFTopologyNode_CloneFrom(node, &src_topology->nodes.nodes[i]->IMFTopologyNode_iface)))
if (SUCCEEDED(hr = IMFTopologyNode_CloneFrom(&node->IMFTopologyNode_iface,
&src_topology->nodes.nodes[i]->IMFTopologyNode_iface)))
{
topology_add_node(topology, node);
}
IMFTopologyNode_Release(node);
IMFTopologyNode_Release(&node->IMFTopologyNode_iface);
}
FIXME("Clone node connections.\n");
/* Clone connections. */
for (i = 0; i < src_topology->nodes.count; ++i)
{
const struct node_streams *outputs = &src_topology->nodes.nodes[i]->outputs;
for (j = 0; j < outputs->count; ++j)
{
DWORD input_index = outputs->streams[j].connection_stream;
TOPOID id = outputs->streams[j].connection->id;
/* Skip node lookup in destination topology, assuming same node order. */
if (SUCCEEDED(hr = topology_get_node_by_id(topology, id, &node)))
topology_node_connect_output(topology->nodes.nodes[i], j, node, input_index);
}
}
/* Copy attributes and id. */
hr = IMFTopology_CopyAllItems(src, (IMFAttributes *)&topology->IMFTopology_iface);
@ -726,7 +743,10 @@ static HRESULT WINAPI topology_GetNodeByID(IMFTopology *iface, TOPOID id, IMFTop
TRACE("%p, %p.\n", iface, ret);
if (SUCCEEDED(hr = topology_get_node_by_id(topology, id, &node)))
{
*ret = &node->IMFTopologyNode_iface;
IMFTopologyNode_AddRef(*ret);
}
else
*ret = NULL;
@ -1358,22 +1378,12 @@ static HRESULT WINAPI topology_node_GetOutputCount(IMFTopologyNode *iface, DWORD
return S_OK;
}
static HRESULT WINAPI topology_node_ConnectOutput(IMFTopologyNode *iface, DWORD output_index,
IMFTopologyNode *peer, DWORD input_index)
static HRESULT topology_node_connect_output(struct topology_node *node, DWORD output_index,
struct topology_node *connection, DWORD input_index)
{
struct topology_node *node = impl_from_IMFTopologyNode(iface);
struct topology_node *connection = unsafe_impl_from_IMFTopologyNode(peer);
struct node_stream *stream;
HRESULT hr;
TRACE("%p, %u, %p, %u.\n", iface, output_index, peer, input_index);
if (!connection)
{
WARN("External node implementations are not supported.\n");
return E_UNEXPECTED;
}
if (node->node_type == MF_TOPOLOGY_OUTPUT_NODE || connection->node_type == MF_TOPOLOGY_SOURCESTREAM_NODE)
return E_FAIL;
@ -1408,6 +1418,23 @@ static HRESULT WINAPI topology_node_ConnectOutput(IMFTopologyNode *iface, DWORD
return hr;
}
static HRESULT WINAPI topology_node_ConnectOutput(IMFTopologyNode *iface, DWORD output_index,
IMFTopologyNode *peer, DWORD input_index)
{
struct topology_node *node = impl_from_IMFTopologyNode(iface);
struct topology_node *connection = unsafe_impl_from_IMFTopologyNode(peer);
TRACE("%p, %u, %p, %u.\n", iface, output_index, peer, input_index);
if (!connection)
{
WARN("External node implementations are not supported.\n");
return E_UNEXPECTED;
}
return topology_node_connect_output(node, output_index, connection, input_index);
}
static HRESULT WINAPI topology_node_DisconnectOutput(IMFTopologyNode *iface, DWORD output_index)
{
struct topology_node *node = impl_from_IMFTopologyNode(iface);
@ -1684,6 +1711,29 @@ static const IMFTopologyNodeVtbl topologynodevtbl =
topology_node_CloneFrom,
};
static HRESULT create_topology_node(MF_TOPOLOGY_TYPE node_type, struct topology_node **node)
{
HRESULT hr;
*node = heap_alloc_zero(sizeof(**node));
if (!*node)
return E_OUTOFMEMORY;
(*node)->IMFTopologyNode_iface.lpVtbl = &topologynodevtbl;
(*node)->refcount = 1;
(*node)->node_type = node_type;
hr = MFCreateAttributes(&(*node)->attributes, 0);
if (FAILED(hr))
{
heap_free(*node);
return hr;
}
(*node)->id = ((TOPOID)GetCurrentProcessId() << 32) | InterlockedIncrement(&next_node_id);
InitializeCriticalSection(&(*node)->cs);
return S_OK;
}
/***********************************************************************
* MFCreateTopologyNode (mf.@)
*/
@ -1692,30 +1742,16 @@ HRESULT WINAPI MFCreateTopologyNode(MF_TOPOLOGY_TYPE node_type, IMFTopologyNode
struct topology_node *object;
HRESULT hr;
TRACE("(%p)\n", node);
TRACE("%d, %p.\n", node_type, node);
if (!node)
return E_POINTER;
object = heap_alloc_zero(sizeof(*object));
if (!object)
return E_OUTOFMEMORY;
hr = create_topology_node(node_type, &object);
if (SUCCEEDED(hr))
*node = &object->IMFTopologyNode_iface;
object->IMFTopologyNode_iface.lpVtbl = &topologynodevtbl;
object->refcount = 1;
object->node_type = node_type;
hr = MFCreateAttributes(&object->attributes, 0);
if (FAILED(hr))
{
heap_free(object);
return hr;
}
object->id = ((TOPOID)GetCurrentProcessId() << 32) | InterlockedIncrement(&next_node_id);
InitializeCriticalSection(&object->cs);
*node = &object->IMFTopologyNode_iface;
return S_OK;
return hr;
}
static HRESULT WINAPI topology_loader_QueryInterface(IMFTopoLoader *iface, REFIID riid, void **out)