Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/quartz/tests/filesource.c | 306 ++++++++++++++++++++++++++++++++- 1 file changed, 305 insertions(+), 1 deletion(-)
diff --git a/dlls/quartz/tests/filesource.c b/dlls/quartz/tests/filesource.c index df0db1b3b53..3c8626b7399 100644 --- a/dlls/quartz/tests/filesource.c +++ b/dlls/quartz/tests/filesource.c @@ -21,6 +21,7 @@
#define COBJMACROS #include "dshow.h" +#include "wine/strmbase.h" #include "wine/test.h"
static IBaseFilter *create_file_source(void) @@ -32,6 +33,12 @@ static IBaseFilter *create_file_source(void) return filter; }
+static BOOL compare_media_types(const AM_MEDIA_TYPE *a, const AM_MEDIA_TYPE *b) +{ + return !memcmp(a, b, offsetof(AM_MEDIA_TYPE, pbFormat)) + && !memcmp(a->pbFormat, b->pbFormat, a->cbFormat); +} + static WCHAR *load_resource(const WCHAR *name) { static WCHAR pathW[MAX_PATH]; @@ -380,8 +387,9 @@ static void test_file_source_filter(void) mt.bTemporalCompression = TRUE; mt.lSampleSize = 123; mt.formattype = FORMAT_VideoInfo; + mt.subtype = MEDIASUBTYPE_RGB32; hr = IPin_QueryAccept(pin, &mt); - ok(hr == S_OK, "Got hr %#x.\n", hr); + todo_wine ok(hr == S_OK, "Got hr %#x.\n", hr);
mt.majortype = MEDIATYPE_Video; hr = IPin_QueryAccept(pin, &mt); @@ -1197,6 +1205,301 @@ static void test_enum_media_types(void) ok(ret, "Failed to delete file, error %u.\n", GetLastError()); }
+struct testsink +{ + struct strmbase_filter filter; + struct strmbase_sink pin; + IAsyncReader *reader; + BOOL reject_avi; + const AM_MEDIA_TYPE *mt; +}; + +static inline struct testsink *impl_sink_from_strmbase_filter(struct strmbase_filter *iface) +{ + return CONTAINING_RECORD(iface, struct testsink, filter); +} + +static struct strmbase_pin *testsink_get_pin(struct strmbase_filter *iface, unsigned int index) +{ + struct testsink *filter = impl_sink_from_strmbase_filter(iface); + if (!index) + return &filter->pin.pin; + return NULL; +} + +static void testsink_destroy(struct strmbase_filter *iface) +{ + struct testsink *filter = impl_sink_from_strmbase_filter(iface); + strmbase_sink_cleanup(&filter->pin); + strmbase_filter_cleanup(&filter->filter); +} + +static const struct strmbase_filter_ops testsink_ops = +{ + .filter_get_pin = testsink_get_pin, + .filter_destroy = testsink_destroy, +}; + +static HRESULT testsink_query_accept(struct strmbase_pin *iface, const AM_MEDIA_TYPE *mt) +{ + return S_OK; +} + +static HRESULT testsink_get_media_type(struct strmbase_pin *iface, unsigned int index, AM_MEDIA_TYPE *mt) +{ + struct testsink *filter = impl_sink_from_strmbase_filter(iface->filter); + if (!index && filter->mt) + { + CopyMediaType(mt, filter->mt); + return S_OK; + } + return VFW_S_NO_MORE_ITEMS; +} + +static HRESULT testsink_connect(struct strmbase_sink *iface, IPin *peer, const AM_MEDIA_TYPE *mt) +{ + struct testsink *filter = impl_sink_from_strmbase_filter(iface->pin.filter); + if (filter->reject_avi && IsEqualGUID(&mt->subtype, &MEDIASUBTYPE_Avi)) + return VFW_E_TYPE_NOT_ACCEPTED; + IPin_QueryInterface(peer, &IID_IAsyncReader, (void **)&filter->reader); + return S_OK; +} + +static void testsink_disconnect(struct strmbase_sink *iface) +{ + struct testsink *filter = impl_sink_from_strmbase_filter(iface->pin.filter); + IAsyncReader_Release(filter->reader); + filter->reader = NULL; +} + +static const struct strmbase_sink_ops testsink_pin_ops = +{ + .base.pin_query_accept = testsink_query_accept, + .base.pin_get_media_type = testsink_get_media_type, + .sink_connect = testsink_connect, + .sink_disconnect = testsink_disconnect, +}; + +static void testsink_init(struct testsink *filter) +{ + static const GUID clsid = {0xabacab}; + memset(filter, 0, sizeof(*filter)); + strmbase_filter_init(&filter->filter, NULL, &clsid, &testsink_ops); + strmbase_sink_init(&filter->pin, &filter->filter, L"", &testsink_pin_ops, NULL); +} + +static void test_connect_pin(void) +{ + AM_MEDIA_TYPE req_mt = + { + .majortype = MEDIATYPE_Stream, + .subtype = MEDIASUBTYPE_Avi, + .formattype = FORMAT_None, + .lSampleSize = 888, + }; + const WCHAR *filename = load_resource(L"test.avi"); + IBaseFilter *filter = create_file_source(); + AM_MEDIA_TYPE mt, *source_mt; + struct testsink testsink; + IEnumMediaTypes *enummt; + IFilterGraph2 *graph; + IPin *source, *peer; + BYTE my_format = 1; + HRESULT hr; + ULONG ref; + BOOL ret; + + testsink_init(&testsink); + CoCreateInstance(&CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, + &IID_IFilterGraph2, (void **)&graph); + IFilterGraph2_AddFilter(graph, &testsink.filter.IBaseFilter_iface, L"sink"); + IFilterGraph2_AddFilter(graph, filter, "file source"); + load_file(filter, filename); + IBaseFilter_FindPin(filter, L"Output", &source); + + IPin_EnumMediaTypes(source, &enummt); + IEnumMediaTypes_Next(enummt, 1, &source_mt, NULL); + IEnumMediaTypes_Release(enummt); + + peer = (IPin *)0xdeadbeef; + hr = IPin_ConnectedTo(source, &peer); + ok(hr == VFW_E_NOT_CONNECTED, "Got hr %#x.\n", hr); + ok(!peer, "Got peer %p.\n", peer); + + hr = IPin_ConnectionMediaType(source, &mt); + ok(hr == VFW_E_NOT_CONNECTED, "Got hr %#x.\n", hr); + + /* Test exact connection. */ + + hr = IFilterGraph2_ConnectDirect(graph, source, &testsink.pin.pin.IPin_iface, &req_mt); + ok(hr == S_OK, "Got hr %#x.\n", hr); + + hr = IPin_ConnectedTo(source, &peer); + ok(hr == S_OK, "Got hr %#x.\n", hr); + ok(peer == &testsink.pin.pin.IPin_iface, "Got peer %p.\n", peer); + IPin_Release(peer); + + hr = IPin_ConnectionMediaType(source, &mt); + ok(hr == S_OK, "Got hr %#x.\n", hr); + ok(compare_media_types(&mt, &req_mt), "Media types didn't match.\n"); + ok(compare_media_types(&testsink.pin.pin.mt, &req_mt), "Media types didn't match.\n"); + + hr = IFilterGraph2_Disconnect(graph, source); + ok(hr == S_OK, "Got hr %#x.\n", hr); + hr = IFilterGraph2_Disconnect(graph, source); + ok(hr == S_FALSE, "Got hr %#x.\n", hr); + ok(testsink.pin.pin.peer == source, "Got peer %p.\n", testsink.pin.pin.peer); + IFilterGraph2_Disconnect(graph, &testsink.pin.pin.IPin_iface); + + req_mt.pbFormat = &my_format; + req_mt.cbFormat = sizeof(my_format); + hr = IFilterGraph2_ConnectDirect(graph, source, &testsink.pin.pin.IPin_iface, &req_mt); + ok(hr == S_OK, "Got hr %#x.\n", hr); + ok(compare_media_types(&testsink.pin.pin.mt, &req_mt), "Media types didn't match.\n"); + IFilterGraph2_Disconnect(graph, source); + IFilterGraph2_Disconnect(graph, &testsink.pin.pin.IPin_iface); + req_mt.pbFormat = NULL; + req_mt.cbFormat = 0; + + 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); + } + req_mt.majortype = MEDIATYPE_Stream; + + req_mt.subtype = MEDIASUBTYPE_RGB8; + hr = IFilterGraph2_ConnectDirect(graph, source, &testsink.pin.pin.IPin_iface, &req_mt); + ok(hr == S_OK, "Got hr %#x.\n", hr); + ok(compare_media_types(&testsink.pin.pin.mt, &req_mt), "Media types didn't match.\n"); + IFilterGraph2_Disconnect(graph, source); + 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); + } + req_mt.subtype = MEDIASUBTYPE_Avi; + + /* Test connection with wildcards. */ + + hr = IFilterGraph2_ConnectDirect(graph, source, &testsink.pin.pin.IPin_iface, NULL); + ok(hr == S_OK, "Got hr %#x.\n", hr); + ok(compare_media_types(&testsink.pin.pin.mt, source_mt), "Media types didn't match.\n"); + IFilterGraph2_Disconnect(graph, source); + IFilterGraph2_Disconnect(graph, &testsink.pin.pin.IPin_iface); + + req_mt.formattype = GUID_NULL; + hr = IFilterGraph2_ConnectDirect(graph, source, &testsink.pin.pin.IPin_iface, &req_mt); + ok(hr == S_OK, "Got hr %#x.\n", hr); + todo_wine ok(compare_media_types(&testsink.pin.pin.mt, source_mt), "Media types didn't match.\n"); + IFilterGraph2_Disconnect(graph, source); + IFilterGraph2_Disconnect(graph, &testsink.pin.pin.IPin_iface); + + req_mt.formattype = FORMAT_None; + req_mt.majortype = GUID_NULL; + hr = IFilterGraph2_ConnectDirect(graph, source, &testsink.pin.pin.IPin_iface, &req_mt); + 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); + } + + req_mt.formattype = GUID_NULL; + hr = IFilterGraph2_ConnectDirect(graph, source, &testsink.pin.pin.IPin_iface, &req_mt); + ok(hr == S_OK, "Got hr %#x.\n", hr); + ok(compare_media_types(&testsink.pin.pin.mt, source_mt), "Media types didn't match.\n"); + IFilterGraph2_Disconnect(graph, source); + IFilterGraph2_Disconnect(graph, &testsink.pin.pin.IPin_iface); + + req_mt.subtype = MEDIASUBTYPE_RGB8; + hr = IFilterGraph2_ConnectDirect(graph, source, &testsink.pin.pin.IPin_iface, &req_mt); + 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); + } + + req_mt.subtype = GUID_NULL; + hr = IFilterGraph2_ConnectDirect(graph, source, &testsink.pin.pin.IPin_iface, &req_mt); + ok(hr == S_OK, "Got hr %#x.\n", hr); + ok(compare_media_types(&testsink.pin.pin.mt, source_mt), "Media types didn't match.\n"); + IFilterGraph2_Disconnect(graph, source); + IFilterGraph2_Disconnect(graph, &testsink.pin.pin.IPin_iface); + + req_mt.majortype = MEDIATYPE_Stream; + req_mt.subtype = MEDIASUBTYPE_RGB8; + hr = IFilterGraph2_ConnectDirect(graph, source, &testsink.pin.pin.IPin_iface, &req_mt); + 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); + } + + req_mt.subtype = GUID_NULL; + hr = IFilterGraph2_ConnectDirect(graph, source, &testsink.pin.pin.IPin_iface, &req_mt); + ok(hr == S_OK, "Got hr %#x.\n", hr); + ok(compare_media_types(&testsink.pin.pin.mt, source_mt), "Media types didn't match.\n"); + IFilterGraph2_Disconnect(graph, source); + IFilterGraph2_Disconnect(graph, &testsink.pin.pin.IPin_iface); + + req_mt.majortype = MEDIATYPE_Video; + hr = IFilterGraph2_ConnectDirect(graph, source, &testsink.pin.pin.IPin_iface, &req_mt); + ok(hr == VFW_E_NO_ACCEPTABLE_TYPES, "Got hr %#x.\n", hr); + + /* The second type (i.e. whose subtype is GUID_NULL) is not tried. This is + * 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); + } + + /* But any types we expose are tried. */ + testsink.mt = &mt; + memset(&mt, 0, sizeof(mt)); + mt.majortype = MEDIATYPE_Video; + 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); + } + + 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"); + IFilterGraph2_Disconnect(graph, source); + IFilterGraph2_Disconnect(graph, &testsink.pin.pin.IPin_iface); + + CoTaskMemFree(source_mt); + IPin_Release(source); + ref = IFilterGraph2_Release(graph); + ok(!ref, "Got outstanding refcount %d.\n", ref); + ref = IBaseFilter_Release(filter); + ok(!ref, "Got outstanding refcount %d.\n", ref); + ref = IBaseFilter_Release(&testsink.filter.IBaseFilter_iface); + ok(!ref, "Got outstanding refcount %d.\n", ref); + ret = DeleteFileW(filename); + ok(ret, "Failed to delete file, error %u.\n", GetLastError()); +} + START_TEST(filesource) { CoInitialize(NULL); @@ -1210,6 +1513,7 @@ START_TEST(filesource) test_file_source_filter(); test_async_reader(); test_enum_media_types(); + test_connect_pin();
CoUninitialize(); }