[PATCH 4/7] qcap: Use separate functions when searching from a pin and filter.

Zebediah Figura z.figura12 at gmail.com
Wed Apr 8 15:58:53 CDT 2020


Previously, if we tried to search from a matching but connected source, we
would loop forever.

Signed-off-by: Zebediah Figura <zfigura at codeweavers.com>
---
 dlls/qcap/capturegraph.c       | 140 +++++++++++++++++++--------------
 dlls/qcap/tests/capturegraph.c |  39 ++++-----
 2 files changed, 95 insertions(+), 84 deletions(-)

diff --git a/dlls/qcap/capturegraph.c b/dlls/qcap/capturegraph.c
index 33b0ecfaa11..b49e45b9d6b 100644
--- a/dlls/qcap/capturegraph.c
+++ b/dlls/qcap/capturegraph.c
@@ -499,83 +499,88 @@ end:
     return hr;
 }
 
-static HRESULT find_unconnected_pin(CaptureGraphImpl *This,
-        const GUID *pCategory, const GUID *pType, IUnknown *pSource, IPin **out_pin)
+static HRESULT find_unconnected_source_from_filter(CaptureGraphImpl *capture_graph,
+        const GUID *category, const GUID *majortype, IBaseFilter *filter, IPin **ret);
+
+static HRESULT find_unconnected_source_from_pin(CaptureGraphImpl *capture_graph,
+        const GUID *category, const GUID *majortype, IPin *pin, IPin **ret)
 {
-    int index = 0;
-    IPin *source_out;
+    PIN_INFO info;
     HRESULT hr;
-    BOOL usedSmartTeePreviewPin = FALSE;
-
-    /* depth-first search the graph for the first unconnected pin that matches
-     * the given category and type */
-    for(;;){
-        IPin *nextpin;
-
-        if (pCategory && (IsEqualIID(pCategory, &PIN_CATEGORY_CAPTURE) || IsEqualIID(pCategory, &PIN_CATEGORY_PREVIEW))){
-            IBaseFilter *sourceFilter = NULL;
-            hr = IUnknown_QueryInterface(pSource, &IID_IBaseFilter, (void**)&sourceFilter);
-            if (SUCCEEDED(hr)) {
-                hr = match_smart_tee_pin(This, pCategory, pType, pSource, &source_out);
-                if (hr == VFW_S_NOPREVIEWPIN)
-                    usedSmartTeePreviewPin = TRUE;
-                IBaseFilter_Release(sourceFilter);
-            } else {
-                hr = ICaptureGraphBuilder2_FindPin(&This->ICaptureGraphBuilder2_iface, pSource, PINDIR_OUTPUT, pCategory, pType, FALSE, index, &source_out);
-            }
-            if (FAILED(hr))
-                return E_INVALIDARG;
-        } else {
-            hr = ICaptureGraphBuilder2_FindPin(&This->ICaptureGraphBuilder2_iface, pSource, PINDIR_OUTPUT, pCategory, pType, FALSE, index, &source_out);
-            if (FAILED(hr))
-                return E_INVALIDARG;
-        }
+    IPin *peer;
 
-        hr = IPin_ConnectedTo(source_out, &nextpin);
-        if(SUCCEEDED(hr)){
-            PIN_INFO info;
+    if (category && (IsEqualGUID(category, &PIN_CATEGORY_CAPTURE)
+            || IsEqualGUID(category, &PIN_CATEGORY_PREVIEW)))
+        hr = match_smart_tee_pin(capture_graph, category, majortype, (IUnknown *)pin, &pin);
+    else
+        hr = ICaptureGraphBuilder2_FindPin(&capture_graph->ICaptureGraphBuilder2_iface,
+                (IUnknown *)pin, PINDIR_OUTPUT, category, majortype, FALSE, -1, &pin);
+    if (FAILED(hr))
+        return hr;
 
-            IPin_Release(source_out);
+    if (FAILED(IPin_ConnectedTo(pin, &peer)))
+    {
+        *ret = pin;
+        return hr;
+    }
 
-            hr = IPin_QueryPinInfo(nextpin, &info);
-            if(FAILED(hr) || !info.pFilter){
-                WARN("QueryPinInfo failed: %08x\n", hr);
-                return hr;
-            }
+    IPin_QueryPinInfo(peer, &info);
+    hr = find_unconnected_source_from_filter(capture_graph, category, majortype, info.pFilter, ret);
+    IBaseFilter_Release(info.pFilter);
+    IPin_Release(peer);
+    IPin_Release(pin);
+    return hr;
+}
 
-            hr = find_unconnected_pin(This, pCategory, pType, (IUnknown*)info.pFilter, out_pin);
+static HRESULT find_unconnected_source_from_filter(CaptureGraphImpl *capture_graph,
+        const GUID *category, const GUID *majortype, IBaseFilter *filter, IPin **ret)
+{
+    IPin *pin, *peer;
+    HRESULT hr;
+    int index;
 
-            IBaseFilter_Release(info.pFilter);
+    if (category && (IsEqualGUID(category, &PIN_CATEGORY_CAPTURE)
+            || IsEqualGUID(category, &PIN_CATEGORY_PREVIEW)))
+    {
+        if (FAILED(hr = match_smart_tee_pin(capture_graph, category, majortype, (IUnknown *)filter, &pin)))
+            return hr;
 
-            if(SUCCEEDED(hr))
-                return hr;
-        }else{
-            *out_pin = source_out;
-            if(usedSmartTeePreviewPin)
-                return VFW_S_NOPREVIEWPIN;
-            return S_OK;
+        if (FAILED(IPin_ConnectedTo(pin, &peer)))
+        {
+            *ret = pin;
+            return hr;
         }
 
-        index++;
+        IPin_Release(peer);
+        IPin_Release(pin);
+        return E_INVALIDARG;
     }
+
+    for (index = 0; SUCCEEDED(ICaptureGraphBuilder2_FindPin(&capture_graph->ICaptureGraphBuilder2_iface,
+            (IUnknown *)filter, PINDIR_OUTPUT, category, majortype, FALSE, index, &pin)); ++index)
+    {
+        hr = find_unconnected_source_from_pin(capture_graph, category, majortype, pin, ret);
+        IPin_Release(pin);
+        if (SUCCEEDED(hr))
+            return hr;
+    }
+
+    return E_INVALIDARG;
 }
 
-static HRESULT WINAPI
-fnCaptureGraphBuilder2_RenderStream(ICaptureGraphBuilder2 * iface,
-                                    const GUID *pCategory,
-                                    const GUID *pType,
-                                    IUnknown *pSource,
-                                    IBaseFilter *pfCompressor,
-                                    IBaseFilter *pfRenderer)
+static HRESULT WINAPI fnCaptureGraphBuilder2_RenderStream(ICaptureGraphBuilder2 *iface,
+        const GUID *category, const GUID *majortype, IUnknown *source,
+        IBaseFilter *pfCompressor, IBaseFilter *pfRenderer)
 {
     CaptureGraphImpl *This = impl_from_ICaptureGraphBuilder2(iface);
     IPin *source_out = NULL, *renderer_in;
     BOOL rendererNeedsRelease = FALSE;
     HRESULT hr, return_hr = S_OK;
+    IBaseFilter *filter;
+    IPin *pin;
 
-    FIXME("(%p/%p)->(%s, %s, %p, %p, %p) semi-stub!\n", This, iface,
-          debugstr_guid(pCategory), debugstr_guid(pType),
-          pSource, pfCompressor, pfRenderer);
+    TRACE("graph %p, category %s, majortype %s, source %p, intermediate %p, sink %p.\n",
+            This, debugstr_guid(category), debugstr_guid(majortype), source, pfCompressor, pfRenderer);
 
     if (!This->mygraph)
     {
@@ -583,12 +588,27 @@ fnCaptureGraphBuilder2_RenderStream(ICaptureGraphBuilder2 * iface,
         return E_UNEXPECTED;
     }
 
-    if (pCategory && IsEqualIID(pCategory, &PIN_CATEGORY_VBI)) {
+    if (category && IsEqualGUID(category, &PIN_CATEGORY_VBI))
+    {
         FIXME("Tee/Sink-to-Sink filter not supported\n");
         return E_NOTIMPL;
     }
 
-    hr = find_unconnected_pin(This, pCategory, pType, pSource, &source_out);
+    if (IUnknown_QueryInterface(source, &IID_IPin, (void **)&pin) == S_OK)
+    {
+        hr = find_unconnected_source_from_pin(This, category, majortype, pin, &source_out);
+        IPin_Release(pin);
+    }
+    else if (IUnknown_QueryInterface(source, &IID_IBaseFilter, (void **)&filter) == S_OK)
+    {
+        hr = find_unconnected_source_from_filter(This, category, majortype, filter, &source_out);
+        IBaseFilter_Release(filter);
+    }
+    else
+    {
+        WARN("Source object does not expose IBaseFilter or IPin.\n");
+        return E_INVALIDARG;
+    }
     if (FAILED(hr))
         return hr;
     return_hr = hr;
diff --git a/dlls/qcap/tests/capturegraph.c b/dlls/qcap/tests/capturegraph.c
index 223bf972de0..629bc92d895 100644
--- a/dlls/qcap/tests/capturegraph.c
+++ b/dlls/qcap/tests/capturegraph.c
@@ -929,12 +929,9 @@ static void test_render_stream(void)
     todo_wine ok(!transform.source1.pin.pin.peer, "Pin should not be connected.\n");
     todo_wine ok(!sink.sink1.pin.pin.peer, "Pin should not be connected.\n");
 
-    if (0)
-    {
-        hr = ICaptureGraphBuilder2_RenderStream(capture_graph, &PIN_CATEGORY_CC, NULL,
-                (IUnknown *)&source.source1.pin.pin.IPin_iface, NULL, &sink.filter.IBaseFilter_iface);
-        ok(hr == E_INVALIDARG, "Got hr %#x.\n", hr);
-    }
+    hr = ICaptureGraphBuilder2_RenderStream(capture_graph, &PIN_CATEGORY_CC, NULL,
+            (IUnknown *)&source.source1.pin.pin.IPin_iface, NULL, &sink.filter.IBaseFilter_iface);
+    ok(hr == E_INVALIDARG, "Got hr %#x.\n", hr);
 
     disconnect_pins(graph, &source.source1);
 
@@ -983,12 +980,9 @@ static void test_render_stream(void)
     check_smart_tee_pin(transform.sink1.pin.pin.peer, L"Capture");
     ok(transform.source1.pin.pin.peer == &sink.sink1.pin.pin.IPin_iface, "Got wrong connection.\n");
 
-    if (0)
-    {
-        hr = ICaptureGraphBuilder2_RenderStream(capture_graph, &PIN_CATEGORY_CAPTURE, NULL,
-                (IUnknown *)&source.filter.IBaseFilter_iface, NULL, &sink.filter.IBaseFilter_iface);
-        ok(hr == E_INVALIDARG, "Got hr %#x.\n", hr);
-    }
+    hr = ICaptureGraphBuilder2_RenderStream(capture_graph, &PIN_CATEGORY_CAPTURE, NULL,
+            (IUnknown *)&source.filter.IBaseFilter_iface, NULL, &sink.filter.IBaseFilter_iface);
+    ok(hr == E_INVALIDARG, "Got hr %#x.\n", hr);
 
     hr = ICaptureGraphBuilder2_RenderStream(capture_graph, &PIN_CATEGORY_PREVIEW, NULL,
             (IUnknown *)&source.filter.IBaseFilter_iface, NULL, &sink.filter.IBaseFilter_iface);
@@ -1014,12 +1008,9 @@ static void test_render_stream(void)
     check_smart_tee_pin(transform.sink1.pin.pin.peer, L"Preview");
     ok(transform.source1.pin.pin.peer == &sink.sink1.pin.pin.IPin_iface, "Got wrong connection.\n");
 
-    if (0)
-    {
-        hr = ICaptureGraphBuilder2_RenderStream(capture_graph, &PIN_CATEGORY_PREVIEW, NULL,
-                (IUnknown *)&source.filter.IBaseFilter_iface, NULL, &sink.filter.IBaseFilter_iface);
-        ok(hr == E_INVALIDARG, "Got hr %#x.\n", hr);
-    }
+    hr = ICaptureGraphBuilder2_RenderStream(capture_graph, &PIN_CATEGORY_PREVIEW, NULL,
+            (IUnknown *)&source.filter.IBaseFilter_iface, NULL, &sink.filter.IBaseFilter_iface);
+    ok(hr == E_INVALIDARG, "Got hr %#x.\n", hr);
 
     disconnect_pins(graph, &source.source1);
     IGraphBuilder_RemoveFilter(graph, &transform.filter.IBaseFilter_iface);
@@ -1031,8 +1022,8 @@ static void test_render_stream(void)
     hr = ICaptureGraphBuilder2_RenderStream(capture_graph, &PIN_CATEGORY_CAPTURE, NULL,
             (IUnknown *)&source.source1.pin.pin.IPin_iface, NULL, &sink.filter.IBaseFilter_iface);
     ok(hr == S_OK, "Got hr %#x.\n", hr);
-    todo_wine check_smart_tee_pin(source.source1.pin.pin.peer, L"Input");
-    todo_wine check_smart_tee_pin(transform.sink1.pin.pin.peer, L"Capture");
+    check_smart_tee_pin(source.source1.pin.pin.peer, L"Input");
+    check_smart_tee_pin(transform.sink1.pin.pin.peer, L"Capture");
     ok(transform.source1.pin.pin.peer == &sink.sink1.pin.pin.IPin_iface, "Got wrong connection.\n");
     disconnect_pins(graph, &source.source1);
     IGraphBuilder_RemoveFilter(graph, &transform.filter.IBaseFilter_iface);
@@ -1062,8 +1053,8 @@ static void test_render_stream(void)
     hr = ICaptureGraphBuilder2_RenderStream(capture_graph, &PIN_CATEGORY_CAPTURE, NULL,
             (IUnknown *)&source.source1.pin.pin.IPin_iface, NULL, &sink.filter.IBaseFilter_iface);
     ok(hr == S_OK, "Got hr %#x.\n", hr);
-    todo_wine check_smart_tee_pin(source.source1.pin.pin.peer, L"Input");
-    todo_wine check_smart_tee_pin(transform.sink1.pin.pin.peer, L"Capture");
+    check_smart_tee_pin(source.source1.pin.pin.peer, L"Input");
+    check_smart_tee_pin(transform.sink1.pin.pin.peer, L"Capture");
     ok(transform.source1.pin.pin.peer == &sink.sink1.pin.pin.IPin_iface, "Got wrong connection.\n");
     disconnect_pins(graph, &source.source1);
     disconnect_pins(graph, &transform.source1);
@@ -1075,9 +1066,9 @@ static void test_render_stream(void)
     ref = IBaseFilter_Release(&source.filter.IBaseFilter_iface);
     ok(!ref, "Got outstanding refcount %d.\n", ref);
     ref = IBaseFilter_Release(&transform.filter.IBaseFilter_iface);
-    todo_wine ok(!ref, "Got outstanding refcount %d.\n", ref);
+    ok(!ref, "Got outstanding refcount %d.\n", ref);
     ref = IBaseFilter_Release(&sink.filter.IBaseFilter_iface);
-    todo_wine ok(!ref, "Got outstanding refcount %d.\n", ref);
+    ok(!ref, "Got outstanding refcount %d.\n", ref);
 }
 
 START_TEST(capturegraph)
-- 
2.26.0




More information about the wine-devel mailing list