[PATCH 1/8] mfplay: Handle user sinks.

Nikolay Sivov nsivov at codeweavers.com
Wed Apr 21 04:29:42 CDT 2021


Signed-off-by: Nikolay Sivov <nsivov at codeweavers.com>
---
 dlls/mfplay/player.c | 75 +++++++++++++++++++++++++++++++-------------
 1 file changed, 53 insertions(+), 22 deletions(-)

diff --git a/dlls/mfplay/player.c b/dlls/mfplay/player.c
index 51f3f67f5b1..87ddf613288 100644
--- a/dlls/mfplay/player.c
+++ b/dlls/mfplay/player.c
@@ -1015,13 +1015,38 @@ static HRESULT media_item_get_stream_type(IMFStreamDescriptor *sd, GUID *major)
     return hr;
 }
 
+static HRESULT media_item_create_source_node(struct media_item *item, IMFStreamDescriptor *sd,
+        IMFTopologyNode **node)
+{
+    HRESULT hr;
+
+    if (SUCCEEDED(hr = MFCreateTopologyNode(MF_TOPOLOGY_SOURCESTREAM_NODE, node)))
+    {
+        IMFTopologyNode_SetUnknown(*node, &MF_TOPONODE_SOURCE, (IUnknown *)item->source);
+        IMFTopologyNode_SetUnknown(*node, &MF_TOPONODE_PRESENTATION_DESCRIPTOR, (IUnknown *)item->pd);
+        IMFTopologyNode_SetUnknown(*node, &MF_TOPONODE_STREAM_DESCRIPTOR, (IUnknown *)sd);
+    }
+
+    return hr;
+}
+
+static HRESULT media_item_create_sink_node(IUnknown *sink, IMFTopologyNode **node)
+{
+    HRESULT hr;
+
+    if (SUCCEEDED(hr = MFCreateTopologyNode(MF_TOPOLOGY_OUTPUT_NODE, node)))
+        IMFTopologyNode_SetObject(*node, sink);
+
+    return hr;
+}
+
 static HRESULT media_item_create_topology(struct media_player *player, struct media_item *item, IMFTopology **out)
 {
     IMFTopologyNode *src_node, *sink_node;
-    IMFActivate *sar_activate;
     IMFStreamDescriptor *sd;
     IMFTopology *topology;
     unsigned int idx;
+    IUnknown *sink;
     BOOL selected;
     HRESULT hr;
     GUID major;
@@ -1029,48 +1054,54 @@ static HRESULT media_item_create_topology(struct media_player *player, struct me
     if (FAILED(hr = MFCreateTopology(&topology)))
         return hr;
 
-    /* FIXME: handle user sinks */
-
     /* Use first stream if none selected. */
     if (player->output_window)
     {
         FIXME("Video streams are not handled.\n");
     }
 
-    /* Set up audio branches for all selected streams. */
+    /* Set up branches for all selected streams. */
 
     idx = 0;
     while (SUCCEEDED(IMFPresentationDescriptor_GetStreamDescriptorByIndex(item->pd, idx++, &selected, &sd)))
     {
-        if (selected && SUCCEEDED(media_item_get_stream_type(sd, &major)) && IsEqualGUID(&major, &MFMediaType_Audio))
+        if (!selected)
         {
-            if (SUCCEEDED(hr = MFCreateTopologyNode(MF_TOPOLOGY_SOURCESTREAM_NODE, &src_node)))
-            {
-                IMFTopologyNode_SetUnknown(src_node, &MF_TOPONODE_SOURCE, (IUnknown *)item->source);
-                IMFTopologyNode_SetUnknown(src_node, &MF_TOPONODE_PRESENTATION_DESCRIPTOR, (IUnknown *)item->pd);
-                IMFTopologyNode_SetUnknown(src_node, &MF_TOPONODE_STREAM_DESCRIPTOR, (IUnknown *)sd);
+            IMFStreamDescriptor_Release(sd);
+            continue;
+        }
 
-                IMFTopology_AddNode(topology, src_node);
-            }
+        sink = NULL;
 
-            if (SUCCEEDED(hr = MFCreateTopologyNode(MF_TOPOLOGY_OUTPUT_NODE, &sink_node)))
-            {
-                if (SUCCEEDED(MFCreateAudioRendererActivate(&sar_activate)))
-                {
-                    IMFTopologyNode_SetObject(sink_node, (IUnknown *)sar_activate);
-                    IMFActivate_Release(sar_activate);
-                }
+        if (SUCCEEDED(IMFStreamDescriptor_GetUnknown(sd, &_MF_CUSTOM_SINK, &IID_IUnknown, (void **)&sink)))
+        {
+            /* User sink is attached as-is. */
+        }
+        else if (SUCCEEDED(media_item_get_stream_type(sd, &major)) && IsEqualGUID(&major, &MFMediaType_Audio))
+        {
+            if (FAILED(hr = MFCreateAudioRendererActivate((IMFActivate **)&sink)))
+                WARN("Failed to create SAR activation object, hr %#x.\n", hr);
+        }
 
-                IMFTopology_AddNode(topology, sink_node);
-            }
+        if (sink)
+        {
+            hr = media_item_create_source_node(item, sd, &src_node);
+            if (SUCCEEDED(hr))
+                hr = media_item_create_sink_node(sink, &sink_node);
 
-            if (src_node && sink_node)
+            if (SUCCEEDED(hr))
+            {
+                IMFTopology_AddNode(topology, src_node);
+                IMFTopology_AddNode(topology, sink_node);
                 IMFTopologyNode_ConnectOutput(src_node, 0, sink_node, 0);
+            }
 
             if (src_node)
                 IMFTopologyNode_Release(src_node);
             if (sink_node)
                 IMFTopologyNode_Release(sink_node);
+
+            IUnknown_Release(sink);
         }
 
         IMFStreamDescriptor_Release(sd);
-- 
2.30.2




More information about the wine-devel mailing list