[PATCH 4/4] quartz: Implement IFilterGraph2::RenderEx().

Zebediah Figura z.figura12 at gmail.com
Mon Jun 15 22:51:26 CDT 2020


From: Zebediah Figura <zfigura at codeweavers.com>

Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=35215
Signed-off-by: Zebediah Figura <z.figura12 at gmail.com>
---
 dlls/quartz/filtergraph.c       | 49 ++++++++++++++++++++++-----------
 dlls/quartz/tests/filtergraph.c | 28 +++++++++++++++----
 2 files changed, 56 insertions(+), 21 deletions(-)

diff --git a/dlls/quartz/filtergraph.c b/dlls/quartz/filtergraph.c
index e3faf64fb82..a23e35d6a1c 100644
--- a/dlls/quartz/filtergraph.c
+++ b/dlls/quartz/filtergraph.c
@@ -1119,10 +1119,12 @@ static HRESULT create_filter(IFilterGraphImpl *graph, IMoniker *moniker, IBaseFi
         return IMoniker_BindToObject(moniker, NULL, NULL, &IID_IBaseFilter, (void **)filter);
 }
 
-static HRESULT autoplug(IFilterGraphImpl *graph, IPin *source, IPin *sink, unsigned int recursion_depth);
+static HRESULT autoplug(IFilterGraphImpl *graph, IPin *source, IPin *sink,
+        BOOL render_to_existing, unsigned int recursion_depth);
 
 static HRESULT autoplug_through_sink(IFilterGraphImpl *graph, IPin *source,
-        IBaseFilter *filter, IPin *middle_sink, IPin *sink, unsigned int recursion_depth)
+        IBaseFilter *filter, IPin *middle_sink, IPin *sink,
+        BOOL render_to_existing, BOOL allow_renderers, unsigned int recursion_depth)
 {
     BOOL any = FALSE, all = TRUE;
     IPin *middle_source, *peer;
@@ -1171,7 +1173,7 @@ static HRESULT autoplug_through_sink(IFilterGraphImpl *graph, IPin *source,
             continue;
         }
 
-        hr = autoplug(graph, middle_source, sink, recursion_depth + 1);
+        hr = autoplug(graph, middle_source, sink, render_to_existing, recursion_depth + 1);
         IPin_Release(middle_source);
         if (SUCCEEDED(hr) && sink)
         {
@@ -1187,7 +1189,7 @@ static HRESULT autoplug_through_sink(IFilterGraphImpl *graph, IPin *source,
 
     if (!sink)
     {
-        if (all)
+        if (all && (any || allow_renderers))
             return S_OK;
         if (any)
             return VFW_S_PARTIAL_RENDER;
@@ -1200,7 +1202,8 @@ err:
 }
 
 static HRESULT autoplug_through_filter(IFilterGraphImpl *graph, IPin *source,
-        IBaseFilter *filter, IPin *sink, unsigned int recursion_depth)
+        IBaseFilter *filter, IPin *sink, BOOL render_to_existing,
+        BOOL allow_renderers, unsigned int recursion_depth)
 {
     IEnumPins *sink_enum;
     IPin *filter_sink;
@@ -1213,7 +1216,8 @@ static HRESULT autoplug_through_filter(IFilterGraphImpl *graph, IPin *source,
 
     while (IEnumPins_Next(sink_enum, 1, &filter_sink, NULL) == S_OK)
     {
-        hr = autoplug_through_sink(graph, source, filter, filter_sink, sink, recursion_depth);
+        hr = autoplug_through_sink(graph, source, filter, filter_sink, sink,
+                render_to_existing, allow_renderers, recursion_depth);
         IPin_Release(filter_sink);
         if (SUCCEEDED(hr))
         {
@@ -1227,7 +1231,8 @@ static HRESULT autoplug_through_filter(IFilterGraphImpl *graph, IPin *source,
 
 /* Common helper for IGraphBuilder::Connect() and IGraphBuilder::Render(), which
  * share most of the same code. Render() calls this with a NULL sink. */
-static HRESULT autoplug(IFilterGraphImpl *graph, IPin *source, IPin *sink, unsigned int recursion_depth)
+static HRESULT autoplug(IFilterGraphImpl *graph, IPin *source, IPin *sink,
+        BOOL render_to_existing, unsigned int recursion_depth)
 {
     IAMGraphBuilderCallback *callback = NULL;
     IEnumMediaTypes *enummt;
@@ -1259,7 +1264,8 @@ static HRESULT autoplug(IFilterGraphImpl *graph, IPin *source, IPin *sink, unsig
     /* Always prefer filters in the graph. */
     LIST_FOR_EACH_ENTRY(filter, &graph->filters, struct filter, entry)
     {
-        if (SUCCEEDED(hr = autoplug_through_filter(graph, source, filter->filter, sink, recursion_depth)))
+        if (SUCCEEDED(hr = autoplug_through_filter(graph, source, filter->filter,
+                sink, render_to_existing, TRUE, recursion_depth)))
             return hr;
     }
 
@@ -1334,7 +1340,8 @@ static HRESULT autoplug(IFilterGraphImpl *graph, IPin *source, IPin *sink, unsig
                 continue;
             }
 
-            hr = autoplug_through_filter(graph, source, filter, sink, recursion_depth);
+            hr = autoplug_through_filter(graph, source, filter, sink,
+                    render_to_existing, !render_to_existing, recursion_depth);
             if (SUCCEEDED(hr))
             {
                 IBaseFilter_Release(filter);
@@ -1383,7 +1390,7 @@ static HRESULT WINAPI FilterGraph2_Connect(IFilterGraph2 *iface, IPin *source, I
 
     EnterCriticalSection(&graph->cs);
 
-    hr = autoplug(graph, source, sink, 0);
+    hr = autoplug(graph, source, sink, FALSE, 0);
 
     LeaveCriticalSection(&graph->cs);
 
@@ -1399,7 +1406,7 @@ static HRESULT WINAPI FilterGraph2_Render(IFilterGraph2 *iface, IPin *source)
     TRACE("graph %p, source %p.\n", graph, source);
 
     EnterCriticalSection(&graph->cs);
-    hr = autoplug(graph, source, NULL, 0);
+    hr = autoplug(graph, source, NULL, FALSE, 0);
     LeaveCriticalSection(&graph->cs);
     if (hr == VFW_E_CANNOT_CONNECT)
         hr = VFW_E_CANNOT_RENDER;
@@ -1598,14 +1605,24 @@ static HRESULT WINAPI FilterGraph2_ReconnectEx(IFilterGraph2 *iface, IPin *pin,
     return hr;
 }
 
-static HRESULT WINAPI FilterGraph2_RenderEx(IFilterGraph2 *iface, IPin *pPinOut, DWORD dwFlags,
-        DWORD *pvContext)
+static HRESULT WINAPI FilterGraph2_RenderEx(IFilterGraph2 *iface, IPin *source, DWORD flags, DWORD *context)
 {
-    IFilterGraphImpl *This = impl_from_IFilterGraph2(iface);
+    IFilterGraphImpl *graph = impl_from_IFilterGraph2(iface);
+    HRESULT hr;
 
-    TRACE("(%p/%p)->(%p %08x %p): stub !!!\n", This, iface, pPinOut, dwFlags, pvContext);
+    TRACE("graph %p, source %p, flags %#x, context %p.\n", graph, source, flags, context);
 
-    return S_OK;
+    if (flags & ~AM_RENDEREX_RENDERTOEXISTINGRENDERERS)
+        FIXME("Unknown flags %#x.\n", flags);
+
+    EnterCriticalSection(&graph->cs);
+    hr = autoplug(graph, source, NULL, !!(flags & AM_RENDEREX_RENDERTOEXISTINGRENDERERS), 0);
+    LeaveCriticalSection(&graph->cs);
+    if (hr == VFW_E_CANNOT_CONNECT)
+        hr = VFW_E_CANNOT_RENDER;
+
+    TRACE("Returning %#x.\n", hr);
+    return hr;
 }
 
 
diff --git a/dlls/quartz/tests/filtergraph.c b/dlls/quartz/tests/filtergraph.c
index 5a61b754648..de8e32034f8 100644
--- a/dlls/quartz/tests/filtergraph.c
+++ b/dlls/quartz/tests/filtergraph.c
@@ -1978,9 +1978,6 @@ static void test_graph_builder_render(void)
 
     /* Test enumeration of filters from the registry. */
 
-    graph = create_graph();
-    IFilterGraph2_AddFilter(graph, &source.IBaseFilter_iface, NULL);
-
     CoRegisterClassObject(&sink1_clsid, (IUnknown *)&sink1_cf.IClassFactory_iface,
             CLSCTX_INPROC_SERVER, REGCLS_MULTIPLEUSE, &cookie1);
     CoRegisterClassObject(&sink2_clsid, (IUnknown *)&sink2_cf.IClassFactory_iface,
@@ -2007,6 +2004,9 @@ static void test_graph_builder_render(void)
     }
     ok(hr == S_OK, "Got hr %#x.\n", hr);
 
+    graph = create_graph();
+    IFilterGraph2_AddFilter(graph, &source.IBaseFilter_iface, NULL);
+
     regpins.dwFlags = REG_PINFLAG_B_RENDERER;
     IFilterMapper2_RegisterFilter(mapper, &sink2_clsid, L"test", NULL, NULL, NULL, &regfilter);
 
@@ -2086,6 +2086,26 @@ static void test_graph_builder_render(void)
     ok(hr == S_OK, "Got hr %#x.\n", hr);
     ok(source_pin.peer == &sink1_pin.IPin_iface, "Got peer %p.\n", source_pin.peer);
 
+    ref = IFilterGraph2_Release(graph);
+    ok(!ref, "Got outstanding refcount %d.\n", ref);
+
+    /* Test AM_RENDEREX_RENDERTOEXISTINGRENDERERS. */
+
+    graph = create_graph();
+    IFilterGraph2_AddFilter(graph, &source.IBaseFilter_iface, NULL);
+
+    hr = IFilterGraph2_RenderEx(graph, &source_pin.IPin_iface, AM_RENDEREX_RENDERTOEXISTINGRENDERERS, NULL);
+    ok(hr == VFW_E_CANNOT_RENDER, "Got hr %#x.\n", hr);
+
+    IFilterGraph2_AddFilter(graph, &sink1.IBaseFilter_iface, NULL);
+
+    hr = IFilterGraph2_RenderEx(graph, &source_pin.IPin_iface, AM_RENDEREX_RENDERTOEXISTINGRENDERERS, NULL);
+    ok(hr == S_OK, "Got hr %#x.\n", hr);
+    ok(source_pin.peer == &sink1_pin.IPin_iface, "Got peer %p.\n", source_pin.peer);
+
+    ref = IFilterGraph2_Release(graph);
+    ok(!ref, "Got outstanding refcount %d.\n", ref);
+
     IFilterMapper2_UnregisterFilter(mapper, NULL, NULL, &sink1_clsid);
     IFilterMapper2_UnregisterFilter(mapper, NULL, NULL, &sink2_clsid);
 
@@ -2093,8 +2113,6 @@ out:
     CoRevokeClassObject(cookie1);
     CoRevokeClassObject(cookie2);
     IFilterMapper2_Release(mapper);
-    ref = IFilterGraph2_Release(graph);
-    ok(!ref, "Got outstanding refcount %d.\n", ref);
     ok(source.ref == 1, "Got outstanding refcount %d.\n", source.ref);
     ok(source_pin.ref == 1, "Got outstanding refcount %d.\n", source_pin.ref);
     ok(sink1.ref == 1, "Got outstanding refcount %d.\n", sink1.ref);
-- 
2.27.0




More information about the wine-devel mailing list