From 696c4f8f938555676b4d45d1c5c2566fd15e202c Mon Sep 17 00:00:00 2001 From: Zebediah Figura Date: Sun, 29 Sep 2019 19:03:25 -0500 Subject: [PATCH] quartz/tests: Add some tests for video renderer pin connection. Signed-off-by: Zebediah Figura Signed-off-by: Alexandre Julliard --- dlls/quartz/tests/Makefile.in | 2 +- dlls/quartz/tests/videorenderer.c | 235 ++++++++++++++++++++++++++++++ 2 files changed, 236 insertions(+), 1 deletion(-) diff --git a/dlls/quartz/tests/Makefile.in b/dlls/quartz/tests/Makefile.in index da474e95309..fe1a45e8ec5 100644 --- a/dlls/quartz/tests/Makefile.in +++ b/dlls/quartz/tests/Makefile.in @@ -1,5 +1,5 @@ TESTDLL = quartz.dll -IMPORTS = advapi32 msvfw32 ole32 oleaut32 strmiids user32 uuid +IMPORTS = strmbase advapi32 msvfw32 ole32 oleaut32 strmiids user32 uuid C_SRCS = \ acmwrapper.c \ diff --git a/dlls/quartz/tests/videorenderer.c b/dlls/quartz/tests/videorenderer.c index 7d3b2776177..24cf0cc8280 100644 --- a/dlls/quartz/tests/videorenderer.c +++ b/dlls/quartz/tests/videorenderer.c @@ -20,6 +20,7 @@ #define COBJMACROS #include "dshow.h" +#include "wine/strmbase.h" #include "wine/test.h" static const WCHAR sink_id[] = {'I','n',0}; @@ -33,6 +34,21 @@ static IBaseFilter *create_video_renderer(void) return filter; } +static inline 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 IFilterGraph2 *create_graph(void) +{ + IFilterGraph2 *ret; + HRESULT hr; + hr = CoCreateInstance(&CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, &IID_IFilterGraph2, (void **)&ret); + ok(hr == S_OK, "Failed to create FilterGraph: %#x\n", hr); + return ret; +} + static ULONG get_refcount(void *iface) { IUnknown *unknown = iface; @@ -472,6 +488,224 @@ static void test_enum_media_types(void) ok(!ref, "Got outstanding refcount %d.\n", ref); } +struct testfilter +{ + struct strmbase_filter filter; + struct strmbase_source source; +}; + +static const IBaseFilterVtbl testfilter_vtbl = +{ + BaseFilterImpl_QueryInterface, + BaseFilterImpl_AddRef, + BaseFilterImpl_Release, + BaseFilterImpl_GetClassID, + BaseFilterImpl_Stop, + BaseFilterImpl_Pause, + BaseFilterImpl_Run, + BaseFilterImpl_GetState, + BaseFilterImpl_SetSyncSource, + BaseFilterImpl_GetSyncSource, + BaseFilterImpl_EnumPins, + BaseFilterImpl_FindPin, + BaseFilterImpl_QueryFilterInfo, + BaseFilterImpl_JoinFilterGraph, + BaseFilterImpl_QueryVendorInfo, +}; + +static inline struct testfilter *impl_from_BaseFilter(struct strmbase_filter *iface) +{ + return CONTAINING_RECORD(iface, struct testfilter, filter); +} + +static IPin *testfilter_get_pin(struct strmbase_filter *iface, unsigned int index) +{ + struct testfilter *filter = impl_from_BaseFilter(iface); + if (!index) + return &filter->source.pin.IPin_iface; + return NULL; +} + +static void testfilter_destroy(struct strmbase_filter *iface) +{ + struct testfilter *filter = impl_from_BaseFilter(iface); + strmbase_source_cleanup(&filter->source); + strmbase_filter_cleanup(&filter->filter); +} + +static const struct strmbase_filter_ops testfilter_ops = +{ + .filter_get_pin = testfilter_get_pin, + .filter_destroy = testfilter_destroy, +}; + +static const IPinVtbl testsource_vtbl = +{ + BasePinImpl_QueryInterface, + BasePinImpl_AddRef, + BasePinImpl_Release, + BaseOutputPinImpl_Connect, + BaseOutputPinImpl_ReceiveConnection, + BasePinImpl_Disconnect, + BasePinImpl_ConnectedTo, + BasePinImpl_ConnectionMediaType, + BasePinImpl_QueryPinInfo, + BasePinImpl_QueryDirection, + BasePinImpl_QueryId, + BasePinImpl_QueryAccept, + BasePinImpl_EnumMediaTypes, + BasePinImpl_QueryInternalConnections, + BaseOutputPinImpl_EndOfStream, + BaseOutputPinImpl_BeginFlush, + BaseOutputPinImpl_EndFlush, + BasePinImpl_NewSegment, +}; + +static HRESULT testsource_query_accept(struct strmbase_pin *iface, const AM_MEDIA_TYPE *mt) +{ + return S_OK; +} + +static HRESULT WINAPI testsource_AttemptConnection(struct strmbase_source *iface, + IPin *peer, const AM_MEDIA_TYPE *mt) +{ + HRESULT hr; + + iface->pin.peer = peer; + IPin_AddRef(peer); + CopyMediaType(&iface->pin.mtCurrent, mt); + + if (FAILED(hr = IPin_ReceiveConnection(peer, &iface->pin.IPin_iface, mt))) + { + ok(hr == VFW_E_TYPE_NOT_ACCEPTED, "Got hr %#x.\n", hr); + IPin_Release(peer); + iface->pin.peer = NULL; + FreeMediaType(&iface->pin.mtCurrent); + } + + return hr; +} + +static const struct strmbase_source_ops testsource_ops = +{ + .base.pin_query_accept = testsource_query_accept, + .base.pin_get_media_type = strmbase_pin_get_media_type, + .pfnAttemptConnection = testsource_AttemptConnection, +}; + +static void testfilter_init(struct testfilter *filter) +{ + static const GUID clsid = {0xabacab}; + strmbase_filter_init(&filter->filter, &testfilter_vtbl, NULL, &clsid, &testfilter_ops); + strmbase_source_init(&filter->source, &testsource_vtbl, &filter->filter, L"", &testsource_ops); +} + +static void test_connect_pin(void) +{ + VIDEOINFOHEADER vih = + { + .bmiHeader.biSize = sizeof(BITMAPINFOHEADER), + .bmiHeader.biBitCount = 16, + .bmiHeader.biWidth = 32, + .bmiHeader.biHeight = 16, + .bmiHeader.biPlanes = 1, + .bmiHeader.biCompression = BI_RGB, + }; + AM_MEDIA_TYPE req_mt = + { + .majortype = MEDIATYPE_Video, + .formattype = FORMAT_VideoInfo, + .cbFormat = sizeof(vih), + .pbFormat = (BYTE *)&vih, + }; + IBaseFilter *filter = create_video_renderer(); + IFilterGraph2 *graph = create_graph(); + struct testfilter source; + AM_MEDIA_TYPE mt; + IPin *pin, *peer; + unsigned int i; + HRESULT hr; + ULONG ref; + + static const GUID *subtype_tests[] = + { + &MEDIASUBTYPE_RGB8, + &MEDIASUBTYPE_RGB565, + &MEDIASUBTYPE_RGB24, + &MEDIASUBTYPE_RGB32, + }; + + testfilter_init(&source); + + IFilterGraph2_AddFilter(graph, &source.filter.IBaseFilter_iface, NULL); + IFilterGraph2_AddFilter(graph, filter, NULL); + + IBaseFilter_FindPin(filter, sink_id, &pin); + + for (i = 0; i < ARRAY_SIZE(subtype_tests); ++i) + { + req_mt.subtype = *subtype_tests[i]; + hr = IFilterGraph2_ConnectDirect(graph, &source.source.pin.IPin_iface, pin, &req_mt); + ok(hr == S_OK, "Got hr %#x for subtype %s.\n", hr, wine_dbgstr_guid(subtype_tests[i])); + + hr = IFilterGraph2_Disconnect(graph, &source.source.pin.IPin_iface); + ok(hr == S_OK, "Got hr %#x.\n", hr); + hr = IFilterGraph2_Disconnect(graph, pin); + ok(hr == S_OK, "Got hr %#x.\n", hr); + } + + req_mt.formattype = FORMAT_None; + hr = IFilterGraph2_ConnectDirect(graph, &source.source.pin.IPin_iface, pin, &req_mt); + ok(hr == VFW_E_TYPE_NOT_ACCEPTED, "Got hr %#x.\n", hr); + req_mt.formattype = GUID_NULL; + hr = IFilterGraph2_ConnectDirect(graph, &source.source.pin.IPin_iface, pin, &req_mt); + ok(hr == VFW_E_TYPE_NOT_ACCEPTED, "Got hr %#x.\n", hr); + req_mt.formattype = FORMAT_VideoInfo; + + peer = (IPin *)0xdeadbeef; + hr = IPin_ConnectedTo(pin, &peer); + ok(hr == VFW_E_NOT_CONNECTED, "Got hr %#x.\n", hr); + ok(!peer, "Got peer %p.\n", peer); + + hr = IPin_ConnectionMediaType(pin, &mt); + ok(hr == VFW_E_NOT_CONNECTED, "Got hr %#x.\n", hr); + + hr = IFilterGraph2_ConnectDirect(graph, &source.source.pin.IPin_iface, pin, &req_mt); + ok(hr == S_OK, "Got hr %#x.\n", hr); + + hr = IPin_ConnectedTo(pin, &peer); + ok(hr == S_OK, "Got hr %#x.\n", hr); + ok(peer == &source.source.pin.IPin_iface, "Got peer %p.\n", peer); + IPin_Release(peer); + + hr = IPin_ConnectionMediaType(pin, &mt); + ok(hr == S_OK, "Got hr %#x.\n", hr); + ok(compare_media_types(&mt, &req_mt), "Media types didn't match.\n"); + + hr = IFilterGraph2_Disconnect(graph, pin); + ok(hr == S_OK, "Got hr %#x.\n", hr); + hr = IFilterGraph2_Disconnect(graph, pin); + ok(hr == S_FALSE, "Got hr %#x.\n", hr); + ok(source.source.pin.peer == pin, "Got peer %p.\n", peer); + IFilterGraph2_Disconnect(graph, &source.source.pin.IPin_iface); + + peer = (IPin *)0xdeadbeef; + hr = IPin_ConnectedTo(pin, &peer); + ok(hr == VFW_E_NOT_CONNECTED, "Got hr %#x.\n", hr); + ok(!peer, "Got peer %p.\n", peer); + + hr = IPin_ConnectionMediaType(pin, &mt); + ok(hr == VFW_E_NOT_CONNECTED, "Got hr %#x.\n", hr); + + IPin_Release(pin); + 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(&source.filter.IBaseFilter_iface); + ok(!ref, "Got outstanding refcount %d.\n", ref); +} + static void test_pin(IPin *pin) { IMemInputPin *mpin = NULL; @@ -597,6 +831,7 @@ START_TEST(videorenderer) test_media_types(); test_enum_media_types(); test_unconnected_filter_state(); + test_connect_pin(); test_basefilter(); CoUninitialize();