mf/topoloader: Add a structure for iterative branch resolution.
Signed-off-by: Nikolay Sivov <nsivov@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
16d44b61d1
commit
e308d81a61
|
@ -1400,6 +1400,7 @@ static void test_topology_loader(void)
|
|||
IMFPresentationDescriptor *pd;
|
||||
IMFSourceResolver *resolver;
|
||||
IMFActivate *sink_activate;
|
||||
IMFStreamSink *stream_sink;
|
||||
unsigned int count, value;
|
||||
IMFMediaType *media_type;
|
||||
IMFStreamDescriptor *sd;
|
||||
|
@ -1512,15 +1513,19 @@ todo_wine
|
|||
hr = IMFActivate_ActivateObject(sink_activate, &IID_IMFMediaSink, (void **)&sink);
|
||||
ok(hr == S_OK, "Failed to activate, hr %#x.\n", hr);
|
||||
|
||||
hr = IMFTopologyNode_SetObject(sink_node, (IUnknown *)sink);
|
||||
hr = IMFMediaSink_GetStreamSinkByIndex(sink, 0, &stream_sink);
|
||||
ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
|
||||
|
||||
hr = IMFTopologyNode_SetObject(sink_node, (IUnknown *)stream_sink);
|
||||
ok(hr == S_OK, "Failed to set object, hr %#x.\n", hr);
|
||||
|
||||
IMFStreamSink_Release(stream_sink);
|
||||
|
||||
hr = IMFTopology_GetCount(topology, &count);
|
||||
ok(hr == S_OK, "Failed to get attribute count, hr %#x.\n", hr);
|
||||
ok(count == 0, "Unexpected count %u.\n", count);
|
||||
|
||||
hr = IMFTopoLoader_Load(loader, topology, &full_topology, NULL);
|
||||
todo_wine
|
||||
ok(hr == S_OK, "Failed to resolve topology, hr %#x.\n", hr);
|
||||
ok(full_topology != topology, "Unexpected instance.\n");
|
||||
|
||||
|
|
|
@ -1935,17 +1935,41 @@ static ULONG WINAPI topology_loader_Release(IMFTopoLoader *iface)
|
|||
|
||||
struct topoloader_context
|
||||
{
|
||||
IMFTopology *input_topology;
|
||||
IMFTopology *output_topology;
|
||||
unsigned int marker;
|
||||
GUID key;
|
||||
};
|
||||
|
||||
static IMFTopologyNode *topology_loader_get_node_for_marker(struct topoloader_context *context, TOPOID *id)
|
||||
{
|
||||
IMFTopologyNode *node;
|
||||
unsigned short i = 0;
|
||||
unsigned int value;
|
||||
|
||||
while (SUCCEEDED(IMFTopology_GetNode(context->output_topology, i++, &node)))
|
||||
{
|
||||
if (SUCCEEDED(IMFTopologyNode_GetUINT32(node, &context->key, &value)) && value == context->marker)
|
||||
{
|
||||
IMFTopologyNode_GetTopoNodeID(node, id);
|
||||
return node;
|
||||
}
|
||||
IMFTopologyNode_Release(node);
|
||||
}
|
||||
|
||||
*id = 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static HRESULT topology_loader_clone_node(struct topoloader_context *context, IMFTopologyNode *node,
|
||||
unsigned int marker)
|
||||
IMFTopologyNode **ret, unsigned int marker)
|
||||
{
|
||||
IMFTopologyNode *cloned_node;
|
||||
MF_TOPOLOGY_TYPE node_type;
|
||||
HRESULT hr;
|
||||
|
||||
if (ret) *ret = NULL;
|
||||
|
||||
IMFTopologyNode_GetNodeType(node, &node_type);
|
||||
|
||||
if (FAILED(hr = MFCreateTopologyNode(node_type, &cloned_node)))
|
||||
|
@ -1957,17 +1981,113 @@ static HRESULT topology_loader_clone_node(struct topoloader_context *context, IM
|
|||
if (SUCCEEDED(hr))
|
||||
hr = IMFTopology_AddNode(context->output_topology, cloned_node);
|
||||
|
||||
if (SUCCEEDED(hr) && ret)
|
||||
{
|
||||
*ret = cloned_node;
|
||||
IMFTopologyNode_AddRef(*ret);
|
||||
}
|
||||
|
||||
IMFTopologyNode_Release(cloned_node);
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
typedef HRESULT (*p_topology_loader_connect_func)(struct topoloader_context *context, IMFTopologyNode *upstream_node,
|
||||
unsigned int output_index, IMFTopologyNode *downstream_node, unsigned int input_index);
|
||||
|
||||
static HRESULT topology_loader_connect_source_node(struct topoloader_context *context, IMFTopologyNode *upstream_node,
|
||||
unsigned int output_index, IMFTopologyNode *downstream_node, unsigned int input_index)
|
||||
{
|
||||
FIXME("Unimplemented.\n");
|
||||
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
static HRESULT topology_loader_resolve_branch(struct topoloader_context *context, IMFTopologyNode *upstream_node,
|
||||
unsigned int output_index, IMFTopologyNode *downstream_node, unsigned input_index)
|
||||
{
|
||||
static const p_topology_loader_connect_func connectors[MF_TOPOLOGY_TEE_NODE+1][MF_TOPOLOGY_TEE_NODE+1] =
|
||||
{
|
||||
/* OUTPUT */ { NULL },
|
||||
/* SOURCESTREAM */ { topology_loader_connect_source_node, NULL, NULL, NULL },
|
||||
/* TRANSFORM */ { NULL },
|
||||
/* TEE */ { NULL },
|
||||
};
|
||||
MF_TOPOLOGY_TYPE u_type, d_type;
|
||||
IMFTopologyNode *node;
|
||||
TOPOID id;
|
||||
|
||||
/* Downstream node might have already been cloned. */
|
||||
IMFTopologyNode_GetTopoNodeID(downstream_node, &id);
|
||||
if (FAILED(IMFTopology_GetNodeByID(context->output_topology, id, &node)))
|
||||
topology_loader_clone_node(context, downstream_node, &node, context->marker + 1);
|
||||
|
||||
IMFTopologyNode_ConnectOutput(upstream_node, output_index, node, input_index);
|
||||
|
||||
IMFTopologyNode_GetNodeType(upstream_node, &u_type);
|
||||
IMFTopologyNode_GetNodeType(downstream_node, &d_type);
|
||||
|
||||
if (!connectors[u_type][d_type])
|
||||
{
|
||||
WARN("Unsupported branch kind %d -> %d.\n", u_type, d_type);
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
return connectors[u_type][d_type](context, upstream_node, output_index, downstream_node, input_index);
|
||||
}
|
||||
|
||||
static HRESULT topology_loader_resolve_nodes(struct topoloader_context *context, unsigned int *layer_size)
|
||||
{
|
||||
IMFTopologyNode *downstream_node, *node, *orig_node;
|
||||
unsigned int input_index, size = 0;
|
||||
MF_TOPOLOGY_TYPE node_type;
|
||||
HRESULT hr = S_OK;
|
||||
TOPOID id;
|
||||
|
||||
while ((node = topology_loader_get_node_for_marker(context, &id)))
|
||||
{
|
||||
++size;
|
||||
|
||||
IMFTopology_GetNodeByID(context->input_topology, id, &orig_node);
|
||||
|
||||
IMFTopologyNode_GetNodeType(node, &node_type);
|
||||
switch (node_type)
|
||||
{
|
||||
case MF_TOPOLOGY_SOURCESTREAM_NODE:
|
||||
if (FAILED(IMFTopologyNode_GetOutput(orig_node, 0, &downstream_node, &input_index)))
|
||||
{
|
||||
IMFTopology_RemoveNode(context->output_topology, node);
|
||||
continue;
|
||||
}
|
||||
|
||||
hr = topology_loader_resolve_branch(context, node, 0, downstream_node, input_index);
|
||||
break;
|
||||
case MF_TOPOLOGY_TRANSFORM_NODE:
|
||||
case MF_TOPOLOGY_TEE_NODE:
|
||||
FIXME("Unsupported node type %d.\n", node_type);
|
||||
break;
|
||||
default:
|
||||
WARN("Unexpected node type %d.\n", node_type);
|
||||
}
|
||||
|
||||
IMFTopologyNode_DeleteItem(node, &context->key);
|
||||
|
||||
if (FAILED(hr))
|
||||
break;
|
||||
}
|
||||
|
||||
*layer_size = size;
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI topology_loader_Load(IMFTopoLoader *iface, IMFTopology *input_topology,
|
||||
IMFTopology **ret_topology, IMFTopology *current_topology)
|
||||
{
|
||||
struct topoloader_context context = { 0 };
|
||||
IMFTopology *output_topology;
|
||||
MF_TOPOLOGY_TYPE node_type;
|
||||
unsigned int layer_size;
|
||||
IMFTopologyNode *node;
|
||||
unsigned short i = 0;
|
||||
IMFStreamSink *sink;
|
||||
|
@ -2016,6 +2136,7 @@ static HRESULT WINAPI topology_loader_Load(IMFTopoLoader *iface, IMFTopology *in
|
|||
if (FAILED(hr = MFCreateTopology(&output_topology)))
|
||||
return hr;
|
||||
|
||||
context.input_topology = input_topology;
|
||||
context.output_topology = output_topology;
|
||||
memset(&context.key, 0xff, sizeof(context.key));
|
||||
|
||||
|
@ -2027,13 +2148,26 @@ static HRESULT WINAPI topology_loader_Load(IMFTopoLoader *iface, IMFTopology *in
|
|||
|
||||
if (node_type == MF_TOPOLOGY_SOURCESTREAM_NODE)
|
||||
{
|
||||
if (FAILED(hr = topology_loader_clone_node(&context, node, 0)))
|
||||
if (FAILED(hr = topology_loader_clone_node(&context, node, NULL, 0)))
|
||||
WARN("Failed to clone source node, hr %#x.\n", hr);
|
||||
}
|
||||
|
||||
IMFTopologyNode_Release(node);
|
||||
}
|
||||
|
||||
for (context.marker = 0;; ++context.marker)
|
||||
{
|
||||
if (FAILED(hr = topology_loader_resolve_nodes(&context, &layer_size)))
|
||||
{
|
||||
WARN("Failed to resolve for marker %u, hr %#x.\n", context.marker, hr);
|
||||
break;
|
||||
}
|
||||
|
||||
/* Reached last marker value. */
|
||||
if (!layer_size)
|
||||
break;
|
||||
}
|
||||
|
||||
/* For now return original topology. */
|
||||
|
||||
*ret_topology = output_topology;
|
||||
|
|
Loading…
Reference in New Issue