Fixes using binaries compiled with Wine's strmbase with Windows 8 and higher.
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/strmbase/filter.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/dlls/strmbase/filter.c b/dlls/strmbase/filter.c index b52a99d25b2..2de0a78f7a0 100644 --- a/dlls/strmbase/filter.c +++ b/dlls/strmbase/filter.c @@ -302,7 +302,8 @@ void strmbase_filter_init(struct strmbase_filter *filter, const IBaseFilterVtbl filter->refcount = 1;
InitializeCriticalSection(&filter->csFilter); - filter->csFilter.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": strmbase_filter.csFilter"); + if (filter->csFilter.DebugInfo != (RTL_CRITICAL_SECTION_DEBUG *)-1) + filter->csFilter.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": strmbase_filter.csFilter"); filter->clsid = *clsid; filter->pin_version = 1; filter->pFuncsTable = func_table; @@ -314,6 +315,5 @@ void strmbase_filter_cleanup(struct strmbase_filter *This) IReferenceClock_Release(This->pClock);
This->IBaseFilter_iface.lpVtbl = NULL; - This->csFilter.DebugInfo->Spare[0] = 0; DeleteCriticalSection(&This->csFilter); }
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- 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();
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=57121
Your paranoid android.
=== debian10 (build log) ===
error: patch failed: dlls/quartz/tests/videorenderer.c:597 Task: Patch failed to apply
=== debian10 (build log) ===
error: patch failed: dlls/quartz/tests/videorenderer.c:597 Task: Patch failed to apply
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/quartz/tests/videorenderer.c | 50 ++++++++++++++++++++++++++++++- 1 file changed, 49 insertions(+), 1 deletion(-)
diff --git a/dlls/quartz/tests/videorenderer.c b/dlls/quartz/tests/videorenderer.c index 24cf0cc8280..bce42c4b8b9 100644 --- a/dlls/quartz/tests/videorenderer.c +++ b/dlls/quartz/tests/videorenderer.c @@ -600,6 +600,49 @@ static void testfilter_init(struct testfilter *filter) strmbase_source_init(&filter->source, &testsource_vtbl, &filter->filter, L"", &testsource_ops); }
+static void test_allocator(IMemInputPin *input) +{ + IMemAllocator *req_allocator, *ret_allocator; + ALLOCATOR_PROPERTIES props; + HRESULT hr; + + hr = IMemInputPin_GetAllocatorRequirements(input, &props); + ok(hr == E_NOTIMPL, "Got hr %#x.\n", hr); + + hr = IMemInputPin_GetAllocator(input, &ret_allocator); + todo_wine ok(hr == S_OK, "Got hr %#x.\n", hr); + + if (hr == S_OK) + { + hr = IMemAllocator_GetProperties(ret_allocator, &props); + ok(hr == S_OK, "Got hr %#x.\n", hr); + ok(!props.cBuffers, "Got %d buffers.\n", props.cBuffers); + ok(!props.cbBuffer, "Got size %d.\n", props.cbBuffer); + ok(!props.cbAlign, "Got alignment %d.\n", props.cbAlign); + ok(!props.cbPrefix, "Got prefix %d.\n", props.cbPrefix); + + hr = IMemInputPin_NotifyAllocator(input, ret_allocator, TRUE); + ok(hr == S_OK, "Got hr %#x.\n", hr); + IMemAllocator_Release(ret_allocator); + } + + hr = IMemInputPin_NotifyAllocator(input, NULL, TRUE); + ok(hr == E_POINTER, "Got hr %#x.\n", hr); + + CoCreateInstance(&CLSID_MemoryAllocator, NULL, CLSCTX_INPROC_SERVER, + &IID_IMemAllocator, (void **)&req_allocator); + + hr = IMemInputPin_NotifyAllocator(input, req_allocator, TRUE); + ok(hr == S_OK, "Got hr %#x.\n", hr); + + hr = IMemInputPin_GetAllocator(input, &ret_allocator); + ok(hr == S_OK, "Got hr %#x.\n", hr); + ok(ret_allocator == req_allocator, "Allocators didn't match.\n"); + + IMemAllocator_Release(req_allocator); + IMemAllocator_Release(ret_allocator); +} + static void test_connect_pin(void) { VIDEOINFOHEADER vih = @@ -621,6 +664,7 @@ static void test_connect_pin(void) IBaseFilter *filter = create_video_renderer(); IFilterGraph2 *graph = create_graph(); struct testfilter source; + IMemInputPin *input; AM_MEDIA_TYPE mt; IPin *pin, *peer; unsigned int i; @@ -682,6 +726,10 @@ static void test_connect_pin(void) ok(hr == S_OK, "Got hr %#x.\n", hr); ok(compare_media_types(&mt, &req_mt), "Media types didn't match.\n");
+ IPin_QueryInterface(pin, &IID_IMemInputPin, (void **)&input); + + test_allocator(input); + hr = IFilterGraph2_Disconnect(graph, pin); ok(hr == S_OK, "Got hr %#x.\n", hr); hr = IFilterGraph2_Disconnect(graph, pin); @@ -697,6 +745,7 @@ static void test_connect_pin(void) hr = IPin_ConnectionMediaType(pin, &mt); ok(hr == VFW_E_NOT_CONNECTED, "Got hr %#x.\n", hr);
+ IMemInputPin_Release(input); IPin_Release(pin); ref = IFilterGraph2_Release(graph); ok(!ref, "Got outstanding refcount %d.\n", ref); @@ -716,7 +765,6 @@ static void test_pin(IPin *pin) if (mpin) { ok(IMemInputPin_ReceiveCanBlock(mpin) == S_OK, "Receive can't block for pin!\n"); - ok(IMemInputPin_NotifyAllocator(mpin, NULL, 0) == E_POINTER, "NotifyAllocator likes a NULL pointer argument\n"); IMemInputPin_Release(mpin); } /* TODO */
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=57122
Your paranoid android.
=== debian10 (build log) ===
error: patch failed: dlls/quartz/tests/videorenderer.c:597 error: patch failed: dlls/quartz/tests/videorenderer.c:600 Task: Patch failed to apply
=== debian10 (build log) ===
error: patch failed: dlls/quartz/tests/videorenderer.c:597 error: patch failed: dlls/quartz/tests/videorenderer.c:600 Task: Patch failed to apply
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- v2: fix incorrect heap allocation size
dlls/quartz/tests/videorenderer.c | 283 ++++++++++++++++++++++++------ 1 file changed, 227 insertions(+), 56 deletions(-)
diff --git a/dlls/quartz/tests/videorenderer.c b/dlls/quartz/tests/videorenderer.c index bce42c4b8b9..4e948a9120a 100644 --- a/dlls/quartz/tests/videorenderer.c +++ b/dlls/quartz/tests/videorenderer.c @@ -20,6 +20,7 @@
#define COBJMACROS #include "dshow.h" +#include "wine/heap.h" #include "wine/strmbase.h" #include "wine/test.h"
@@ -643,6 +644,212 @@ static void test_allocator(IMemInputPin *input) IMemAllocator_Release(ret_allocator); }
+struct frame_thread_params +{ + IMemInputPin *sink; + IMediaSample *sample; +}; + +static DWORD WINAPI frame_thread(void *arg) +{ + struct frame_thread_params *params = arg; + HRESULT hr; + + if (winetest_debug > 1) trace("%04x: Sending frame.\n", GetCurrentThreadId()); + hr = IMemInputPin_Receive(params->sink, params->sample); + if (winetest_debug > 1) trace("%04x: Returned %#x.\n", GetCurrentThreadId(), hr); + IMediaSample_Release(params->sample); + heap_free(params); + return hr; +} + +static HANDLE send_frame(IMemInputPin *sink) +{ + struct frame_thread_params *params = heap_alloc(sizeof(*params)); + REFERENCE_TIME start_time, end_time; + IMemAllocator *allocator; + IMediaSample *sample; + HANDLE thread; + HRESULT hr; + BYTE *data; + + hr = IMemInputPin_GetAllocator(sink, &allocator); + ok(hr == S_OK, "Got hr %#x.\n", hr); + + hr = IMemAllocator_GetBuffer(allocator, &sample, NULL, NULL, 0); + ok(hr == S_OK, "Got hr %#x.\n", hr); + + hr = IMediaSample_GetPointer(sample, &data); + ok(hr == S_OK, "Got hr %#x.\n", hr); + memset(data, 0x55, 32 * 16 * 2); + + hr = IMediaSample_SetActualDataLength(sample, 32 * 16 * 2); + ok(hr == S_OK, "Got hr %#x.\n", hr); + + start_time = 0; + end_time = start_time + 10000000; + hr = IMediaSample_SetTime(sample, &start_time, &end_time); + ok(hr == S_OK, "Got hr %#x.\n", hr); + + params->sink = sink; + params->sample = sample; + thread = CreateThread(NULL, 0, frame_thread, params, 0, NULL); + + IMemAllocator_Release(allocator); + return thread; +} + +static HRESULT join_thread_(int line, HANDLE thread) +{ + DWORD ret; + ok_(__FILE__, line)(!WaitForSingleObject(thread, 1000), "Wait failed.\n"); + GetExitCodeThread(thread, &ret); + CloseHandle(thread); + return ret; +} +#define join_thread(a) join_thread_(__LINE__, a) + +static void test_filter_state(IMemInputPin *input, IFilterGraph2 *graph) +{ + IMemAllocator *allocator; + IMediaControl *control; + IMediaSample *sample; + OAFilterState state; + HANDLE thread; + HRESULT hr; + + IFilterGraph2_QueryInterface(graph, &IID_IMediaControl, (void **)&control); + + thread = send_frame(input); + hr = join_thread(thread); + todo_wine ok(hr == E_FAIL, "Got hr %#x.\n", hr); + + /* The renderer is not fully paused until it receives a sample. The thread + * sending the sample blocks in IMemInputPin_Receive() until the filter is + * stopped or run. */ + + hr = IMediaControl_Pause(control); + ok(hr == S_FALSE, "Got hr %#x.\n", hr); + + hr = IMediaControl_GetState(control, 0, &state); + todo_wine ok(hr == VFW_S_STATE_INTERMEDIATE, "Got hr %#x.\n", hr); + + thread = send_frame(input); + + hr = IMediaControl_GetState(control, 1000, &state); + ok(hr == S_OK, "Got hr %#x.\n", hr); + + todo_wine ok(WaitForSingleObject(thread, 100) == WAIT_TIMEOUT, "Thread should block in Receive().\n"); + + hr = IMediaControl_Stop(control); + ok(hr == S_OK, "Got hr %#x.\n", hr); + + hr = join_thread(thread); + ok(hr == S_OK, "Got hr %#x.\n", hr); + + /* The sink will decommit our allocator for us when stopping, and recommit + * it when pausing. */ + hr = IMemInputPin_GetAllocator(input, &allocator); + ok(hr == S_OK, "Got hr %#x.\n", hr); + hr = IMemAllocator_GetBuffer(allocator, &sample, NULL, NULL, 0); + todo_wine ok(hr == VFW_E_NOT_COMMITTED, "Got hr %#x.\n", hr); + if (hr == S_OK) IMediaSample_Release(sample); + + hr = IMemAllocator_Commit(allocator); + ok(hr == S_OK, "Got hr %#x.\n", hr); + thread = send_frame(input); + hr = join_thread(thread); + todo_wine ok(hr == E_FAIL, "Got hr %#x.\n", hr); + + hr = IMediaControl_Pause(control); + ok(hr == S_FALSE, "Got hr %#x.\n", hr); + + hr = IMediaControl_GetState(control, 0, &state); + todo_wine ok(hr == VFW_S_STATE_INTERMEDIATE, "Got hr %#x.\n", hr); + + thread = send_frame(input); + + hr = IMediaControl_GetState(control, 1000, &state); + ok(hr == S_OK, "Got hr %#x.\n", hr); + + todo_wine ok(WaitForSingleObject(thread, 100) == WAIT_TIMEOUT, "Thread should block in Receive().\n"); + + hr = IMediaControl_Run(control); + todo_wine ok(hr == S_OK, "Got hr %#x.\n", hr); + + hr = IMediaControl_GetState(control, 0, &state); + ok(hr == S_OK, "Got hr %#x.\n", hr); + + hr = join_thread(thread); + ok(hr == S_OK, "Got hr %#x.\n", hr); + + thread = send_frame(input); + hr = join_thread(thread); + ok(hr == S_OK, "Got hr %#x.\n", hr); + + hr = IMediaControl_Pause(control); + ok(hr == S_FALSE, "Got hr %#x.\n", hr); + + hr = IMediaControl_GetState(control, 0, &state); + todo_wine ok(hr == VFW_S_STATE_INTERMEDIATE, "Got hr %#x.\n", hr); + + thread = send_frame(input); + + hr = IMediaControl_GetState(control, 1000, &state); + ok(hr == S_OK, "Got hr %#x.\n", hr); + + todo_wine ok(WaitForSingleObject(thread, 100) == WAIT_TIMEOUT, "Thread should block in Receive().\n"); + + hr = IMediaControl_Run(control); + todo_wine ok(hr == S_OK, "Got hr %#x.\n", hr); + + hr = IMediaControl_GetState(control, 0, &state); + ok(hr == S_OK, "Got hr %#x.\n", hr); + + hr = join_thread(thread); + ok(hr == S_OK, "Got hr %#x.\n", hr); + + hr = IMediaControl_Pause(control); + ok(hr == S_FALSE, "Got hr %#x.\n", hr); + + hr = IMediaControl_GetState(control, 0, &state); + todo_wine ok(hr == VFW_S_STATE_INTERMEDIATE, "Got hr %#x.\n", hr); + + hr = IMediaControl_Stop(control); + ok(hr == S_OK, "Got hr %#x.\n", hr); + + hr = IMediaControl_GetState(control, 0, &state); + ok(hr == S_OK, "Got hr %#x.\n", hr); + + hr = IMediaControl_Pause(control); + ok(hr == S_FALSE, "Got hr %#x.\n", hr); + + hr = IMediaControl_GetState(control, 0, &state); + todo_wine ok(hr == VFW_S_STATE_INTERMEDIATE, "Got hr %#x.\n", hr); + + hr = IMediaControl_Run(control); + ok(hr == S_FALSE, "Got hr %#x.\n", hr); + + hr = IMediaControl_GetState(control, 0, &state); + todo_wine ok(hr == VFW_S_STATE_INTERMEDIATE, "Got hr %#x.\n", hr); + + thread = send_frame(input); + hr = join_thread(thread); + ok(hr == S_OK, "Got hr %#x.\n", hr); + + hr = IMediaControl_GetState(control, 0, &state); + ok(hr == S_OK, "Got hr %#x.\n", hr); + + hr = IMediaControl_Stop(control); + ok(hr == S_OK, "Got hr %#x.\n", hr); + + hr = IMediaControl_GetState(control, 0, &state); + ok(hr == S_OK, "Got hr %#x.\n", hr); + + IMemAllocator_Release(allocator); + IMediaControl_Release(control); +} + static void test_connect_pin(void) { VIDEOINFOHEADER vih = @@ -661,9 +868,11 @@ static void test_connect_pin(void) .cbFormat = sizeof(vih), .pbFormat = (BYTE *)&vih, }; + ALLOCATOR_PROPERTIES req_props = {1, 32 * 16 * 2, 1, 0}, ret_props; IBaseFilter *filter = create_video_renderer(); IFilterGraph2 *graph = create_graph(); struct testfilter source; + IMemAllocator *allocator; IMemInputPin *input; AM_MEDIA_TYPE mt; IPin *pin, *peer; @@ -730,6 +939,22 @@ static void test_connect_pin(void)
test_allocator(input);
+ hr = CoCreateInstance(&CLSID_MemoryAllocator, NULL, CLSCTX_INPROC_SERVER, + &IID_IMemAllocator, (void **)&allocator); + ok(hr == S_OK, "Got hr %#x.\n", hr); + hr = IMemAllocator_SetProperties(allocator, &req_props, &ret_props); + ok(hr == S_OK, "Got hr %#x.\n", hr); + ok(!memcmp(&ret_props, &req_props, sizeof(req_props)), "Properties did not match.\n"); + hr = IMemInputPin_NotifyAllocator(input, allocator, TRUE); + ok(hr == S_OK, "Got hr %#x.\n", hr); + hr = IMemAllocator_Commit(allocator); + ok(hr == S_OK, "Got hr %#x.\n", hr); + + hr = IMemInputPin_ReceiveCanBlock(input); + ok(hr == S_OK, "Got hr %#x.\n", hr); + + test_filter_state(input, graph); + hr = IFilterGraph2_Disconnect(graph, pin); ok(hr == S_OK, "Got hr %#x.\n", hr); hr = IFilterGraph2_Disconnect(graph, pin); @@ -745,6 +970,8 @@ static void test_connect_pin(void) hr = IPin_ConnectionMediaType(pin, &mt); ok(hr == VFW_E_NOT_CONNECTED, "Got hr %#x.\n", hr);
+ ref = IMemAllocator_Release(allocator); + todo_wine ok(!ref, "Got outstanding refcount %d.\n", ref); IMemInputPin_Release(input); IPin_Release(pin); ref = IFilterGraph2_Release(graph); @@ -755,61 +982,6 @@ static void test_connect_pin(void) ok(!ref, "Got outstanding refcount %d.\n", ref); }
-static void test_pin(IPin *pin) -{ - IMemInputPin *mpin = NULL; - - IPin_QueryInterface(pin, &IID_IMemInputPin, (void **)&mpin); - - ok(mpin != NULL, "No IMemInputPin found!\n"); - if (mpin) - { - ok(IMemInputPin_ReceiveCanBlock(mpin) == S_OK, "Receive can't block for pin!\n"); - IMemInputPin_Release(mpin); - } - /* TODO */ -} - -static void test_basefilter(void) -{ - IEnumPins *pin_enum = NULL; - IBaseFilter *base = create_video_renderer(); - IPin *pins[2]; - ULONG ref; - HRESULT hr; - - hr = IBaseFilter_EnumPins(base, NULL); - ok(hr == E_POINTER, "hr = %08x and not E_POINTER\n", hr); - - hr= IBaseFilter_EnumPins(base, &pin_enum); - ok(hr == S_OK, "hr = %08x and not S_OK\n", hr); - - hr = IEnumPins_Next(pin_enum, 1, NULL, NULL); - ok(hr == E_POINTER, "hr = %08x and not E_POINTER\n", hr); - - hr = IEnumPins_Next(pin_enum, 2, pins, NULL); - ok(hr == E_INVALIDARG, "hr = %08x and not E_INVALIDARG\n", hr); - - pins[0] = (void *)0xdead; - pins[1] = (void *)0xdeed; - - hr = IEnumPins_Next(pin_enum, 2, pins, &ref); - ok(hr == S_FALSE, "hr = %08x instead of S_FALSE\n", hr); - ok(pins[0] != (void *)0xdead && pins[0] != NULL, "pins[0] = %p\n", pins[0]); - if (pins[0] != (void *)0xdead && pins[0] != NULL) - { - test_pin(pins[0]); - IPin_Release(pins[0]); - } - - ok(pins[1] == (void *)0xdeed, "pins[1] = %p\n", pins[1]); - - ref = IEnumPins_Release(pin_enum); - ok(ref == 0, "ref is %u and not 0!\n", ref); - - IBaseFilter_Release(base); -} - static void test_unconnected_filter_state(void) { IBaseFilter *filter = create_video_renderer(); @@ -880,7 +1052,6 @@ START_TEST(videorenderer) test_enum_media_types(); test_unconnected_filter_state(); test_connect_pin(); - test_basefilter();
CoUninitialize(); }
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=57123
Your paranoid android.
=== debian10 (build log) ===
error: patch failed: dlls/quartz/tests/videorenderer.c:597 error: patch failed: dlls/quartz/tests/videorenderer.c:600 error: patch failed: dlls/quartz/tests/videorenderer.c:20 Task: Patch failed to apply
=== debian10 (build log) ===
error: patch failed: dlls/quartz/tests/videorenderer.c:597 error: patch failed: dlls/quartz/tests/videorenderer.c:600 error: patch failed: dlls/quartz/tests/videorenderer.c:20 Task: Patch failed to apply
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/quartz/tests/videorenderer.c | 63 +++++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+)
diff --git a/dlls/quartz/tests/videorenderer.c b/dlls/quartz/tests/videorenderer.c index 4e948a9120a..a3ca8038bcc 100644 --- a/dlls/quartz/tests/videorenderer.c +++ b/dlls/quartz/tests/videorenderer.c @@ -850,6 +850,68 @@ static void test_filter_state(IMemInputPin *input, IFilterGraph2 *graph) IMediaControl_Release(control); }
+static void test_flushing(IPin *pin, IMemInputPin *input, IFilterGraph2 *graph) +{ + IMediaControl *control; + OAFilterState state; + HANDLE thread; + HRESULT hr; + + IFilterGraph2_QueryInterface(graph, &IID_IMediaControl, (void **)&control); + + hr = IMediaControl_Pause(control); + ok(hr == S_FALSE, "Got hr %#x.\n", hr); + + thread = send_frame(input); + todo_wine ok(WaitForSingleObject(thread, 100) == WAIT_TIMEOUT, "Thread should block in Receive().\n"); + + hr = IMediaControl_GetState(control, 0, &state); + ok(hr == S_OK, "Got hr %#x.\n", hr); + + hr = IPin_BeginFlush(pin); + ok(hr == S_OK, "Got hr %#x.\n", hr); + + hr = join_thread(thread); + ok(hr == S_OK, "Got hr %#x.\n", hr); + + thread = send_frame(input); + hr = join_thread(thread); + todo_wine ok(hr == E_FAIL, "Got hr %#x.\n", hr); + + hr = IPin_EndFlush(pin); + ok(hr == S_OK, "Got hr %#x.\n", hr); + + /* We dropped the sample we were holding, so now we need a new one... */ + + hr = IMediaControl_GetState(control, 0, &state); + todo_wine ok(hr == VFW_S_STATE_INTERMEDIATE, "Got hr %#x.\n", hr); + + thread = send_frame(input); + todo_wine ok(WaitForSingleObject(thread, 100) == WAIT_TIMEOUT, "Thread should block in Receive().\n"); + + hr = IMediaControl_Run(control); + todo_wine ok(hr == S_OK, "Got hr %#x.\n", hr); + hr = join_thread(thread); + ok(hr == S_OK, "Got hr %#x.\n", hr); + + hr = IPin_BeginFlush(pin); + ok(hr == S_OK, "Got hr %#x.\n", hr); + + hr = join_thread(send_frame(input)); + todo_wine ok(hr == E_FAIL, "Got hr %#x.\n", hr); + + hr = IPin_EndFlush(pin); + ok(hr == S_OK, "Got hr %#x.\n", hr); + + hr = join_thread(send_frame(input)); + ok(hr == S_OK, "Got hr %#x.\n", hr); + + hr = IMediaControl_Stop(control); + ok(hr == S_OK, "Got hr %#x.\n", hr); + + IMediaControl_Release(control); +} + static void test_connect_pin(void) { VIDEOINFOHEADER vih = @@ -954,6 +1016,7 @@ static void test_connect_pin(void) ok(hr == S_OK, "Got hr %#x.\n", hr);
test_filter_state(input, graph); + test_flushing(pin, input, graph);
hr = IFilterGraph2_Disconnect(graph, pin); ok(hr == S_OK, "Got hr %#x.\n", hr);
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=57124
Your paranoid android.
=== debian10 (build log) ===
error: patch failed: dlls/quartz/tests/videorenderer.c:597 error: patch failed: dlls/quartz/tests/videorenderer.c:600 error: patch failed: dlls/quartz/tests/videorenderer.c:20 error: patch failed: dlls/quartz/tests/videorenderer.c:850 Task: Patch failed to apply
=== debian10 (build log) ===
error: patch failed: dlls/quartz/tests/videorenderer.c:597 error: patch failed: dlls/quartz/tests/videorenderer.c:600 error: patch failed: dlls/quartz/tests/videorenderer.c:20 error: patch failed: dlls/quartz/tests/videorenderer.c:850 Task: Patch failed to apply
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/quartz/tests/videorenderer.c | 88 +++++++++++++++++++++++++++++-- 1 file changed, 84 insertions(+), 4 deletions(-)
diff --git a/dlls/quartz/tests/videorenderer.c b/dlls/quartz/tests/videorenderer.c index a3ca8038bcc..3919b419e14 100644 --- a/dlls/quartz/tests/videorenderer.c +++ b/dlls/quartz/tests/videorenderer.c @@ -663,11 +663,11 @@ static DWORD WINAPI frame_thread(void *arg) return hr; }
-static HANDLE send_frame(IMemInputPin *sink) +static HANDLE send_frame_time(IMemInputPin *sink, REFERENCE_TIME start_time, unsigned char color) { struct frame_thread_params *params = heap_alloc(sizeof(*params)); - REFERENCE_TIME start_time, end_time; IMemAllocator *allocator; + REFERENCE_TIME end_time; IMediaSample *sample; HANDLE thread; HRESULT hr; @@ -681,12 +681,12 @@ static HANDLE send_frame(IMemInputPin *sink)
hr = IMediaSample_GetPointer(sample, &data); ok(hr == S_OK, "Got hr %#x.\n", hr); - memset(data, 0x55, 32 * 16 * 2); + memset(data, color, 32 * 16 * 2);
hr = IMediaSample_SetActualDataLength(sample, 32 * 16 * 2); ok(hr == S_OK, "Got hr %#x.\n", hr);
- start_time = 0; + start_time *= 10000000; end_time = start_time + 10000000; hr = IMediaSample_SetTime(sample, &start_time, &end_time); ok(hr == S_OK, "Got hr %#x.\n", hr); @@ -699,6 +699,11 @@ static HANDLE send_frame(IMemInputPin *sink) return thread; }
+static HANDLE send_frame(IMemInputPin *sink) +{ + return send_frame_time(sink, 0, 0x55); /* purple */ +} + static HRESULT join_thread_(int line, HANDLE thread) { DWORD ret; @@ -912,6 +917,80 @@ static void test_flushing(IPin *pin, IMemInputPin *input, IFilterGraph2 *graph) IMediaControl_Release(control); }
+static void test_sample_time(IPin *pin, IMemInputPin *input, IFilterGraph2 *graph) +{ + IMediaControl *control; + OAFilterState state; + HANDLE thread; + HRESULT hr; + + IFilterGraph2_QueryInterface(graph, &IID_IMediaControl, (void **)&control); + + hr = IMediaControl_Pause(control); + ok(hr == S_FALSE, "Got hr %#x.\n", hr); + + hr = IMediaControl_GetState(control, 0, &state); + todo_wine ok(hr == VFW_S_STATE_INTERMEDIATE, "Got hr %#x.\n", hr); + + thread = send_frame_time(input, 1, 0x11); /* dark blue */ + + hr = IMediaControl_GetState(control, 1000, &state); + ok(hr == S_OK, "Got hr %#x.\n", hr); + + ok(WaitForSingleObject(thread, 100) == WAIT_TIMEOUT, "Thread should block in Receive().\n"); + + hr = IMediaControl_Run(control); + todo_wine ok(hr == S_OK, "Got hr %#x.\n", hr); + + ok(WaitForSingleObject(thread, 500) == WAIT_TIMEOUT, "Thread should block in Receive().\n"); + + hr = join_thread(thread); + ok(hr == S_OK, "Got hr %#x.\n", hr); + + /* Sample time is relative to the time passed to Run(). Thus a sample + * stamped at or earlier than 1s will now be displayed immediately, because + * that time has already passed. + * One may manually verify that all of the frames in this function are + * rendered, including (by adding a Sleep() after sending the frame) the + * dark and light green frames. Thus the video renderer does not attempt to + * drop any frames that it considers late. This remains true if the frames + * are marked as discontinuous. */ + + hr = join_thread(send_frame_time(input, 1, 0x22)); /* dark green */ + ok(hr == S_OK, "Got hr %#x.\n", hr); + + hr = join_thread(send_frame_time(input, 0, 0x33)); /* light green */ + ok(hr == S_OK, "Got hr %#x.\n", hr); + + hr = join_thread(send_frame_time(input, -2, 0x44)); /* dark red */ + ok(hr == S_OK, "Got hr %#x.\n", hr); + + thread = send_frame_time(input, 2, 0x66); /* orange */ + ok(WaitForSingleObject(thread, 800) == WAIT_TIMEOUT, "Thread should block in Receive().\n"); + hr = join_thread(thread); + ok(hr == S_OK, "Got hr %#x.\n", hr); + + thread = send_frame_time(input, 1000000, 0xff); /* white */ + ok(WaitForSingleObject(thread, 100) == WAIT_TIMEOUT, "Thread should block in Receive().\n"); + + hr = IPin_BeginFlush(pin); + ok(hr == S_OK, "Got hr %#x.\n", hr); + hr = join_thread(thread); + ok(hr == S_OK, "Got hr %#x.\n", hr); + hr = IPin_EndFlush(pin); + ok(hr == S_OK, "Got hr %#x.\n", hr); + + thread = send_frame_time(input, 1000000, 0xff); + ok(WaitForSingleObject(thread, 100) == WAIT_TIMEOUT, "Thread should block in Receive().\n"); + + hr = IMediaControl_Stop(control); + ok(hr == S_OK, "Got hr %#x.\n", hr); + hr = join_thread(thread); + ok(hr == S_OK, "Got hr %#x.\n", hr); + + IMediaControl_Release(control); +} + static void test_connect_pin(void) { VIDEOINFOHEADER vih = @@ -1017,6 +1096,7 @@ static void test_connect_pin(void)
test_filter_state(input, graph); test_flushing(pin, input, graph); + test_sample_time(pin, input, graph);
hr = IFilterGraph2_Disconnect(graph, pin); ok(hr == S_OK, "Got hr %#x.\n", hr);
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=57125
Your paranoid android.
=== debian10 (build log) ===
error: patch failed: dlls/quartz/tests/videorenderer.c:597 error: patch failed: dlls/quartz/tests/videorenderer.c:600 error: patch failed: dlls/quartz/tests/videorenderer.c:20 error: patch failed: dlls/quartz/tests/videorenderer.c:850 error: patch failed: dlls/quartz/tests/videorenderer.c:663 Task: Patch failed to apply
=== debian10 (build log) ===
error: patch failed: dlls/quartz/tests/videorenderer.c:597 error: patch failed: dlls/quartz/tests/videorenderer.c:600 error: patch failed: dlls/quartz/tests/videorenderer.c:20 error: patch failed: dlls/quartz/tests/videorenderer.c:850 error: patch failed: dlls/quartz/tests/videorenderer.c:663 Task: Patch failed to apply