It is not interesting to account for IPin::QueryDirection failing.
Signed-off-by: Zebediah Figura zfigura@codeweavers.com --- dlls/qcap/capturegraph.c | 30 +++++++++++++----------------- 1 file changed, 13 insertions(+), 17 deletions(-)
diff --git a/dlls/qcap/capturegraph.c b/dlls/qcap/capturegraph.c index f258ccb6499..8c85f59bb4c 100644 --- a/dlls/qcap/capturegraph.c +++ b/dlls/qcap/capturegraph.c @@ -574,25 +574,24 @@ fnCaptureGraphBuilder2_CopyCaptureFile(ICaptureGraphBuilder2 * iface, return E_NOTIMPL; }
-static HRESULT pin_matches(IPin *pin, PIN_DIRECTION direction, const GUID *cat, const GUID *type, BOOL unconnected) +static BOOL pin_matches(IPin *pin, PIN_DIRECTION direction, const GUID *cat, const GUID *type, BOOL unconnected) { IPin *partner; PIN_DIRECTION pindir; HRESULT hr;
- hr = IPin_QueryDirection(pin, &pindir); + if (FAILED(hr = IPin_QueryDirection(pin, &pindir))) + ERR("Failed to query direction, hr %#x.\n", hr);
if (unconnected && IPin_ConnectedTo(pin, &partner) == S_OK && partner!=NULL) { IPin_Release(partner); TRACE("No match, %p already connected to %p\n", pin, partner); - return FAILED(hr) ? hr : S_FALSE; + return FALSE; }
- if (FAILED(hr)) - return hr; - if (SUCCEEDED(hr) && pindir != direction) - return S_FALSE; + if (pindir != direction) + return FALSE;
if (cat) { @@ -602,13 +601,13 @@ static HRESULT pin_matches(IPin *pin, PIN_DIRECTION direction, const GUID *cat,
hr = IPin_QueryInterface(pin, &IID_IKsPropertySet, (void**)&props); if (FAILED(hr)) - return S_FALSE; + return FALSE;
hr = IKsPropertySet_Get(props, &ROPSETID_Pin, 0, NULL, 0, &category, sizeof(category), &fetched); IKsPropertySet_Release(props); if (FAILED(hr) || !IsEqualIID(&category, cat)) - return S_FALSE; + return FALSE; }
if (type) @@ -619,14 +618,14 @@ static HRESULT pin_matches(IPin *pin, PIN_DIRECTION direction, const GUID *cat,
hr = IPin_EnumMediaTypes(pin, &types); if (FAILED(hr)) - return S_FALSE; + return FALSE;
IEnumMediaTypes_Reset(types); while (1) { if (IEnumMediaTypes_Next(types, 1, &media_type, &fetched) != S_OK || fetched != 1) { IEnumMediaTypes_Release(types); - return S_FALSE; + return FALSE; }
if (IsEqualIID(&media_type->majortype, type)) @@ -640,7 +639,7 @@ static HRESULT pin_matches(IPin *pin, PIN_DIRECTION direction, const GUID *cat, }
TRACE("Pin matched\n"); - return S_OK; + return TRUE; }
static HRESULT WINAPI @@ -706,13 +705,10 @@ fnCaptureGraphBuilder2_FindPin(ICaptureGraphBuilder2 * iface, }
TRACE("Testing match\n"); - hr = pin_matches(pin, pindir, pCategory, pType, fUnconnected); - if (hr == S_OK && numcurrent++ == num) + if (pin_matches(pin, pindir, pCategory, pType, fUnconnected) && numcurrent++ == num) break; IPin_Release(pin); pin = NULL; - if (FAILED(hr)) - break; } IEnumPins_Release(enumpins); IBaseFilter_Release(filter); @@ -723,7 +719,7 @@ fnCaptureGraphBuilder2_FindPin(ICaptureGraphBuilder2 * iface, return E_FAIL; } } - else if (pin_matches(pin, pindir, pCategory, pType, fUnconnected) != S_OK) + else if (!pin_matches(pin, pindir, pCategory, pType, fUnconnected)) { IPin_Release(pin); return E_FAIL;
Fixes: 15b3eba742301147571f6b168255d52f728d14d6 Signed-off-by: Zebediah Figura zfigura@codeweavers.com --- dlls/qcap/capturegraph.c | 245 ++++++++++----- dlls/qcap/tests/Makefile.in | 1 + dlls/qcap/tests/capturegraph.c | 538 +++++++++++++++++++++++++++++++++ include/axextend.idl | 6 + 4 files changed, 706 insertions(+), 84 deletions(-) create mode 100644 dlls/qcap/tests/capturegraph.c
diff --git a/dlls/qcap/capturegraph.c b/dlls/qcap/capturegraph.c index 8c85f59bb4c..33b0ecfaa11 100644 --- a/dlls/qcap/capturegraph.c +++ b/dlls/qcap/capturegraph.c @@ -222,25 +222,170 @@ fnCaptureGraphBuilder2_SetOutputFileName(ICaptureGraphBuilder2 * iface, return E_NOTIMPL; }
-static HRESULT WINAPI -fnCaptureGraphBuilder2_FindInterface(ICaptureGraphBuilder2 * iface, - const GUID *pCategory, - const GUID *pType, - IBaseFilter *pf, - REFIID riid, - void **ppint) +static BOOL pin_has_majortype(IPin *pin, const GUID *majortype) { - CaptureGraphImpl *This = impl_from_ICaptureGraphBuilder2(iface); + IEnumMediaTypes *enummt; + AM_MEDIA_TYPE *mt;
- FIXME("(%p/%p)->(%s, %s, %p, %s, %p) - workaround stub!\n", This, iface, - debugstr_guid(pCategory), debugstr_guid(pType), - pf, debugstr_guid(riid), ppint); + if (FAILED(IPin_EnumMediaTypes(pin, &enummt))) + return FALSE; + + while (IEnumMediaTypes_Next(enummt, 1, &mt, NULL) == S_OK) + { + if (IsEqualGUID(&mt->majortype, majortype)) + { + DeleteMediaType(mt); + IEnumMediaTypes_Release(enummt); + return TRUE; + } + DeleteMediaType(mt); + } + IEnumMediaTypes_Release(enummt); + return FALSE; +} + +static BOOL pin_matches(IPin *pin, PIN_DIRECTION dir, const GUID *category, + const GUID *majortype, BOOL unconnected) +{ + PIN_DIRECTION candidate_dir; + HRESULT hr; + IPin *peer; + + if (FAILED(hr = IPin_QueryDirection(pin, &candidate_dir))) + ERR("Failed to query direction, hr %#x.\n", hr); + + if (dir != candidate_dir) + return FALSE; + + if (unconnected && IPin_ConnectedTo(pin, &peer) == S_OK && peer) + { + IPin_Release(peer); + return FALSE; + } + + if (category) + { + IKsPropertySet *set; + GUID property; + DWORD size; + + if (FAILED(IPin_QueryInterface(pin, &IID_IKsPropertySet, (void **)&set))) + return FALSE; + + hr = IKsPropertySet_Get(set, &ROPSETID_Pin, AMPROPERTY_PIN_CATEGORY, + NULL, 0, &property, sizeof(property), &size); + IKsPropertySet_Release(set); + if (FAILED(hr) || !IsEqualGUID(&property, category)) + return FALSE; + } + + if (majortype && !pin_has_majortype(pin, majortype)) + return FALSE; + + return TRUE; +} + +static HRESULT find_interface_recurse(PIN_DIRECTION dir, const GUID *category, + const GUID *majortype, IBaseFilter *filter, REFIID iid, void **out) +{ + BOOL found_category = FALSE; + IEnumPins *enumpins; + IPin *pin, *peer; + PIN_INFO info; + HRESULT hr; + + TRACE("Looking for %s pins, category %s, majortype %s from filter %p.\n", + dir == PINDIR_INPUT ? "sink" : "source", debugstr_guid(category), + debugstr_guid(majortype), filter); + + if (FAILED(hr = IBaseFilter_EnumPins(filter, &enumpins))) + { + ERR("Failed to enumerate pins, hr %#x.\n", hr); + return hr; + } + + while (IEnumPins_Next(enumpins, 1, &pin, NULL) == S_OK) + { + if (!pin_matches(pin, dir, category, majortype, FALSE)) + { + IPin_Release(pin); + continue; + } + + if (category) + found_category = TRUE; + + if (IPin_QueryInterface(pin, iid, out) == S_OK) + { + IPin_Release(pin); + IEnumPins_Release(enumpins); + return S_OK; + } + + hr = IPin_ConnectedTo(pin, &peer); + IPin_Release(pin); + if (hr == S_OK) + { + if (IPin_QueryInterface(peer, iid, out) == S_OK) + { + IPin_Release(peer); + IEnumPins_Release(enumpins); + return S_OK; + }
- return IBaseFilter_QueryInterface(pf, riid, ppint); - /* Looks for the specified interface on the filter, upstream and - * downstream from the filter, and, optionally, only on the output - * pin of the given category. - */ + IPin_QueryPinInfo(peer, &info); + IPin_Release(peer); + + if (IBaseFilter_QueryInterface(info.pFilter, iid, out) == S_OK) + { + IBaseFilter_Release(info.pFilter); + IEnumPins_Release(enumpins); + return S_OK; + } + + hr = find_interface_recurse(dir, NULL, NULL, info.pFilter, iid, out); + IBaseFilter_Release(info.pFilter); + if (hr == S_OK) + { + IEnumPins_Release(enumpins); + return S_OK; + } + } + } + IEnumPins_Release(enumpins); + + if (category && !found_category) + return E_NOINTERFACE; + + return E_FAIL; +} + +static HRESULT WINAPI fnCaptureGraphBuilder2_FindInterface(ICaptureGraphBuilder2 *iface, + const GUID *category, const GUID *majortype, IBaseFilter *filter, REFIID iid, void **out) +{ + CaptureGraphImpl *graph = impl_from_ICaptureGraphBuilder2(iface); + HRESULT hr; + + TRACE("graph %p, category %s, majortype %s, filter %p, iid %s, out %p.\n", + graph, debugstr_guid(category), debugstr_guid(majortype), filter, debugstr_guid(iid), out); + + if (category && IsEqualGUID(category, &LOOK_DOWNSTREAM_ONLY)) + return find_interface_recurse(PINDIR_OUTPUT, NULL, NULL, filter, iid, out); + + if (category && IsEqualGUID(category, &LOOK_UPSTREAM_ONLY)) + return find_interface_recurse(PINDIR_INPUT, NULL, NULL, filter, iid, out); + + if (IBaseFilter_QueryInterface(filter, iid, out) == S_OK) + return S_OK; + + if (!category) + majortype = NULL; + + hr = find_interface_recurse(PINDIR_OUTPUT, category, majortype, filter, iid, out); + if (hr == S_OK || hr == E_NOINTERFACE) + return hr; + + return find_interface_recurse(PINDIR_INPUT, NULL, NULL, filter, iid, out); }
static HRESULT match_smart_tee_pin(CaptureGraphImpl *This, @@ -574,74 +719,6 @@ fnCaptureGraphBuilder2_CopyCaptureFile(ICaptureGraphBuilder2 * iface, return E_NOTIMPL; }
-static BOOL pin_matches(IPin *pin, PIN_DIRECTION direction, const GUID *cat, const GUID *type, BOOL unconnected) -{ - IPin *partner; - PIN_DIRECTION pindir; - HRESULT hr; - - if (FAILED(hr = IPin_QueryDirection(pin, &pindir))) - ERR("Failed to query direction, hr %#x.\n", hr); - - if (unconnected && IPin_ConnectedTo(pin, &partner) == S_OK && partner!=NULL) - { - IPin_Release(partner); - TRACE("No match, %p already connected to %p\n", pin, partner); - return FALSE; - } - - if (pindir != direction) - return FALSE; - - if (cat) - { - IKsPropertySet *props; - GUID category; - DWORD fetched; - - hr = IPin_QueryInterface(pin, &IID_IKsPropertySet, (void**)&props); - if (FAILED(hr)) - return FALSE; - - hr = IKsPropertySet_Get(props, &ROPSETID_Pin, 0, NULL, - 0, &category, sizeof(category), &fetched); - IKsPropertySet_Release(props); - if (FAILED(hr) || !IsEqualIID(&category, cat)) - return FALSE; - } - - if (type) - { - IEnumMediaTypes *types; - AM_MEDIA_TYPE *media_type; - ULONG fetched; - - hr = IPin_EnumMediaTypes(pin, &types); - if (FAILED(hr)) - return FALSE; - - IEnumMediaTypes_Reset(types); - while (1) { - if (IEnumMediaTypes_Next(types, 1, &media_type, &fetched) != S_OK || fetched != 1) - { - IEnumMediaTypes_Release(types); - return FALSE; - } - - if (IsEqualIID(&media_type->majortype, type)) - { - DeleteMediaType(media_type); - break; - } - DeleteMediaType(media_type); - } - IEnumMediaTypes_Release(types); - } - - TRACE("Pin matched\n"); - return TRUE; -} - static HRESULT WINAPI fnCaptureGraphBuilder2_FindPin(ICaptureGraphBuilder2 * iface, IUnknown *pSource, diff --git a/dlls/qcap/tests/Makefile.in b/dlls/qcap/tests/Makefile.in index 4c480d524de..43ee5bcd1c5 100644 --- a/dlls/qcap/tests/Makefile.in +++ b/dlls/qcap/tests/Makefile.in @@ -5,6 +5,7 @@ C_SRCS = \ audiorecord.c \ avico.c \ avimux.c \ + capturegraph.c \ qcap.c \ smartteefilter.c \ videocapture.c diff --git a/dlls/qcap/tests/capturegraph.c b/dlls/qcap/tests/capturegraph.c new file mode 100644 index 00000000000..49c4e8fe755 --- /dev/null +++ b/dlls/qcap/tests/capturegraph.c @@ -0,0 +1,538 @@ +/* + * Capture graph builder unit tests + * + * Copyright 2019 Zebediah Figura + * Copyright 2020 Zebediah Figura for CodeWeavers + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#define COBJMACROS +#include "dshow.h" +#include "wine/strmbase.h" +#include "wine/test.h" + +static ICaptureGraphBuilder2 *create_capture_graph(void) +{ + ICaptureGraphBuilder2 *ret; + HRESULT hr = CoCreateInstance(&CLSID_CaptureGraphBuilder2, NULL, + CLSCTX_INPROC_SERVER, &IID_ICaptureGraphBuilder2, (void **)&ret); + ok(hr == S_OK, "Failed to create capture graph builder, hr %#x.\n", hr); + return ret; +} + +static const GUID testiid = {0x11111111}, testtype = {0x22222222}; + +struct testfilter +{ + struct strmbase_filter filter; + struct strmbase_source source, source2; + struct strmbase_sink sink, sink2; + BOOL filter_has_iface, source_has_iface, source2_has_iface, sink_has_iface, sink2_has_iface; + IKsPropertySet IKsPropertySet_iface; +}; + +static inline struct testfilter *impl_from_strmbase_filter(struct strmbase_filter *iface) +{ + return CONTAINING_RECORD(iface, struct testfilter, filter); +} + +static HRESULT testfilter_query_interface(struct strmbase_filter *iface, REFIID iid, void **out) +{ + struct testfilter *filter = impl_from_strmbase_filter(iface); + + ok(!IsEqualGUID(iid, &IID_IKsPropertySet), "Unexpected query for IKsPropertySet.\n"); + + if (filter->filter_has_iface && IsEqualGUID(iid, &testiid)) + *out = &iface->IBaseFilter_iface; + else + return E_NOINTERFACE; + + IUnknown_AddRef((IUnknown *)*out); + return S_OK; +} + +static struct strmbase_pin *testfilter_get_pin(struct strmbase_filter *iface, unsigned int index) +{ + struct testfilter *filter = impl_from_strmbase_filter(iface); + + if (!index) + return &filter->source.pin; + else if (index == 1) + return &filter->sink.pin; + else if (index == 2) + return &filter->source2.pin; + else if (index == 3) + return &filter->sink2.pin; + return NULL; +} + +static void testfilter_destroy(struct strmbase_filter *iface) +{ + struct testfilter *filter = impl_from_strmbase_filter(iface); + strmbase_source_cleanup(&filter->source); + strmbase_sink_cleanup(&filter->sink); + strmbase_filter_cleanup(&filter->filter); +} + +static const struct strmbase_filter_ops testfilter_ops = +{ + .filter_query_interface = testfilter_query_interface, + .filter_get_pin = testfilter_get_pin, + .filter_destroy = testfilter_destroy, +}; + +static struct testfilter *impl_from_IKsPropertySet(IKsPropertySet *iface) +{ + return CONTAINING_RECORD(iface, struct testfilter, IKsPropertySet_iface); +} + +static HRESULT WINAPI property_set_QueryInterface(IKsPropertySet *iface, REFIID iid, void **out) +{ + struct testfilter *filter = impl_from_IKsPropertySet(iface); + return IPin_QueryInterface(&filter->source.pin.IPin_iface, iid, out); +} + +static ULONG WINAPI property_set_AddRef(IKsPropertySet *iface) +{ + struct testfilter *filter = impl_from_IKsPropertySet(iface); + return IPin_AddRef(&filter->source.pin.IPin_iface); +} + +static ULONG WINAPI property_set_Release(IKsPropertySet *iface) +{ + struct testfilter *filter = impl_from_IKsPropertySet(iface); + return IPin_Release(&filter->source.pin.IPin_iface); +} + +static HRESULT WINAPI property_set_Set(IKsPropertySet *iface, REFGUID set, DWORD id, + void *instance_data, DWORD instance_size, void *property_data, DWORD property_size) +{ + ok(0, "Unexpected call.\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI property_set_Get(IKsPropertySet *iface, REFGUID set, DWORD id, + void *instance_data, DWORD instance_size, void *property_data, DWORD property_size, DWORD *ret_size) +{ + if (winetest_debug > 1) trace("Get()\n"); + + ok(IsEqualGUID(set, &ROPSETID_Pin), "Got set %s.\n", debugstr_guid(set)); + ok(id == AMPROPERTY_PIN_CATEGORY, "Got id %#x.\n", id); + ok(!instance_data, "Got instance data %p.\n", instance_data); + ok(!instance_size, "Got instance size %u.\n", instance_size); + ok(property_size == sizeof(GUID), "Got property size %u.\n", property_size); + ok(!!ret_size, "Expected non-NULL return size.\n"); + memcpy(property_data, &PIN_CATEGORY_CAPTURE, sizeof(GUID)); + return S_OK; +} + +static HRESULT WINAPI property_set_QuerySupported(IKsPropertySet *iface, REFGUID set, DWORD id, DWORD *flags) +{ + ok(0, "Unexpected call.\n"); + return E_NOTIMPL; +} + +static const IKsPropertySetVtbl property_set_vtbl = +{ + property_set_QueryInterface, + property_set_AddRef, + property_set_Release, + property_set_Set, + property_set_Get, + property_set_QuerySupported, +}; + +static HRESULT testsource_query_interface(struct strmbase_pin *iface, REFIID iid, void **out) +{ + struct testfilter *filter = impl_from_strmbase_filter(iface->filter); + + if (iface == &filter->source.pin && filter->source_has_iface && IsEqualGUID(iid, &testiid)) + *out = &iface->IPin_iface; + else if (iface == &filter->source2.pin && filter->source2_has_iface && IsEqualGUID(iid, &testiid)) + *out = &iface->IPin_iface; + else if (iface == &filter->source.pin && filter->IKsPropertySet_iface.lpVtbl + && IsEqualGUID(iid, &IID_IKsPropertySet)) + *out = &filter->IKsPropertySet_iface; + else + return E_NOINTERFACE; + + IUnknown_AddRef((IUnknown *)*out); + return S_OK; +} + +static HRESULT testsource_query_accept(struct strmbase_pin *iface, const AM_MEDIA_TYPE *mt) +{ + return S_OK; +} + +static HRESULT testsource_get_media_type(struct strmbase_pin *iface, unsigned int index, AM_MEDIA_TYPE *mt) +{ + if (!index) + { + memset(mt, 0, sizeof(*mt)); + mt->majortype = testtype; + return S_OK; + } + return VFW_S_NO_MORE_ITEMS; +} + +static HRESULT WINAPI testsource_DecideAllocator(struct strmbase_source *iface, + IMemInputPin *input, IMemAllocator **allocator) +{ + return S_OK; +} + +static const struct strmbase_source_ops testsource_ops = +{ + .base.pin_query_interface = testsource_query_interface, + .base.pin_query_accept = testsource_query_accept, + .base.pin_get_media_type = testsource_get_media_type, + .pfnAttemptConnection = BaseOutputPinImpl_AttemptConnection, + .pfnDecideAllocator = testsource_DecideAllocator, +}; + +static HRESULT testsink_query_interface(struct strmbase_pin *iface, REFIID iid, void **out) +{ + struct testfilter *filter = impl_from_strmbase_filter(iface->filter); + + ok(!IsEqualGUID(iid, &IID_IKsPropertySet), "Unexpected query for IKsPropertySet.\n"); + + if (IsEqualGUID(iid, &IID_IMemInputPin)) + *out = &filter->sink.IMemInputPin_iface; + else if (iface == &filter->sink.pin && filter->sink_has_iface && IsEqualGUID(iid, &testiid)) + *out = &iface->IPin_iface; + else if (iface == &filter->sink2.pin && filter->sink2_has_iface && IsEqualGUID(iid, &testiid)) + *out = &iface->IPin_iface; + else + return E_NOINTERFACE; + + IUnknown_AddRef((IUnknown *)*out); + return S_OK; +} + +static HRESULT testsink_query_accept(struct strmbase_pin *iface, const AM_MEDIA_TYPE *mt) +{ + return S_OK; +} + +static const struct strmbase_sink_ops testsink_ops = +{ + .base.pin_query_interface = testsink_query_interface, + .base.pin_query_accept = testsink_query_accept, + .base.pin_get_media_type = strmbase_pin_get_media_type, +}; + +static void reset_interfaces(struct testfilter *filter) +{ + filter->filter_has_iface = filter->sink_has_iface = filter->sink2_has_iface = TRUE; + filter->source_has_iface = filter->source2_has_iface = TRUE; +} + +static void testfilter_init(struct testfilter *filter) +{ + static const GUID clsid = {0xabacab}; + memset(filter, 0, sizeof(*filter)); + strmbase_filter_init(&filter->filter, NULL, &clsid, &testfilter_ops); + strmbase_source_init(&filter->source, &filter->filter, L"source", &testsource_ops); + strmbase_source_init(&filter->source2, &filter->filter, L"source2", &testsource_ops); + strmbase_sink_init(&filter->sink, &filter->filter, L"sink", &testsink_ops, NULL); + strmbase_sink_init(&filter->sink2, &filter->filter, L"sink2", &testsink_ops, NULL); + reset_interfaces(filter); +} + +static void test_find_interface(void) +{ + static const AM_MEDIA_TYPE mt1 = + { + .majortype = {0x111}, + .subtype = {0x222}, + .formattype = {0x333}, + }; + static const AM_MEDIA_TYPE mt2 = + { + .majortype = {0x444}, + .subtype = {0x555}, + .formattype = {0x666}, + }; + static const GUID bogus_majortype = {0x777}; + + ICaptureGraphBuilder2 *capture_graph = create_capture_graph(); + struct testfilter filter1, filter2, filter3; + IGraphBuilder *graph; + unsigned int i; + IUnknown *unk; + HRESULT hr; + ULONG ref; + + struct + { + BOOL *expose; + const void *iface; + } + tests_from_filter2[] = + { + {&filter2.filter_has_iface, &filter2.filter.IBaseFilter_iface}, + {&filter2.source_has_iface, &filter2.source.pin.IPin_iface}, + {&filter3.sink_has_iface, &filter3.sink.pin.IPin_iface}, + {&filter3.filter_has_iface, &filter3.filter.IBaseFilter_iface}, + {&filter3.source_has_iface, &filter3.source.pin.IPin_iface}, + {&filter3.source2_has_iface, &filter3.source2.pin.IPin_iface}, + {&filter2.source2_has_iface, &filter2.source2.pin.IPin_iface}, + {&filter2.sink_has_iface, &filter2.sink.pin.IPin_iface}, + {&filter1.source_has_iface, &filter1.source.pin.IPin_iface}, + {&filter1.filter_has_iface, &filter1.filter.IBaseFilter_iface}, + {&filter1.sink_has_iface, &filter1.sink.pin.IPin_iface}, + {&filter1.sink2_has_iface, &filter1.sink2.pin.IPin_iface}, + {&filter2.sink2_has_iface, &filter2.sink2.pin.IPin_iface}, + }, tests_from_filter1[] = + { + {&filter1.filter_has_iface, &filter1.filter.IBaseFilter_iface}, + {&filter1.source_has_iface, &filter1.source.pin.IPin_iface}, + {&filter2.sink_has_iface, &filter2.sink.pin.IPin_iface}, + {&filter2.filter_has_iface, &filter2.filter.IBaseFilter_iface}, + {&filter2.source_has_iface, &filter2.source.pin.IPin_iface}, + {&filter3.sink_has_iface, &filter3.sink.pin.IPin_iface}, + {&filter3.filter_has_iface, &filter3.filter.IBaseFilter_iface}, + {&filter3.source_has_iface, &filter3.source.pin.IPin_iface}, + {&filter3.source2_has_iface, &filter3.source2.pin.IPin_iface}, + {&filter2.source2_has_iface, &filter2.source2.pin.IPin_iface}, + {&filter1.source2_has_iface, &filter1.source2.pin.IPin_iface}, + {&filter1.sink_has_iface, &filter1.sink.pin.IPin_iface}, + {&filter1.sink2_has_iface, &filter1.sink2.pin.IPin_iface}, + }, look_upstream_tests[] = + { + {&filter2.sink_has_iface, &filter2.sink.pin.IPin_iface}, + {&filter1.source_has_iface, &filter1.source.pin.IPin_iface}, + {&filter1.filter_has_iface, &filter1.filter.IBaseFilter_iface}, + {&filter1.sink_has_iface, &filter1.sink.pin.IPin_iface}, + {&filter1.sink2_has_iface, &filter1.sink2.pin.IPin_iface}, + {&filter2.sink2_has_iface, &filter2.sink2.pin.IPin_iface}, + }, look_downstream_tests[] = + { + {&filter2.source_has_iface, &filter2.source.pin.IPin_iface}, + {&filter3.sink_has_iface, &filter3.sink.pin.IPin_iface}, + {&filter3.filter_has_iface, &filter3.filter.IBaseFilter_iface}, + {&filter3.source_has_iface, &filter3.source.pin.IPin_iface}, + {&filter3.source2_has_iface, &filter3.source2.pin.IPin_iface}, + {&filter2.source2_has_iface, &filter2.source2.pin.IPin_iface}, + }, category_tests[] = + { + {&filter3.filter_has_iface, &filter3.filter.IBaseFilter_iface}, + {&filter3.source_has_iface, &filter3.source.pin.IPin_iface}, + {&filter3.source2_has_iface, &filter3.source2.pin.IPin_iface}, + {&filter2.sink_has_iface, &filter2.sink.pin.IPin_iface}, + {&filter1.source_has_iface, &filter1.source.pin.IPin_iface}, + {&filter1.filter_has_iface, &filter1.filter.IBaseFilter_iface}, + {&filter1.sink_has_iface, &filter1.sink.pin.IPin_iface}, + {&filter1.sink2_has_iface, &filter1.sink2.pin.IPin_iface}, + {&filter2.sink2_has_iface, &filter2.sink2.pin.IPin_iface}, + }; + + CoCreateInstance(&CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, &IID_IGraphBuilder, (void **)&graph); + hr = ICaptureGraphBuilder2_SetFiltergraph(capture_graph, graph); + ok(hr == S_OK, "Got hr %#x.\n", hr); + + testfilter_init(&filter1); + IGraphBuilder_AddFilter(graph, &filter1.filter.IBaseFilter_iface, L"filter1"); + testfilter_init(&filter2); + IGraphBuilder_AddFilter(graph, &filter2.filter.IBaseFilter_iface, L"filter2"); + testfilter_init(&filter3); + IGraphBuilder_AddFilter(graph, &filter3.filter.IBaseFilter_iface, L"filter3"); + + hr = IGraphBuilder_ConnectDirect(graph, &filter1.source.pin.IPin_iface, &filter2.sink.pin.IPin_iface, &mt1); + ok(hr == S_OK, "Got hr %#x.\n", hr); + hr = IGraphBuilder_ConnectDirect(graph, &filter2.source.pin.IPin_iface, &filter3.sink.pin.IPin_iface, &mt2); + ok(hr == S_OK, "Got hr %#x.\n", hr); + + /* Test search order without any restrictions applied. */ + + for (i = 0; i < ARRAY_SIZE(tests_from_filter2); ++i) + { + hr = ICaptureGraphBuilder2_FindInterface(capture_graph, NULL, &bogus_majortype, + &filter2.filter.IBaseFilter_iface, &testiid, (void **)&unk); + ok(hr == S_OK, "Test %u: got hr %#x.\n", i, hr); + ok(unk == tests_from_filter2[i].iface, "Test %u: got wrong interface %p.\n", i, unk); + IUnknown_Release(unk); + *tests_from_filter2[i].expose = FALSE; + } + + hr = ICaptureGraphBuilder2_FindInterface(capture_graph, NULL, &bogus_majortype, + &filter2.filter.IBaseFilter_iface, &testiid, (void **)&unk); + ok(hr == E_FAIL, "Got hr %#x.\n", hr); + + reset_interfaces(&filter1); + reset_interfaces(&filter2); + reset_interfaces(&filter3); + + for (i = 0; i < ARRAY_SIZE(tests_from_filter1); ++i) + { + hr = ICaptureGraphBuilder2_FindInterface(capture_graph, NULL, &bogus_majortype, + &filter1.filter.IBaseFilter_iface, &testiid, (void **)&unk); + ok(hr == S_OK, "Test %u: got hr %#x.\n", i, hr); + ok(unk == tests_from_filter1[i].iface, "Test %u: got wrong interface %p.\n", i, unk); + IUnknown_Release(unk); + *tests_from_filter1[i].expose = FALSE; + } + + hr = ICaptureGraphBuilder2_FindInterface(capture_graph, NULL, &bogus_majortype, + &filter1.filter.IBaseFilter_iface, &testiid, (void **)&unk); + ok(hr == E_FAIL, "Got hr %#x.\n", hr); + + /* Test with upstream/downstream flags. */ + + reset_interfaces(&filter1); + reset_interfaces(&filter2); + reset_interfaces(&filter3); + + for (i = 0; i < ARRAY_SIZE(look_upstream_tests); ++i) + { + hr = ICaptureGraphBuilder2_FindInterface(capture_graph, &LOOK_UPSTREAM_ONLY, &bogus_majortype, + &filter2.filter.IBaseFilter_iface, &testiid, (void **)&unk); + ok(hr == S_OK, "Test %u: got hr %#x.\n", i, hr); + ok(unk == look_upstream_tests[i].iface, "Test %u: got wrong interface %p.\n", i, unk); + IUnknown_Release(unk); + *look_upstream_tests[i].expose = FALSE; + } + + hr = ICaptureGraphBuilder2_FindInterface(capture_graph, &LOOK_UPSTREAM_ONLY, &bogus_majortype, + &filter2.filter.IBaseFilter_iface, &testiid, (void **)&unk); + ok(hr == E_FAIL, "Got hr %#x.\n", hr); + + reset_interfaces(&filter1); + reset_interfaces(&filter2); + reset_interfaces(&filter3); + + for (i = 0; i < ARRAY_SIZE(look_downstream_tests); ++i) + { + hr = ICaptureGraphBuilder2_FindInterface(capture_graph, &LOOK_DOWNSTREAM_ONLY, &bogus_majortype, + &filter2.filter.IBaseFilter_iface, &testiid, (void **)&unk); + ok(hr == S_OK, "Test %u: got hr %#x.\n", i, hr); + ok(unk == look_downstream_tests[i].iface, "Test %u: got wrong interface %p.\n", i, unk); + IUnknown_Release(unk); + *look_downstream_tests[i].expose = FALSE; + } + + hr = ICaptureGraphBuilder2_FindInterface(capture_graph, &LOOK_DOWNSTREAM_ONLY, &bogus_majortype, + &filter2.filter.IBaseFilter_iface, &testiid, (void **)&unk); + ok(hr == E_FAIL, "Got hr %#x.\n", hr); + + /* Test with a category flag. */ + + reset_interfaces(&filter1); + reset_interfaces(&filter2); + reset_interfaces(&filter3); + + hr = ICaptureGraphBuilder2_FindInterface(capture_graph, &PIN_CATEGORY_CAPTURE, NULL, + &filter2.filter.IBaseFilter_iface, &testiid, (void **)&unk); + ok(hr == S_OK, "Got hr %#x\n", hr); + ok(unk == (IUnknown *)&filter2.filter.IBaseFilter_iface, "Got wrong interface %p.\n", unk); + IUnknown_Release(unk); + filter2.filter_has_iface = FALSE; + + hr = ICaptureGraphBuilder2_FindInterface(capture_graph, &PIN_CATEGORY_CAPTURE, NULL, + &filter2.filter.IBaseFilter_iface, &testiid, (void **)&unk); + ok(hr == E_NOINTERFACE, "Got hr %#x.\n", hr); + + filter2.IKsPropertySet_iface.lpVtbl = &property_set_vtbl; + hr = ICaptureGraphBuilder2_FindInterface(capture_graph, &PIN_CATEGORY_CAPTURE, NULL, + &filter2.filter.IBaseFilter_iface, &testiid, (void **)&unk); + ok(hr == S_OK, "Got hr %#x.\n", hr); + ok(unk == (IUnknown *)&filter2.source.pin.IPin_iface, "Got wrong interface %p.\n", unk); + IUnknown_Release(unk); + filter2.source_has_iface = FALSE; + + /* Native returns the filter3 sink next, but suffers from a bug wherein it + * releases a reference to the wrong pin. */ + filter3.sink_has_iface = FALSE; + + for (i = 0; i < ARRAY_SIZE(category_tests); ++i) + { + hr = ICaptureGraphBuilder2_FindInterface(capture_graph, &PIN_CATEGORY_CAPTURE, NULL, + &filter2.filter.IBaseFilter_iface, &testiid, (void **)&unk); + ok(hr == S_OK, "Test %u: got hr %#x.\n", i, hr); + ok(unk == category_tests[i].iface, "Test %u: got wrong interface %p.\n", i, unk); + IUnknown_Release(unk); + *category_tests[i].expose = FALSE; + } + + hr = ICaptureGraphBuilder2_FindInterface(capture_graph, &PIN_CATEGORY_CAPTURE, NULL, + &filter2.filter.IBaseFilter_iface, &testiid, (void **)&unk); + ok(hr == E_FAIL, "Got hr %#x.\n", hr); + + /* Test with a media type. */ + + reset_interfaces(&filter1); + reset_interfaces(&filter2); + reset_interfaces(&filter3); + + hr = ICaptureGraphBuilder2_FindInterface(capture_graph, &PIN_CATEGORY_CAPTURE, &bogus_majortype, + &filter2.filter.IBaseFilter_iface, &testiid, (void **)&unk); + ok(hr == S_OK, "Got hr %#x\n", hr); + ok(unk == (IUnknown *)&filter2.filter.IBaseFilter_iface, "Got wrong interface %p.\n", unk); + IUnknown_Release(unk); + filter2.filter_has_iface = FALSE; + + hr = ICaptureGraphBuilder2_FindInterface(capture_graph, &PIN_CATEGORY_CAPTURE, &bogus_majortype, + &filter2.filter.IBaseFilter_iface, &testiid, (void **)&unk); + ok(hr == E_NOINTERFACE, "Got hr %#x.\n", hr); + + hr = ICaptureGraphBuilder2_FindInterface(capture_graph, &PIN_CATEGORY_CAPTURE, &mt2.majortype, + &filter2.filter.IBaseFilter_iface, &testiid, (void **)&unk); + ok(hr == E_NOINTERFACE, "Got hr %#x.\n", hr); + + hr = ICaptureGraphBuilder2_FindInterface(capture_graph, &PIN_CATEGORY_CAPTURE, &testtype, + &filter2.filter.IBaseFilter_iface, &testiid, (void **)&unk); + ok(hr == S_OK, "Got hr %#x.\n", hr); + ok(unk == (IUnknown *)&filter2.source.pin.IPin_iface, "Got wrong interface %p.\n", unk); + IUnknown_Release(unk); + filter2.source_has_iface = FALSE; + + filter3.sink_has_iface = FALSE; + + for (i = 0; i < ARRAY_SIZE(category_tests); ++i) + { + hr = ICaptureGraphBuilder2_FindInterface(capture_graph, &PIN_CATEGORY_CAPTURE, NULL, + &filter2.filter.IBaseFilter_iface, &testiid, (void **)&unk); + ok(hr == S_OK, "Test %u: got hr %#x.\n", i, hr); + ok(unk == category_tests[i].iface, "Test %u: got wrong interface %p.\n", i, unk); + IUnknown_Release(unk); + *category_tests[i].expose = FALSE; + } + + hr = ICaptureGraphBuilder2_FindInterface(capture_graph, &PIN_CATEGORY_CAPTURE, NULL, + &filter2.filter.IBaseFilter_iface, &testiid, (void **)&unk); + ok(hr == E_FAIL, "Got hr %#x.\n", hr); + + ref = ICaptureGraphBuilder2_Release(capture_graph); + ok(!ref, "Got outstanding refcount %d.\n", ref); + ref = IGraphBuilder_Release(graph); + ok(!ref, "Got outstanding refcount %d.\n", ref); + ref = IBaseFilter_Release(&filter1.filter.IBaseFilter_iface); + ok(!ref, "Got outstanding refcount %d.\n", ref); + ref = IBaseFilter_Release(&filter2.filter.IBaseFilter_iface); + ok(!ref, "Got outstanding refcount %d.\n", ref); + ref = IBaseFilter_Release(&filter3.filter.IBaseFilter_iface); + ok(!ref, "Got outstanding refcount %d.\n", ref); +} + +START_TEST(capturegraph) +{ + CoInitializeEx(NULL, COINIT_MULTITHREADED); + + test_find_interface(); + + CoUninitialize(); +} diff --git a/include/axextend.idl b/include/axextend.idl index fd231bca3c4..2156b13315f 100644 --- a/include/axextend.idl +++ b/include/axextend.idl @@ -1153,6 +1153,12 @@ cpp_quote("#define _IKsPropertySet_") cpp_quote("#define KSPROPERTY_SUPPORT_GET 1") cpp_quote("#define KSPROPERTY_SUPPORT_SET 2")
+typedef enum AMPROPERTY_PIN +{ + AMPROPERTY_PIN_CATEGORY, + AMPROPERTY_PIN_MEDIUM, +} AMPROPERTY_PIN; + [ object, uuid(31efac30-515c-11d0-a9aa-00aa0061be93),
PowerPoint 2016 tries to build a graph by autoplugging the file source to the sample grabber; direct connection should fail here.
Signed-off-by: Zebediah Figura zfigura@codeweavers.com --- dlls/quartz/filesource.c | 3 ++- dlls/quartz/tests/filesource.c | 30 +++++------------------------- 2 files changed, 7 insertions(+), 26 deletions(-)
diff --git a/dlls/quartz/filesource.c b/dlls/quartz/filesource.c index c683283752b..8fed09cab0d 100644 --- a/dlls/quartz/filesource.c +++ b/dlls/quartz/filesource.c @@ -605,7 +605,8 @@ static HRESULT WINAPI FileAsyncReaderPin_AttemptConnection(struct strmbase_sourc
TRACE("%p->(%p, %p)\n", This, pReceivePin, pmt);
- /* FIXME: call queryacceptproc */ + if (This->pin.ops->pin_query_accept(&This->pin, pmt) != S_OK) + return VFW_E_TYPE_NOT_ACCEPTED;
This->pin.peer = pReceivePin; IPin_AddRef(pReceivePin); diff --git a/dlls/quartz/tests/filesource.c b/dlls/quartz/tests/filesource.c index 846b92ac60b..2040910516f 100644 --- a/dlls/quartz/tests/filesource.c +++ b/dlls/quartz/tests/filesource.c @@ -1363,12 +1363,7 @@ static void test_connect_pin(void)
req_mt.majortype = MEDIATYPE_Video; hr = IFilterGraph2_ConnectDirect(graph, source, &testsink.pin.pin.IPin_iface, &req_mt); - todo_wine ok(hr == VFW_E_TYPE_NOT_ACCEPTED, "Got hr %#x.\n", hr); - if (hr == S_OK) - { - IFilterGraph2_Disconnect(graph, source); - IFilterGraph2_Disconnect(graph, &testsink.pin.pin.IPin_iface); - } + ok(hr == VFW_E_TYPE_NOT_ACCEPTED, "Got hr %#x.\n", hr); req_mt.majortype = MEDIATYPE_Stream;
req_mt.subtype = MEDIASUBTYPE_RGB8; @@ -1379,12 +1374,7 @@ static void test_connect_pin(void) IFilterGraph2_Disconnect(graph, &testsink.pin.pin.IPin_iface); req_mt.subtype = GUID_NULL; hr = IFilterGraph2_ConnectDirect(graph, source, &testsink.pin.pin.IPin_iface, &req_mt); - todo_wine ok(hr == VFW_E_TYPE_NOT_ACCEPTED, "Got hr %#x.\n", hr); - if (hr == S_OK) - { - IFilterGraph2_Disconnect(graph, source); - IFilterGraph2_Disconnect(graph, &testsink.pin.pin.IPin_iface); - } + ok(hr == VFW_E_TYPE_NOT_ACCEPTED, "Got hr %#x.\n", hr); req_mt.subtype = MEDIASUBTYPE_Avi;
/* Test connection with wildcards. */ @@ -1445,12 +1435,7 @@ static void test_connect_pin(void) * consistent with its being rejected by IPin::QueryAccept(). */ testsink.reject_avi = TRUE; hr = IFilterGraph2_ConnectDirect(graph, source, &testsink.pin.pin.IPin_iface, NULL); - todo_wine ok(hr == VFW_E_NO_ACCEPTABLE_TYPES, "Got hr %#x.\n", hr); - if (hr == S_OK) - { - IFilterGraph2_Disconnect(graph, source); - IFilterGraph2_Disconnect(graph, &testsink.pin.pin.IPin_iface); - } + ok(hr == VFW_E_NO_ACCEPTABLE_TYPES, "Got hr %#x.\n", hr);
/* But any types we expose are tried. */ testsink.mt = &mt; @@ -1459,17 +1444,12 @@ static void test_connect_pin(void) mt.subtype = MEDIASUBTYPE_RGB8; mt.formattype = FORMAT_None; hr = IFilterGraph2_ConnectDirect(graph, source, &testsink.pin.pin.IPin_iface, NULL); - todo_wine ok(hr == VFW_E_NO_ACCEPTABLE_TYPES, "Got hr %#x.\n", hr); - if (hr == S_OK) - { - IFilterGraph2_Disconnect(graph, source); - IFilterGraph2_Disconnect(graph, &testsink.pin.pin.IPin_iface); - } + ok(hr == VFW_E_NO_ACCEPTABLE_TYPES, "Got hr %#x.\n", hr);
mt.majortype = MEDIATYPE_Stream; hr = IFilterGraph2_ConnectDirect(graph, source, &testsink.pin.pin.IPin_iface, NULL); ok(hr == S_OK, "Got hr %#x.\n", hr); - todo_wine ok(compare_media_types(&testsink.pin.pin.mt, &mt), "Media types didn't match.\n"); + ok(compare_media_types(&testsink.pin.pin.mt, &mt), "Media types didn't match.\n"); IFilterGraph2_Disconnect(graph, source); IFilterGraph2_Disconnect(graph, &testsink.pin.pin.IPin_iface);
Signed-off-by: Zebediah Figura zfigura@codeweavers.com --- dlls/qedit/samplegrabber.c | 64 ++++++++++++-------------------- dlls/qedit/tests/samplegrabber.c | 12 +++--- 2 files changed, 30 insertions(+), 46 deletions(-)
diff --git a/dlls/qedit/samplegrabber.c b/dlls/qedit/samplegrabber.c index 10e85dfc37f..ad458cbaa14 100644 --- a/dlls/qedit/samplegrabber.c +++ b/dlls/qedit/samplegrabber.c @@ -480,9 +480,31 @@ static HRESULT sample_grabber_sink_query_interface(struct strmbase_pin *iface, R return S_OK; }
+static BOOL check_filter_mt(SG_Impl *filter, const AM_MEDIA_TYPE *mt) +{ + if (IsEqualGUID(&filter->filter_mt.majortype, &GUID_NULL)) + return TRUE; + if (!IsEqualGUID(&filter->filter_mt.majortype, &mt->majortype)) + return FALSE; + + if (IsEqualGUID(&filter->filter_mt.subtype, &GUID_NULL)) + return TRUE; + if (!IsEqualGUID(&filter->filter_mt.subtype, &mt->subtype)) + return FALSE; + + if (IsEqualGUID(&filter->filter_mt.formattype, &GUID_NULL)) + return TRUE; + if (!IsEqualGUID(&filter->filter_mt.formattype, &mt->formattype)) + return FALSE; + + return TRUE; +} + static HRESULT sample_grabber_sink_query_accept(struct strmbase_pin *iface, const AM_MEDIA_TYPE *mt) { - return S_OK; + SG_Impl *filter = impl_from_sink_pin(iface); + + return check_filter_mt(filter, mt) ? S_OK : S_FALSE; }
static HRESULT sample_grabber_sink_get_media_type(struct strmbase_pin *iface, @@ -498,32 +520,11 @@ static HRESULT sample_grabber_sink_get_media_type(struct strmbase_pin *iface, return VFW_S_NO_MORE_ITEMS; }
-static HRESULT sample_grabber_sink_connect(struct strmbase_sink *iface, - IPin *peer, const AM_MEDIA_TYPE *mt) -{ - SG_Impl *filter = impl_from_sink_pin(&iface->pin); - - if (!IsEqualGUID(&filter->filter_mt.majortype, &GUID_NULL) - && !IsEqualGUID(&filter->filter_mt.majortype, &mt->majortype)) - return VFW_E_TYPE_NOT_ACCEPTED; - - if (!IsEqualGUID(&filter->filter_mt.subtype, &GUID_NULL) - && !IsEqualGUID(&filter->filter_mt.subtype, &mt->subtype)) - return VFW_E_TYPE_NOT_ACCEPTED; - - if (!IsEqualGUID(&filter->filter_mt.formattype, &GUID_NULL) - && !IsEqualGUID(&filter->filter_mt.formattype, &mt->formattype)) - return VFW_E_TYPE_NOT_ACCEPTED; - - return S_OK; -} - static const struct strmbase_sink_ops sink_ops = { .base.pin_query_interface = sample_grabber_sink_query_interface, .base.pin_query_accept = sample_grabber_sink_query_accept, .base.pin_get_media_type = sample_grabber_sink_get_media_type, - .sink_connect = sample_grabber_sink_connect, };
static inline SG_Impl *impl_from_source_pin(struct strmbase_pin *iface) @@ -548,24 +549,7 @@ static HRESULT sample_grabber_source_query_accept(struct strmbase_pin *iface, co if (filter->sink.pin.peer && IPin_QueryAccept(filter->sink.pin.peer, mt) != S_OK) return S_FALSE;
- strmbase_dump_media_type(&filter->filter_mt); - - if (IsEqualGUID(&filter->filter_mt.majortype, &GUID_NULL)) - return S_OK; - if (!IsEqualGUID(&filter->filter_mt.majortype, &mt->majortype)) - return S_FALSE; - - if (IsEqualGUID(&filter->filter_mt.subtype, &GUID_NULL)) - return S_OK; - if (!IsEqualGUID(&filter->filter_mt.subtype, &mt->subtype)) - return S_FALSE; - - if (IsEqualGUID(&filter->filter_mt.formattype, &GUID_NULL)) - return S_OK; - if (!IsEqualGUID(&filter->filter_mt.formattype, &mt->formattype)) - return S_FALSE; - - return S_OK; + return check_filter_mt(filter, mt) ? S_OK : S_FALSE; }
static HRESULT sample_grabber_source_get_media_type(struct strmbase_pin *iface, diff --git a/dlls/qedit/tests/samplegrabber.c b/dlls/qedit/tests/samplegrabber.c index 06db9d740e6..5436700d17d 100644 --- a/dlls/qedit/tests/samplegrabber.c +++ b/dlls/qedit/tests/samplegrabber.c @@ -513,13 +513,13 @@ static void test_media_types(void) hr = ISampleGrabber_SetMediaType(grabber, &match_mt); ok(hr == S_OK, "Got hr %#x.\n", hr); hr = IPin_QueryAccept(sink, &mt); - todo_wine ok(hr == S_FALSE, "Got hr %#x.\n", hr); + ok(hr == S_FALSE, "Got hr %#x.\n", hr); hr = IPin_QueryAccept(source, &mt); ok(hr == S_FALSE, "Got hr %#x.\n", hr);
mt.majortype = GUID_NULL; hr = IPin_QueryAccept(sink, &mt); - todo_wine ok(hr == S_FALSE, "Got hr %#x.\n", hr); + ok(hr == S_FALSE, "Got hr %#x.\n", hr); hr = IPin_QueryAccept(source, &mt); ok(hr == S_FALSE, "Got hr %#x.\n", hr); mt.majortype = match_mt.majortype; @@ -533,13 +533,13 @@ static void test_media_types(void) hr = ISampleGrabber_SetMediaType(grabber, &match_mt); ok(hr == S_OK, "Got hr %#x.\n", hr); hr = IPin_QueryAccept(sink, &mt); - todo_wine ok(hr == S_FALSE, "Got hr %#x.\n", hr); + ok(hr == S_FALSE, "Got hr %#x.\n", hr); hr = IPin_QueryAccept(source, &mt); ok(hr == S_FALSE, "Got hr %#x.\n", hr);
mt.subtype = GUID_NULL; hr = IPin_QueryAccept(sink, &mt); - todo_wine ok(hr == S_FALSE, "Got hr %#x.\n", hr); + ok(hr == S_FALSE, "Got hr %#x.\n", hr); hr = IPin_QueryAccept(source, &mt); ok(hr == S_FALSE, "Got hr %#x.\n", hr); mt.subtype = match_mt.subtype; @@ -552,13 +552,13 @@ static void test_media_types(void) hr = ISampleGrabber_SetMediaType(grabber, &match_mt); ok(hr == S_OK, "Got hr %#x.\n", hr); hr = IPin_QueryAccept(sink, &mt); - todo_wine ok(hr == S_FALSE, "Got hr %#x.\n", hr); + ok(hr == S_FALSE, "Got hr %#x.\n", hr); hr = IPin_QueryAccept(source, &mt); ok(hr == S_FALSE, "Got hr %#x.\n", hr);
mt.formattype = GUID_NULL; hr = IPin_QueryAccept(sink, &mt); - todo_wine ok(hr == S_FALSE, "Got hr %#x.\n", hr); + ok(hr == S_FALSE, "Got hr %#x.\n", hr); hr = IPin_QueryAccept(source, &mt); ok(hr == S_FALSE, "Got hr %#x.\n", hr); mt.formattype = match_mt.formattype;
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=66479
Your paranoid android.
=== debiant (32 bit Chinese:China report) ===
d3d11: d3d11.c:17958: Test failed: Got {0x00000001, 0xffffffff, 0x00000000, 0x00000000}, expected {0x00000001, 0x00000000, 0x00000000, 0x00000000} at (0, 0), sub-resource 0.
Signed-off-by: Zebediah Figura zfigura@codeweavers.com --- dlls/qedit/samplegrabber.c | 18 ++++++++++++++++-- dlls/qedit/tests/samplegrabber.c | 17 +++++++++++------ 2 files changed, 27 insertions(+), 8 deletions(-)
diff --git a/dlls/qedit/samplegrabber.c b/dlls/qedit/samplegrabber.c index ad458cbaa14..7e29154762b 100644 --- a/dlls/qedit/samplegrabber.c +++ b/dlls/qedit/samplegrabber.c @@ -511,12 +511,26 @@ static HRESULT sample_grabber_sink_get_media_type(struct strmbase_pin *iface, unsigned int index, AM_MEDIA_TYPE *mt) { SG_Impl *filter = impl_from_sink_pin(iface); + IEnumMediaTypes *enummt; + AM_MEDIA_TYPE *pmt; + HRESULT hr; + + if (!filter->source.pin.peer) + return VFW_E_NOT_CONNECTED; + + if (FAILED(hr = IPin_EnumMediaTypes(filter->source.pin.peer, &enummt))) + return hr;
- if (!index) + if ((!index || IEnumMediaTypes_Skip(enummt, index) == S_OK) + && IEnumMediaTypes_Next(enummt, 1, &pmt, NULL) == S_OK) { - CopyMediaType(mt, &filter->filter_mt); + CopyMediaType(mt, pmt); + DeleteMediaType(pmt); + IEnumMediaTypes_Release(enummt); return S_OK; } + + IEnumMediaTypes_Release(enummt); return VFW_S_NO_MORE_ITEMS; }
diff --git a/dlls/qedit/tests/samplegrabber.c b/dlls/qedit/tests/samplegrabber.c index 5436700d17d..8e68e3efae1 100644 --- a/dlls/qedit/tests/samplegrabber.c +++ b/dlls/qedit/tests/samplegrabber.c @@ -482,8 +482,7 @@ static void test_media_types(void) IBaseFilter_FindPin(filter, L"Out", &source);
hr = IPin_EnumMediaTypes(sink, &enummt); - todo_wine ok(hr == VFW_E_NOT_CONNECTED, "Got hr %#x.\n", hr); - if (hr == S_OK) IEnumMediaTypes_Release(enummt); + ok(hr == VFW_E_NOT_CONNECTED, "Got hr %#x.\n", hr);
hr = IPin_EnumMediaTypes(source, &enummt); ok(hr == VFW_E_NOT_CONNECTED, "Got hr %#x.\n", hr); @@ -497,8 +496,7 @@ static void test_media_types(void) ok(hr == S_OK, "Got hr %#x.\n", hr);
hr = IPin_EnumMediaTypes(sink, &enummt); - todo_wine ok(hr == VFW_E_NOT_CONNECTED, "Got hr %#x.\n", hr); - if (hr == S_OK) IEnumMediaTypes_Release(enummt); + ok(hr == VFW_E_NOT_CONNECTED, "Got hr %#x.\n", hr);
hr = IPin_EnumMediaTypes(source, &enummt); ok(hr == VFW_E_NOT_CONNECTED, "Got hr %#x.\n", hr); @@ -824,8 +822,7 @@ static void test_connect_pin(void) ok(compare_media_types(&mt, &req_mt), "Media types didn't match.\n");
hr = IPin_EnumMediaTypes(sink, &enummt); - todo_wine ok(hr == VFW_E_NOT_CONNECTED, "Got hr %#x.\n", hr); - if (hr == S_OK) IEnumMediaTypes_Release(enummt); + ok(hr == VFW_E_NOT_CONNECTED, "Got hr %#x.\n", hr); hr = IPin_EnumMediaTypes(source, &enummt); ok(hr == S_OK, "Got hr %#x.\n", hr); hr = IEnumMediaTypes_Next(enummt, 1, &pmt, NULL); @@ -1000,6 +997,14 @@ static void test_connect_pin(void) ok(hr == S_OK, "Got hr %#x.\n", hr); ok(compare_media_types(&testsink.sink.pin.mt, &req_mt), "Media types didn't match.\n"); ok(compare_media_types(&testsource.source.pin.mt, &testsink.sink.pin.mt), "Media types didn't match.\n"); + + hr = IPin_EnumMediaTypes(sink, &enummt); + ok(hr == S_OK, "Got hr %#x.\n", hr); + hr = IEnumMediaTypes_Next(enummt, 1, &pmt, NULL); + ok(hr == S_OK, "Got hr %#x.\n", hr); + ok(compare_media_types(pmt, testsink.sink_mt), "Media types didn't match.\n"); + IEnumMediaTypes_Release(enummt); + IFilterGraph2_Disconnect(graph, source); IFilterGraph2_Disconnect(graph, &testsink.sink.pin.IPin_iface);