From: Zebediah Figura Subject: [PATCH 4/4] quartz/filtergraph: Improve HRESULT propagation from IFilterGraph2_Connect(). Message-Id: <1537666318-1055-4-git-send-email-z.figura12@gmail.com> Date: Sat, 22 Sep 2018 20:31:58 -0500 In-Reply-To: <1537666318-1055-1-git-send-email-z.figura12@gmail.com> References: <1537666318-1055-1-git-send-email-z.figura12@gmail.com> Signed-off-by: Zebediah Figura --- dlls/quartz/filtergraph.c | 15 +++++++++--- dlls/quartz/tests/filtergraph.c | 51 ++++++++++++++++++++++++++++++++++++++--- 2 files changed, 60 insertions(+), 6 deletions(-) diff --git a/dlls/quartz/filtergraph.c b/dlls/quartz/filtergraph.c index 0468cb5..7148990 100644 --- a/dlls/quartz/filtergraph.c +++ b/dlls/quartz/filtergraph.c @@ -1181,8 +1181,17 @@ static HRESULT WINAPI FilterGraph2_Connect(IFilterGraph2 *iface, IPin *ppinOut, /* Try direct connection first */ hr = IPin_Connect(ppinOut, ppinIn, NULL); - if (SUCCEEDED(hr)) - goto out; + + /* If direct connection succeeded, we should propagate that return value. + * If it returned VFW_E_NOT_CONNECTED or VFW_E_NO_AUDIO_HARDWARE, then don't + * even bother trying intermediate filters, since they won't succeed. */ + if (SUCCEEDED(hr) || hr == VFW_E_NOT_CONNECTED || hr == VFW_E_NO_AUDIO_HARDWARE) + { + --This->recursioncount; + LeaveCriticalSection(&This->cs); + TRACE("--> %#x\n", hr); + return hr; + } TRACE("Direct connection failed, trying to render using extra filters\n"); @@ -1391,7 +1400,7 @@ out: --This->recursioncount; LeaveCriticalSection(&This->cs); TRACE("--> %08x\n", hr); - return SUCCEEDED(hr) ? S_OK : hr; + return SUCCEEDED(hr) ? S_OK : VFW_E_CANNOT_CONNECT; } /* Render all output pins of the given filter. Helper for FilterGraph2_Render(). */ diff --git a/dlls/quartz/tests/filtergraph.c b/dlls/quartz/tests/filtergraph.c index 6c8b9fa..b40145a 100644 --- a/dlls/quartz/tests/filtergraph.c +++ b/dlls/quartz/tests/filtergraph.c @@ -609,7 +609,6 @@ static void test_render_run(const WCHAR *file) ok(!refs, "Graph has %u references\n", refs); hr = test_graph_builder_connect_file(filename); -todo_wine ok(hr == VFW_E_CANNOT_CONNECT, "got %#x\n", hr); } else @@ -776,6 +775,7 @@ struct testpin unsigned int type_count, enum_idx; AM_MEDIA_TYPE *request_mt, *accept_mt; + HRESULT Connect_hr; HRESULT QueryInternalConnections_hr; }; @@ -1063,6 +1063,7 @@ static void testpin_init(struct testpin *pin, const IPinVtbl *vtbl, PIN_DIRECTIO pin->IEnumMediaTypes_iface.lpVtbl = &testenummt_vtbl; pin->ref = 1; pin->dir = dir; + pin->Connect_hr = S_OK; pin->QueryInternalConnections_hr = E_NOTIMPL; } @@ -1077,12 +1078,16 @@ static HRESULT WINAPI testsource_Connect(IPin *iface, IPin *peer, const AM_MEDIA HRESULT hr; if (winetest_debug > 1) trace("%p->Connect(%p)\n", pin, peer); + if (FAILED(pin->Connect_hr)) + return pin->Connect_hr; + ok(!mt, "Got media type %p.\n", mt); if (SUCCEEDED(hr = IPin_ReceiveConnection(peer, &pin->IPin_iface, pin->request_mt))) { pin->peer = peer; IPin_AddRef(peer); + return pin->Connect_hr; } return hr; } @@ -1711,12 +1716,39 @@ static void test_graph_builder_connect(void) IFilterGraph2_Disconnect(graph, source_pin.peer); IFilterGraph2_Disconnect(graph, &source_pin.IPin_iface); + for (source_pin.Connect_hr = 0x00040200; source_pin.Connect_hr <= 0x000402ff; + ++source_pin.Connect_hr) + { + hr = IFilterGraph2_Connect(graph, &source_pin.IPin_iface, &sink_pin.IPin_iface); + ok(hr == source_pin.Connect_hr, "Got hr %#x for Connect() hr %#x.\n", + hr, source_pin.Connect_hr); + ok(source_pin.peer == &sink_pin.IPin_iface, "Got peer %p.\n", source_pin.peer); + IFilterGraph2_Disconnect(graph, source_pin.peer); + IFilterGraph2_Disconnect(graph, &source_pin.IPin_iface); + } + source_pin.Connect_hr = S_OK; + sink_pin.accept_mt = &sink_type; hr = IFilterGraph2_Connect(graph, &source_pin.IPin_iface, &sink_pin.IPin_iface); -todo_wine ok(hr == VFW_E_CANNOT_CONNECT, "Got hr %#x.\n", hr); ok(!source_pin.peer, "Got peer %p.\n", source_pin.peer); + for (source_pin.Connect_hr = 0x80040200; source_pin.Connect_hr <= 0x800402ff; + ++source_pin.Connect_hr) + { + hr = IFilterGraph2_Connect(graph, &source_pin.IPin_iface, &sink_pin.IPin_iface); + if (source_pin.Connect_hr == VFW_E_NOT_CONNECTED + || source_pin.Connect_hr == VFW_E_NO_AUDIO_HARDWARE) + ok(hr == source_pin.Connect_hr, "Got hr %#x for Connect() hr %#x.\n", + hr, source_pin.Connect_hr); + else + ok(hr == VFW_E_CANNOT_CONNECT, "Got hr %#x for Connect() hr %#x.\n", + hr, source_pin.Connect_hr); + ok(!source_pin.peer, "Got peer %p.\n", source_pin.peer); + ok(!sink_pin.peer, "Got peer %p.\n", sink_pin.peer); + } + source_pin.Connect_hr = S_OK; + /* Test usage of intermediate filters. Similarly to Render(), filters are * simply tried in enumeration order. */ @@ -1740,6 +1772,20 @@ todo_wine IFilterGraph2_Disconnect(graph, sink_pin.peer); IFilterGraph2_Disconnect(graph, &sink_pin.IPin_iface); + for (source_pin.Connect_hr = 0x00040200; source_pin.Connect_hr <= 0x000402ff; + ++source_pin.Connect_hr) + { + hr = IFilterGraph2_Connect(graph, &source_pin.IPin_iface, &sink_pin.IPin_iface); + ok(hr == S_OK, "Got hr %#x for Connect() hr %#x.\n", hr, source_pin.Connect_hr); + ok(source_pin.peer == &parser2_pins[0].IPin_iface, "Got peer %p.\n", source_pin.peer); + ok(sink_pin.peer == &parser2_pins[1].IPin_iface, "Got peer %p.\n", sink_pin.peer); + IFilterGraph2_Disconnect(graph, source_pin.peer); + IFilterGraph2_Disconnect(graph, &source_pin.IPin_iface); + IFilterGraph2_Disconnect(graph, sink_pin.peer); + IFilterGraph2_Disconnect(graph, &sink_pin.IPin_iface); + } + source_pin.Connect_hr = S_OK; + IFilterGraph2_RemoveFilter(graph, &parser1.IBaseFilter_iface); IFilterGraph2_AddFilter(graph, &parser1.IBaseFilter_iface, NULL); @@ -1805,7 +1851,6 @@ todo_wine parser1_pins[1].name[0] = '~'; hr = IFilterGraph2_Connect(graph, &source_pin.IPin_iface, &sink_pin.IPin_iface); -todo_wine ok(hr == VFW_E_CANNOT_CONNECT, "Got hr %#x.\n", hr); ok(!source_pin.peer, "Got peer %p.\n", source_pin.peer); -- 2.7.4