Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/quartz/tests/filtergraph.c | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+)
diff --git a/dlls/quartz/tests/filtergraph.c b/dlls/quartz/tests/filtergraph.c index 4d2a3195b6d..2e1a8b7ad66 100644 --- a/dlls/quartz/tests/filtergraph.c +++ b/dlls/quartz/tests/filtergraph.c @@ -3708,6 +3708,35 @@ todo_wine hr = IMediaControl_Stop(control); ok(hr == S_OK, "Got hr %#x.\n", hr);
+ /* Add and remove a filter while the graph is running. */ + + hr = IFilterGraph2_AddFilter(graph, &dummy.IBaseFilter_iface, L"dummy"); + ok(hr == S_OK, "Got hr %#x.\n", hr); + ok(dummy.state == State_Stopped, "Got state %#x.\n", dummy.state); + + hr = IMediaControl_Pause(control); + ok(hr == S_OK, "Got hr %#x.\n", hr); + check_filter_state(graph, State_Paused); + ok(dummy.state == State_Paused, "Got state %#x.\n", dummy.state); + + hr = IFilterGraph2_RemoveFilter(graph, &dummy.IBaseFilter_iface); + ok(hr == S_OK, "Got hr %#x.\n", hr); + todo_wine ok(dummy.state == State_Paused, "Got state %#x.\n", dummy.state); + + hr = IFilterGraph2_AddFilter(graph, &dummy.IBaseFilter_iface, L"dummy"); + ok(hr == S_OK, "Got hr %#x.\n", hr); + todo_wine ok(dummy.state == State_Paused, "Got state %#x.\n", dummy.state); + + if (dummy.state == State_Stopped) + dummy.expect_stop_prev = State_Stopped; + hr = IMediaControl_Stop(control); + ok(hr == S_OK, "Got hr %#x.\n", hr); + check_filter_state(graph, State_Stopped); + + hr = IFilterGraph2_RemoveFilter(graph, &dummy.IBaseFilter_iface); + ok(hr == S_OK, "Got hr %#x.\n", hr); + ok(dummy.state == State_Stopped, "Got state %#x.\n", dummy.state); + /* Destroying the graph while it's running stops all filters. */
hr = IMediaControl_Run(control);
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/quartz/filtergraph.c | 5 ----- dlls/quartz/tests/filtergraph.c | 6 ++---- 2 files changed, 2 insertions(+), 9 deletions(-)
diff --git a/dlls/quartz/filtergraph.c b/dlls/quartz/filtergraph.c index b7f15695a6d..872b355cd35 100644 --- a/dlls/quartz/filtergraph.c +++ b/dlls/quartz/filtergraph.c @@ -720,11 +720,6 @@ static HRESULT WINAPI FilterGraph2_RemoveFilter(IFilterGraph2 *iface, IBaseFilte }
TRACE("Removing filter %s.\n", debugstr_w(entry->name)); - IBaseFilter_GetState(pFilter, 0, &state); - if (state == State_Running) - IBaseFilter_Pause(pFilter); - if (state != State_Stopped) - IBaseFilter_Stop(pFilter);
hr = IBaseFilter_EnumPins(pFilter, &penumpins); if (SUCCEEDED(hr)) { diff --git a/dlls/quartz/tests/filtergraph.c b/dlls/quartz/tests/filtergraph.c index 2e1a8b7ad66..b0f287e7fe2 100644 --- a/dlls/quartz/tests/filtergraph.c +++ b/dlls/quartz/tests/filtergraph.c @@ -3721,14 +3721,12 @@ todo_wine
hr = IFilterGraph2_RemoveFilter(graph, &dummy.IBaseFilter_iface); ok(hr == S_OK, "Got hr %#x.\n", hr); - todo_wine ok(dummy.state == State_Paused, "Got state %#x.\n", dummy.state); + ok(dummy.state == State_Paused, "Got state %#x.\n", dummy.state);
hr = IFilterGraph2_AddFilter(graph, &dummy.IBaseFilter_iface, L"dummy"); ok(hr == S_OK, "Got hr %#x.\n", hr); - todo_wine ok(dummy.state == State_Paused, "Got state %#x.\n", dummy.state); + ok(dummy.state == State_Paused, "Got state %#x.\n", dummy.state);
- if (dummy.state == State_Stopped) - dummy.expect_stop_prev = State_Stopped; hr = IMediaControl_Stop(control); ok(hr == S_OK, "Got hr %#x.\n", hr); check_filter_state(graph, State_Stopped);
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/quartz/tests/filtergraph.c | 79 ++++++++++++++++----------------- 1 file changed, 38 insertions(+), 41 deletions(-)
diff --git a/dlls/quartz/tests/filtergraph.c b/dlls/quartz/tests/filtergraph.c index b0f287e7fe2..1821919a094 100644 --- a/dlls/quartz/tests/filtergraph.c +++ b/dlls/quartz/tests/filtergraph.c @@ -789,7 +789,7 @@ struct testpin IPin IPin_iface; LONG ref; PIN_DIRECTION dir; - IBaseFilter *filter; + struct testfilter *filter; IPin *peer; AM_MEDIA_TYPE *mt; WCHAR name[10]; @@ -806,6 +806,40 @@ struct testpin HRESULT QueryInternalConnections_hr; };
+struct testfilter +{ + IBaseFilter IBaseFilter_iface; + LONG ref; + IFilterGraph *graph; + WCHAR *name; + IReferenceClock *clock; + + IEnumPins IEnumPins_iface; + struct testpin *pins; + unsigned int pin_count, enum_idx; + + FILTER_STATE state; + REFERENCE_TIME start_time; + HRESULT state_hr, GetState_hr, seek_hr; + FILTER_STATE expect_stop_prev, expect_run_prev; + + IAMFilterMiscFlags IAMFilterMiscFlags_iface; + ULONG misc_flags; + + IMediaSeeking IMediaSeeking_iface; + LONG seeking_ref; + DWORD seek_caps; + BOOL support_testguid, support_media_time; + GUID time_format; + LONGLONG seek_duration, seek_current, seek_stop; + double seek_rate; + + IReferenceClock IReferenceClock_iface; + + IFileSourceFilter IFileSourceFilter_iface; + WCHAR filename[MAX_PATH]; +}; + static inline struct testpin *impl_from_IEnumMediaTypes(IEnumMediaTypes *iface) { return CONTAINING_RECORD(iface, struct testpin, IEnumMediaTypes_iface); @@ -954,8 +988,8 @@ static HRESULT WINAPI testpin_QueryPinInfo(IPin *iface, PIN_INFO *info) struct testpin *pin = impl_from_IPin(iface); if (winetest_debug > 1) trace("%p->QueryPinInfo()\n", pin);
- info->pFilter = pin->filter; - IBaseFilter_AddRef(pin->filter); + info->pFilter = &pin->filter->IBaseFilter_iface; + IBaseFilter_AddRef(info->pFilter); info->dir = pin->dir; wcscpy(info->achName, pin->name); return S_OK; @@ -1158,40 +1192,6 @@ static void testsource_init(struct testpin *pin, const AM_MEDIA_TYPE *types, int pin->type_count = type_count; }
-struct testfilter -{ - IBaseFilter IBaseFilter_iface; - LONG ref; - IFilterGraph *graph; - WCHAR *name; - IReferenceClock *clock; - - IEnumPins IEnumPins_iface; - struct testpin *pins; - unsigned int pin_count, enum_idx; - - FILTER_STATE state; - REFERENCE_TIME start_time; - HRESULT state_hr, GetState_hr, seek_hr; - FILTER_STATE expect_stop_prev, expect_run_prev; - - IAMFilterMiscFlags IAMFilterMiscFlags_iface; - ULONG misc_flags; - - IMediaSeeking IMediaSeeking_iface; - LONG seeking_ref; - DWORD seek_caps; - BOOL support_testguid, support_media_time; - GUID time_format; - LONGLONG seek_duration, seek_current, seek_stop; - double seek_rate; - - IReferenceClock IReferenceClock_iface; - - IFileSourceFilter IFileSourceFilter_iface; - WCHAR filename[MAX_PATH]; -}; - static inline struct testfilter *impl_from_IEnumPins(IEnumPins *iface) { return CONTAINING_RECORD(iface, struct testfilter, IEnumPins_iface); @@ -1842,7 +1842,7 @@ static void testfilter_init(struct testfilter *filter, struct testpin *pins, int filter->pins = pins; filter->pin_count = pin_count; for (i = 0; i < pin_count; i++) - pins[i].filter = &filter->IBaseFilter_iface; + pins[i].filter = filter;
filter->state = State_Stopped; filter->expect_stop_prev = filter->expect_run_prev = State_Paused; @@ -3232,9 +3232,6 @@ static void test_filter_state(void) IFilterGraph2_QueryInterface(graph, &IID_IMediaFilter, (void **)&filter); IFilterGraph2_QueryInterface(graph, &IID_IMediaControl, (void **)&control);
- source_pin.filter = &source.IBaseFilter_iface; - sink_pin.filter = &sink.IBaseFilter_iface; - IFilterGraph2_AddFilter(graph, &source.IBaseFilter_iface, NULL); IFilterGraph2_AddFilter(graph, &sink.IBaseFilter_iface, NULL); IFilterGraph2_AddFilter(graph, &dummy.IBaseFilter_iface, NULL);
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=81875
Your paranoid android.
=== w10pro64_ar (64 bit report) ===
quartz: filtergraph.c:533: Test failed: expected 524874, got 0
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/quartz/tests/filtergraph.c | 48 +++++++++++++++++++++++++++++---- 1 file changed, 43 insertions(+), 5 deletions(-)
diff --git a/dlls/quartz/tests/filtergraph.c b/dlls/quartz/tests/filtergraph.c index 1821919a094..7b2aa25a932 100644 --- a/dlls/quartz/tests/filtergraph.c +++ b/dlls/quartz/tests/filtergraph.c @@ -801,6 +801,8 @@ struct testpin AM_MEDIA_TYPE *request_mt, *accept_mt; const struct testpin *require_connected_pin;
+ BOOL require_stopped_disconnect; + HRESULT Connect_hr; HRESULT EnumMediaTypes_hr; HRESULT QueryInternalConnections_hr; @@ -958,6 +960,9 @@ static HRESULT WINAPI testpin_Disconnect(IPin *iface) if (!pin->peer) return S_FALSE;
+ if (pin->require_stopped_disconnect && pin->filter->state != State_Stopped) + return VFW_E_NOT_STOPPED; + IPin_Release(pin->peer); pin->peer = NULL; return S_OK; @@ -2885,6 +2890,7 @@ static void test_connect_direct(void) struct testfilter source, sink, parser1, parser2;
IFilterGraph2 *graph = create_graph(); + IMediaControl *control; AM_MEDIA_TYPE mt; HRESULT hr;
@@ -2905,6 +2911,12 @@ static void test_connect_direct(void) hr = IFilterGraph2_AddFilter(graph, &sink.IBaseFilter_iface, NULL); ok(hr == S_OK, "Got hr %#x.\n", hr);
+ /* The filter graph does not prevent connection while it is running; only + * individual filters do. */ + IFilterGraph2_QueryInterface(graph, &IID_IMediaControl, (void **)&control); + hr = IMediaControl_Pause(control); + ok(hr == S_OK, "Got hr %#x.\n", hr); + hr = IFilterGraph2_ConnectDirect(graph, &source_pin.IPin_iface, &sink_pin.IPin_iface, NULL); ok(hr == S_OK, "Got hr %#x.\n", hr); ok(source_pin.peer == &sink_pin.IPin_iface, "Got peer %p.\n", source_pin.peer); @@ -2999,6 +3011,14 @@ todo_wine
/* Test Reconnect[Ex](). */
+ hr = IFilterGraph2_Reconnect(graph, &source_pin.IPin_iface); + todo_wine ok(hr == VFW_E_WRONG_STATE, "Got hr %#x.\n", hr); + hr = IFilterGraph2_Reconnect(graph, &sink_pin.IPin_iface); + todo_wine ok(hr == VFW_E_WRONG_STATE, "Got hr %#x.\n", hr); + + hr = IMediaControl_Stop(control); + ok(hr == S_OK, "Got hr %#x.\n", hr); + hr = IFilterGraph2_Reconnect(graph, &source_pin.IPin_iface); ok(hr == VFW_E_NOT_CONNECTED, "Got hr %#x.\n", hr); hr = IFilterGraph2_Reconnect(graph, &sink_pin.IPin_iface); @@ -3097,17 +3117,35 @@ todo_wine ok(!source_pin.peer, "Got peer %p.\n", source_pin.peer); ok(!sink_pin.peer, "Got peer %p.\n", sink_pin.peer);
- /* Or when the graph is destroyed. */ + /* If the filter cannot be disconnected, then RemoveFilter() fails. */ + hr = IFilterGraph2_AddFilter(graph, &source.IBaseFilter_iface, NULL); ok(hr == S_OK, "Got hr %#x.\n", hr); - - hr = IFilterGraph2_ConnectDirect(graph, &source_pin.IPin_iface, &sink_pin.IPin_iface, NULL); + hr = IFilterGraph2_ConnectDirect(graph, &source_pin.IPin_iface, &sink_pin.IPin_iface, &mt); + ok(hr == S_OK, "Got hr %#x.\n", hr); + sink_pin.peer = &source_pin.IPin_iface; + IPin_AddRef(sink_pin.peer); + hr = IMediaControl_Pause(control); ok(hr == S_OK, "Got hr %#x.\n", hr); + + source_pin.require_stopped_disconnect = TRUE; + hr = IFilterGraph2_RemoveFilter(graph, &source.IBaseFilter_iface); + todo_wine ok(hr == VFW_E_NOT_STOPPED, "Got hr %#x.\n", hr); ok(source_pin.peer == &sink_pin.IPin_iface, "Got peer %p.\n", source_pin.peer); - ok(!source_pin.mt, "Got mt %p.\n", source_pin.mt); ok(!sink_pin.peer, "Got peer %p.\n", sink_pin.peer); - IPin_AddRef(sink_pin.peer = &source_pin.IPin_iface);
+ sink_pin.peer = &source_pin.IPin_iface; + IPin_AddRef(sink_pin.peer); + source_pin.require_stopped_disconnect = FALSE; + sink_pin.require_stopped_disconnect = TRUE; + hr = IFilterGraph2_RemoveFilter(graph, &source.IBaseFilter_iface); + todo_wine ok(hr == VFW_E_NOT_STOPPED, "Got hr %#x.\n", hr); + ok(source_pin.peer == &sink_pin.IPin_iface, "Got peer %p.\n", source_pin.peer); + ok(sink_pin.peer == &source_pin.IPin_iface, "Got peer %p.\n", sink_pin.peer); + + /* Filters are stopped, and pins disconnected, when the graph is destroyed. */ + + IMediaControl_Release(control); hr = IFilterGraph2_Release(graph); ok(!hr, "Got outstanding refcount %d.\n", hr); ok(source.ref == 1, "Got outstanding refcount %d.\n", source.ref);
Do not try to stop the filter.
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/quartz/filtergraph.c | 44 +++++++++++++++------------------ dlls/quartz/tests/filtergraph.c | 4 +-- 2 files changed, 22 insertions(+), 26 deletions(-)
diff --git a/dlls/quartz/filtergraph.c b/dlls/quartz/filtergraph.c index 872b355cd35..b3aebabbdad 100644 --- a/dlls/quartz/filtergraph.c +++ b/dlls/quartz/filtergraph.c @@ -704,14 +704,11 @@ static HRESULT WINAPI FilterGraph2_RemoveFilter(IFilterGraph2 *iface, IBaseFilte
TRACE("(%p/%p)->(%p)\n", This, iface, pFilter);
- /* FIXME: check graph is stopped */ - LIST_FOR_EACH_ENTRY(entry, &This->filters, struct filter, entry) { if (entry->filter == pFilter) { IEnumPins *penumpins = NULL; - FILTER_STATE state;
if (This->defaultclock && This->refClockProvider == pFilter) { @@ -726,31 +723,30 @@ static HRESULT WINAPI FilterGraph2_RemoveFilter(IFilterGraph2 *iface, IBaseFilte IPin *ppin; while(IEnumPins_Next(penumpins, 1, &ppin, NULL) == S_OK) { - IPin *victim = NULL; - HRESULT h; - IPin_ConnectedTo(ppin, &victim); - if (victim) + IPin *peer = NULL; + HRESULT hr; + + IPin_ConnectedTo(ppin, &peer); + if (peer) { - h = IPin_Disconnect(victim); - TRACE("Disconnect other side: %08x\n", h); - if (h == VFW_E_NOT_STOPPED) + if (FAILED(hr = IPin_Disconnect(peer))) { - PIN_INFO pinfo; - IPin_QueryPinInfo(victim, &pinfo); - - IBaseFilter_GetState(pinfo.pFilter, 0, &state); - if (state == State_Running) - IBaseFilter_Pause(pinfo.pFilter); - IBaseFilter_Stop(pinfo.pFilter); - IBaseFilter_Release(pinfo.pFilter); - h = IPin_Disconnect(victim); - TRACE("Disconnect retry: %08x\n", h); + WARN("Failed to disconnect peer %p, hr %#x.\n", peer, hr); + IPin_Release(peer); + IPin_Release(ppin); + IEnumPins_Release(penumpins); + return hr; } - IPin_Release(victim); - } - h = IPin_Disconnect(ppin); - TRACE("Disconnect 2: %08x\n", h); + IPin_Release(peer);
+ if (FAILED(hr = IPin_Disconnect(ppin))) + { + WARN("Failed to disconnect pin %p, hr %#x.\n", ppin, hr); + IPin_Release(ppin); + IEnumPins_Release(penumpins); + return hr; + } + } IPin_Release(ppin); } IEnumPins_Release(penumpins); diff --git a/dlls/quartz/tests/filtergraph.c b/dlls/quartz/tests/filtergraph.c index 7b2aa25a932..e7ee4e5c446 100644 --- a/dlls/quartz/tests/filtergraph.c +++ b/dlls/quartz/tests/filtergraph.c @@ -3130,7 +3130,7 @@ todo_wine
source_pin.require_stopped_disconnect = TRUE; hr = IFilterGraph2_RemoveFilter(graph, &source.IBaseFilter_iface); - todo_wine ok(hr == VFW_E_NOT_STOPPED, "Got hr %#x.\n", hr); + ok(hr == VFW_E_NOT_STOPPED, "Got hr %#x.\n", hr); ok(source_pin.peer == &sink_pin.IPin_iface, "Got peer %p.\n", source_pin.peer); ok(!sink_pin.peer, "Got peer %p.\n", sink_pin.peer);
@@ -3139,7 +3139,7 @@ todo_wine source_pin.require_stopped_disconnect = FALSE; sink_pin.require_stopped_disconnect = TRUE; hr = IFilterGraph2_RemoveFilter(graph, &source.IBaseFilter_iface); - todo_wine ok(hr == VFW_E_NOT_STOPPED, "Got hr %#x.\n", hr); + ok(hr == VFW_E_NOT_STOPPED, "Got hr %#x.\n", hr); ok(source_pin.peer == &sink_pin.IPin_iface, "Got peer %p.\n", source_pin.peer); ok(sink_pin.peer == &source_pin.IPin_iface, "Got peer %p.\n", sink_pin.peer);
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=81873
Your paranoid android.
=== w10pro64_zh_CN (32 bit report) ===
quartz: filtergraph.c:529: Test failed: didn't get EOS filtergraph.c:533: Test failed: expected 524874, got 0