[PATCH v2 3/4] mf/topoloader: Implement source node to sink node branch resolver.

Derek Lesho dlesho at codeweavers.com
Fri Nov 27 13:51:31 CST 2020


Signed-off-by: Derek Lesho <dlesho at codeweavers.com>
---
 dlls/mf/topology.c | 268 ++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 266 insertions(+), 2 deletions(-)

diff --git a/dlls/mf/topology.c b/dlls/mf/topology.c
index a09f6ef0ef4..4756a30895b 100644
--- a/dlls/mf/topology.c
+++ b/dlls/mf/topology.c
@@ -1992,15 +1992,279 @@ static HRESULT topology_loader_clone_node(struct topoloader_context *context, IM
     return hr;
 }
 
+struct available_output_type
+{
+    IMFMediaType *type;
+    IMFTransform *transform;
+};
+
+static HRESULT topology_loader_enumerate_output_types(GUID *category, IMFMediaType *input_type, HRESULT (*new_type)(struct available_output_type *, void *), void *context)
+{
+    MFT_REGISTER_TYPE_INFO mft_typeinfo;
+    GUID major_type, subtype;
+    IMFActivate **activates;
+    UINT32 num_activates;
+    HRESULT hr;
+
+    if (FAILED(hr = IMFMediaType_GetMajorType(input_type, &major_type)))
+        return hr;
+
+    if (FAILED(hr = IMFMediaType_GetGUID(input_type, &MF_MT_SUBTYPE, &subtype)))
+        return hr;
+
+    mft_typeinfo.guidMajorType = major_type;
+    mft_typeinfo.guidSubtype = subtype;
+
+    if (FAILED(hr = MFTEnumEx(*category, MFT_ENUM_FLAG_ALL, &mft_typeinfo, NULL, &activates, &num_activates)))
+        return hr;
+
+    hr = E_FAIL;
+
+    for (unsigned int i = 0; i < num_activates; i++)
+    {
+        IMFTransform *mft;
+
+        if (FAILED(IMFActivate_ActivateObject(activates[i], &IID_IMFTransform, (void**) &mft)))
+        {
+            IMFActivate_Release(activates[i]);
+            continue;
+        }
+
+        if (SUCCEEDED(hr = IMFTransform_SetInputType(mft, 0, input_type, 0)))
+        {
+            struct available_output_type avail = {.transform = mft};
+            unsigned int output_count = 0;
+
+            while (SUCCEEDED(IMFTransform_GetOutputAvailableType(mft, 0, output_count++, &avail.type)))
+            {
+                if (SUCCEEDED(hr = new_type(&avail, context)))
+                {
+                    IMFActivate_Release(activates[i]);
+                    return hr;
+                }
+            }
+        }
+
+        IMFActivate_ShutdownObject(activates[i]);
+        IMFActivate_Release(activates[i]);
+    }
+
+    return hr;
+}
+
+struct connect_to_sink_context
+{
+    struct topoloader_context *context;
+    IMFTopologyNode *src, *sink;
+    IMFMediaTypeHandler *sink_mth;
+};
+
+HRESULT connect_to_sink(struct available_output_type *type, void *context)
+{
+    IMFTopologyNode *node;
+    struct connect_to_sink_context *ctx = context;
+
+    if (SUCCEEDED(IMFMediaTypeHandler_IsMediaTypeSupported(ctx->sink_mth, type->type, NULL)))
+    {
+        MFCreateTopologyNode(MF_TOPOLOGY_TRANSFORM_NODE, &node);
+        IMFTopologyNode_SetObject(node, (IUnknown *) type->transform);
+        IMFTopologyNode_ConnectOutput(ctx->src, 0, node, 0);
+        IMFTopologyNode_ConnectOutput(node, 0, ctx->sink, 0);
+
+        IMFTopology_AddNode(ctx->context->output_topology, node);
+        IMFTopologyNode_Release(node);
+
+        IMFMediaTypeHandler_SetCurrentMediaType(ctx->sink_mth, type->type);
+        IMFTransform_SetOutputType(type->transform, 0, type->type, 0);
+
+        return S_OK;
+    }
+    return MF_E_TRANSFORM_NOT_POSSIBLE_FOR_CURRENT_MEDIATYPE_COMBINATION;
+}
+
+struct connect_to_converter_context
+{
+    struct connect_to_sink_context sink_ctx;
+    GUID *converter_category;
+};
+
+HRESULT connect_to_converter(struct available_output_type *type, void *context)
+{
+    struct connect_to_converter_context *ctx = context;
+    struct connect_to_sink_context sink_ctx;
+    IMFTopologyNode *node;
+    HRESULT hr;
+
+    if (SUCCEEDED(connect_to_sink(type, &ctx->sink_ctx)))
+        return S_OK;
+
+    MFCreateTopologyNode(MF_TOPOLOGY_TRANSFORM_NODE, &node);
+    IMFTopologyNode_SetObject(node, (IUnknown *) type->transform);
+
+    sink_ctx = ctx->sink_ctx;
+    sink_ctx.src = node;
+    if (SUCCEEDED(hr = topology_loader_enumerate_output_types(ctx->converter_category, type->type, connect_to_sink, &sink_ctx)))
+    {
+        IMFTopologyNode_ConnectOutput(ctx->sink_ctx.src, 0, node, 0);
+
+        IMFTopology_AddNode(ctx->sink_ctx.context->output_topology, node);
+
+        IMFTransform_SetOutputType(type->transform, 0, type->type, 0);
+
+        return S_OK;
+    }
+    IMFTopologyNode_Release(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");
+    UINT32 enum_src_types, src_method = 0, sink_method = MF_CONNECT_ALLOW_DECODER;
+    IMFMediaTypeHandler *src_mth = NULL, *sink_mth = NULL;
+    struct connect_to_converter_context convert_ctx;
+    unsigned int i, k, i_, k_, src_type_count;
+    GUID major_type, decode_cat, convert_cat;
+    struct connect_to_sink_context sink_ctx;
+    IMFStreamDescriptor *desc = NULL;
+    IMFStreamSink *stream_sink;
+    IMFMediaType *media_type;
+    HRESULT hr;
 
-    return E_NOTIMPL;
+    TRACE("attempting to connect %p:%u to %p:%u\n", upstream_node, output_index, downstream_node, input_index);
+
+    IMFTopologyNode_GetUnknown(upstream_node, &MF_TOPONODE_STREAM_DESCRIPTOR, &IID_IMFStreamDescriptor, (void **)&desc);
+
+    if (FAILED(hr = IMFStreamDescriptor_GetMediaTypeHandler(desc, &src_mth)))
+        goto done;
+
+    if (FAILED(hr = IMFMediaTypeHandler_GetMediaTypeCount(src_mth, &src_type_count)))
+        goto done;
+
+    IMFTopologyNode_GetObject(downstream_node, (IUnknown **)&stream_sink);
+
+    if (FAILED(hr = IMFStreamSink_GetMediaTypeHandler(stream_sink, &sink_mth)))
+    {
+        IMFStreamSink_Release(stream_sink);
+        goto done;
+    }
+    IMFStreamSink_Release(stream_sink);
+
+    IMFTopologyNode_GetUINT32(upstream_node, &MF_TOPONODE_CONNECT_METHOD, &src_method);
+    IMFTopologyNode_GetUINT32(downstream_node, &MF_TOPONODE_CONNECT_METHOD, &sink_method);
+    IMFTopology_GetUINT32(context->input_topology, &MF_TOPOLOGY_ENUMERATE_SOURCE_TYPES, &enum_src_types);
+
+    if (FAILED(hr = IMFMediaTypeHandler_GetMajorType(src_mth, &major_type)))
+        goto done;
+
+    if (IsEqualGUID(&major_type, &MFMediaType_Audio))
+    {
+        decode_cat = MFT_CATEGORY_AUDIO_DECODER;
+        convert_cat = MFT_CATEGORY_AUDIO_EFFECT;
+    }
+    else if (IsEqualGUID(&major_type, &MFMediaType_Video))
+    {
+        decode_cat = MFT_CATEGORY_VIDEO_DECODER;
+        convert_cat = MFT_CATEGORY_VIDEO_EFFECT;
+    }
+    else
+    {
+        hr = MF_E_INVALIDTYPE;
+        goto done;
+    }
+
+    sink_ctx.context = context;
+    sink_ctx.src = upstream_node;
+    sink_ctx.sink = downstream_node;
+    sink_ctx.sink_mth = sink_mth;
+
+    convert_ctx.sink_ctx = sink_ctx;
+    convert_ctx.converter_category = &convert_cat;
+
+    i_ = (enum_src_types && src_method & MF_CONNECT_RESOLVE_INDEPENDENT_OUTPUTTYPES) ? src_type_count : 1;
+    k_ = (enum_src_types && !(src_method & MF_CONNECT_RESOLVE_INDEPENDENT_OUTPUTTYPES)) ? src_type_count : 1;
+    for(i = 0; i < i_; i++)
+    {
+        /* MF_CONNECT_DIRECT */
+        for (k = 0; k < k_; k++)
+        {
+            if (enum_src_types)
+            {
+                if (FAILED(hr = IMFMediaTypeHandler_GetMediaTypeByIndex(src_mth, i * k, &media_type))) goto done;
+            }
+            else
+                if (FAILED(hr = IMFMediaTypeHandler_GetCurrentMediaType(src_mth, &media_type))) goto done;
+
+            if (SUCCEEDED(hr = IMFMediaTypeHandler_IsMediaTypeSupported(sink_mth, media_type, NULL)))
+            {
+                IMFMediaTypeHandler_SetCurrentMediaType(src_mth, media_type);
+                IMFMediaTypeHandler_SetCurrentMediaType(sink_mth, media_type);
+                IMFTopologyNode_ConnectOutput(upstream_node, output_index, downstream_node, input_index);
+                IMFMediaType_Release(media_type);
+                goto done;
+            }
+
+            IMFMediaType_Release(media_type);
+        }
+
+        for (k = 0; k < k_; k++)
+        {
+            if (enum_src_types)
+            {
+                if (FAILED(hr = IMFMediaTypeHandler_GetMediaTypeByIndex(src_mth, i * k, &media_type))) goto done;
+            }
+            else
+                if (FAILED(hr = IMFMediaTypeHandler_GetCurrentMediaType(src_mth, &media_type))) goto done;
+
+            if (sink_method & MF_CONNECT_ALLOW_CONVERTER)
+            {
+                if (SUCCEEDED(hr = topology_loader_enumerate_output_types(&convert_cat, media_type, connect_to_sink, &sink_ctx)))
+                {
+                    IMFMediaTypeHandler_SetCurrentMediaType(src_mth, media_type);
+                    IMFMediaType_Release(media_type);
+                    goto done;
+                }
+            }
+
+            IMFMediaType_Release(media_type);
+        }
+
+        for (k = 0; k < k_; k++)
+        {
+            if (enum_src_types)
+            {
+                if (FAILED(hr = IMFMediaTypeHandler_GetMediaTypeByIndex(src_mth, i * k, &media_type))) goto done;
+            }
+            else
+                if (FAILED(hr = IMFMediaTypeHandler_GetCurrentMediaType(src_mth, &media_type))) goto done;
+
+            if (sink_method & MF_CONNECT_ALLOW_DECODER)
+            {
+                if (SUCCEEDED(hr = topology_loader_enumerate_output_types(&decode_cat, media_type, connect_to_converter, &convert_ctx)))
+                {
+                    IMFMediaTypeHandler_SetCurrentMediaType(src_mth, media_type);
+                    IMFMediaType_Release(media_type);
+                    goto done;
+                }
+            }
+
+            IMFMediaType_Release(media_type);
+        }
+    }
+    hr = MF_E_INVALIDMEDIATYPE;
+
+    done:
+    if (desc)
+        IMFStreamDescriptor_Release(desc);
+    if (src_mth)
+        IMFMediaTypeHandler_Release(src_mth);
+    if (sink_mth)
+        IMFMediaTypeHandler_Release(sink_mth);
+
+    return hr;
 }
 
 static HRESULT topology_loader_resolve_branch(struct topoloader_context *context, IMFTopologyNode *upstream_node,
-- 
2.29.2




More information about the wine-devel mailing list