Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/quartz/tests/vmr7.c | 56 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+)
diff --git a/dlls/quartz/tests/vmr7.c b/dlls/quartz/tests/vmr7.c index 73017290fb..fdd493c089 100644 --- a/dlls/quartz/tests/vmr7.c +++ b/dlls/quartz/tests/vmr7.c @@ -960,6 +960,56 @@ 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, req_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); + + req_props.cBuffers = 1; + req_props.cbBuffer = 32 * 16 * 4; + req_props.cbAlign = 1; + req_props.cbPrefix = 0; + hr = IMemAllocator_SetProperties(ret_allocator, &req_props, &props); + ok(hr == S_OK, "Got hr %#x.\n", hr); + ok(props.cBuffers == 1, "Got %d buffers.\n", props.cBuffers); + ok(props.cbBuffer == 32 * 16 * 4, "Got size %d.\n", props.cbBuffer); + ok(props.cbAlign == 1, "Got alignment %d.\n", props.cbAlign); + ok(!props.cbPrefix, "Got prefix %d.\n", props.cbPrefix); + + IMemAllocator_Release(ret_allocator); + } + + hr = IMemInputPin_NotifyAllocator(input, NULL, TRUE); + todo_wine ok(hr == E_FAIL, "Got hr %#x.\n", hr); + + CoCreateInstance(&CLSID_MemoryAllocator, NULL, CLSCTX_INPROC_SERVER, + &IID_IMemAllocator, (void **)&req_allocator); + + hr = IMemInputPin_NotifyAllocator(input, req_allocator, TRUE); + todo_wine ok(hr == E_FAIL, "Got hr %#x.\n", hr); + + IMemAllocator_Release(req_allocator); +} + static void test_connect_pin(void) { VIDEOINFOHEADER vih = @@ -981,6 +1031,7 @@ static void test_connect_pin(void) IBaseFilter *filter = create_vmr7(VMRMode_Windowed); IFilterGraph2 *graph = create_graph(); struct testfilter source; + IMemInputPin *input; AM_MEDIA_TYPE mt; IPin *pin, *peer; unsigned int i; @@ -1073,6 +1124,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); @@ -1088,6 +1143,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);
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/quartz/tests/vmr7.c | 226 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 226 insertions(+)
diff --git a/dlls/quartz/tests/vmr7.c b/dlls/quartz/tests/vmr7.c index fdd493c089..4dcb15dd5d 100644 --- a/dlls/quartz/tests/vmr7.c +++ b/dlls/quartz/tests/vmr7.c @@ -22,6 +22,7 @@ #include "dshow.h" #include "d3d9.h" #include "vmr9.h" +#include "wine/heap.h" #include "wine/strmbase.h" #include "wine/test.h"
@@ -1010,6 +1011,215 @@ static void test_allocator(IMemInputPin *input) IMemAllocator_Release(req_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 * 4); + + hr = IMediaSample_SetActualDataLength(sample, 32 * 16 * 4); + 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); + ok(hr == VFW_E_WRONG_STATE, "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, however it + * will not 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); + ok(hr == VFW_E_WRONG_STATE, "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 = IMemAllocator_Commit(allocator); + 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 = @@ -1028,9 +1238,11 @@ static void test_connect_pin(void) .cbFormat = sizeof(vih), .pbFormat = (BYTE *)&vih, }; + ALLOCATOR_PROPERTIES req_props = {1, 32 * 16 * 4, 1, 0}, ret_props; IBaseFilter *filter = create_vmr7(VMRMode_Windowed); IFilterGraph2 *graph = create_graph(); struct testfilter source; + IMemAllocator *allocator; IMemInputPin *input; AM_MEDIA_TYPE mt; IPin *pin, *peer; @@ -1128,6 +1340,20 @@ static void test_connect_pin(void)
test_allocator(input);
+ hr = IMemInputPin_GetAllocator(input, &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 = IMemAllocator_Commit(allocator); + ok(hr == S_OK, "Got hr %#x.\n", hr); + IMemAllocator_Release(allocator); + + 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);
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=60542
Your paranoid android.
=== w7u (32 bit report) ===
quartz: vmr7.c:1054: Test failed: Got hr 0x8004020d. vmr7.c:1091: Test failed: Wait failed. vmr7.c:1092: Test failed: Got hr 0x103.
Report errors: quartz:vmr7 crashed (c0000005)
=== wvistau64 (64 bit report) ===
Report errors: quartz:vmr7 crashed (c0000374)
=== w2008s64 (64 bit report) ===
Report errors: quartz:vmr7 crashed (c0000374)
=== w864 (64 bit report) ===
Report errors: quartz:vmr7 crashed (c0000374)
=== w1064v1507 (64 bit report) ===
Report errors: quartz:vmr7 crashed (c0000374)
=== w1064v1809 (64 bit report) ===
quartz: 1960:vmr7: unhandled exception c0000005 at 000000000043CC75
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/quartz/tests/vmr7.c | 72 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 72 insertions(+)
diff --git a/dlls/quartz/tests/vmr7.c b/dlls/quartz/tests/vmr7.c index 4dcb15dd5d..80b6c2176d 100644 --- a/dlls/quartz/tests/vmr7.c +++ b/dlls/quartz/tests/vmr7.c @@ -1220,6 +1220,77 @@ static void test_filter_state(IMemInputPin *input, IFilterGraph2 *graph) IMediaControl_Release(control); }
+static void test_flushing(IPin *pin, IMemInputPin *input, IFilterGraph2 *graph) +{ + IMemAllocator *allocator; + IMediaControl *control; + OAFilterState state; + HANDLE thread; + HRESULT hr; + + IFilterGraph2_QueryInterface(graph, &IID_IMediaControl, (void **)&control); + + hr = IMemInputPin_GetAllocator(input, &allocator); + ok(hr == S_OK, "Got hr %#x.\n", hr); + hr = IMemAllocator_Commit(allocator); + ok(hr == S_OK, "Got hr %#x.\n", hr); + IMemAllocator_Release(allocator); + + 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); + ok(hr == S_FALSE, "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); + + thread = send_frame(input); + hr = join_thread(thread); + ok(hr == S_FALSE, "Got hr %#x.\n", hr); + + hr = IPin_EndFlush(pin); + 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_Stop(control); + ok(hr == S_OK, "Got hr %#x.\n", hr); + + IMediaControl_Release(control); +} + static void test_connect_pin(void) { VIDEOINFOHEADER vih = @@ -1353,6 +1424,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=60543
Your paranoid android.
=== w7u (32 bit report) ===
quartz: vmr7.c:1054: Test failed: Got hr 0x8004020d.
Report errors: quartz:vmr7 crashed (c0000005)
=== wvistau64 (64 bit report) ===
Report errors: quartz:vmr7 crashed (c0000374)
=== w2008s64 (64 bit report) ===
Report errors: quartz:vmr7 crashed (c0000374)
=== w864 (64 bit report) ===
Report errors: quartz:vmr7 crashed (c0000374)
=== w1064v1507 (64 bit report) ===
Report errors: quartz:vmr7 crashed (c0000374)
=== w1064v1809 (64 bit report) ===
quartz: 1964:vmr7: unhandled exception c0000005 at 000000000043CC75
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/quartz/tests/vmr9.c | 56 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+)
diff --git a/dlls/quartz/tests/vmr9.c b/dlls/quartz/tests/vmr9.c index e30da6b782..3346aaff84 100644 --- a/dlls/quartz/tests/vmr9.c +++ b/dlls/quartz/tests/vmr9.c @@ -964,6 +964,56 @@ 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, req_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); + + req_props.cBuffers = 1; + req_props.cbBuffer = 32 * 16 * 4; + req_props.cbAlign = 1; + req_props.cbPrefix = 0; + hr = IMemAllocator_SetProperties(ret_allocator, &req_props, &props); + ok(hr == S_OK, "Got hr %#x.\n", hr); + ok(props.cBuffers == 1, "Got %d buffers.\n", props.cBuffers); + ok(props.cbBuffer == 32 * 16 * 4, "Got size %d.\n", props.cbBuffer); + ok(props.cbAlign == 1, "Got alignment %d.\n", props.cbAlign); + ok(!props.cbPrefix, "Got prefix %d.\n", props.cbPrefix); + + IMemAllocator_Release(ret_allocator); + } + + hr = IMemInputPin_NotifyAllocator(input, NULL, TRUE); + todo_wine ok(hr == E_FAIL, "Got hr %#x.\n", hr); + + CoCreateInstance(&CLSID_MemoryAllocator, NULL, CLSCTX_INPROC_SERVER, + &IID_IMemAllocator, (void **)&req_allocator); + + hr = IMemInputPin_NotifyAllocator(input, req_allocator, TRUE); + todo_wine ok(hr == E_FAIL, "Got hr %#x.\n", hr); + + IMemAllocator_Release(req_allocator); +} + static void test_connect_pin(void) { VIDEOINFOHEADER vih = @@ -985,6 +1035,7 @@ static void test_connect_pin(void) IBaseFilter *filter = create_vmr9(VMR9Mode_Windowed); IFilterGraph2 *graph = create_graph(); struct testfilter source; + IMemInputPin *input; unsigned int i, j; AM_MEDIA_TYPE mt; IPin *pin, *peer; @@ -1077,6 +1128,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); @@ -1093,6 +1148,7 @@ static void test_connect_pin(void) ok(hr == VFW_E_NOT_CONNECTED, "Got hr %#x.\n", hr);
out: + IMemInputPin_Release(input); IPin_Release(pin); ref = IFilterGraph2_Release(graph); ok(!ref, "Got outstanding refcount %d.\n", ref);
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/quartz/tests/vmr9.c | 226 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 226 insertions(+)
diff --git a/dlls/quartz/tests/vmr9.c b/dlls/quartz/tests/vmr9.c index 3346aaff84..cd2c5f9833 100644 --- a/dlls/quartz/tests/vmr9.c +++ b/dlls/quartz/tests/vmr9.c @@ -22,6 +22,7 @@ #include "dshow.h" #include "d3d9.h" #include "vmr9.h" +#include "wine/heap.h" #include "wine/strmbase.h" #include "wine/test.h"
@@ -1014,6 +1015,215 @@ static void test_allocator(IMemInputPin *input) IMemAllocator_Release(req_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 * 4); + + hr = IMediaSample_SetActualDataLength(sample, 32 * 16 * 4); + 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); + ok(hr == VFW_E_WRONG_STATE, "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, however it + * will not 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); + ok(hr == VFW_E_WRONG_STATE, "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 = IMemAllocator_Commit(allocator); + 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 = @@ -1032,9 +1242,11 @@ static void test_connect_pin(void) .cbFormat = sizeof(vih), .pbFormat = (BYTE *)&vih, }; + ALLOCATOR_PROPERTIES req_props = {1, 32 * 16 * 4, 1, 0}, ret_props; IBaseFilter *filter = create_vmr9(VMR9Mode_Windowed); IFilterGraph2 *graph = create_graph(); struct testfilter source; + IMemAllocator *allocator; IMemInputPin *input; unsigned int i, j; AM_MEDIA_TYPE mt; @@ -1132,6 +1344,20 @@ static void test_connect_pin(void)
test_allocator(input);
+ hr = IMemInputPin_GetAllocator(input, &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 = IMemAllocator_Commit(allocator); + ok(hr == S_OK, "Got hr %#x.\n", hr); + IMemAllocator_Release(allocator); + + 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);
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=60545
Your paranoid android.
=== w864 (64 bit report) ===
Report errors: quartz:vmr9 crashed (c0000374)
=== w1064v1507 (64 bit report) ===
Report errors: quartz:vmr9 crashed (c0000374)
=== w1064v1809 (64 bit report) ===
Report errors: quartz:vmr9 crashed (c0000374)
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/quartz/tests/vmr9.c | 72 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 72 insertions(+)
diff --git a/dlls/quartz/tests/vmr9.c b/dlls/quartz/tests/vmr9.c index cd2c5f9833..b2f4829741 100644 --- a/dlls/quartz/tests/vmr9.c +++ b/dlls/quartz/tests/vmr9.c @@ -1224,6 +1224,77 @@ static void test_filter_state(IMemInputPin *input, IFilterGraph2 *graph) IMediaControl_Release(control); }
+static void test_flushing(IPin *pin, IMemInputPin *input, IFilterGraph2 *graph) +{ + IMemAllocator *allocator; + IMediaControl *control; + OAFilterState state; + HANDLE thread; + HRESULT hr; + + IFilterGraph2_QueryInterface(graph, &IID_IMediaControl, (void **)&control); + + hr = IMemInputPin_GetAllocator(input, &allocator); + ok(hr == S_OK, "Got hr %#x.\n", hr); + hr = IMemAllocator_Commit(allocator); + ok(hr == S_OK, "Got hr %#x.\n", hr); + IMemAllocator_Release(allocator); + + 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); + ok(hr == S_FALSE, "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); + + thread = send_frame(input); + hr = join_thread(thread); + ok(hr == S_FALSE, "Got hr %#x.\n", hr); + + hr = IPin_EndFlush(pin); + 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_Stop(control); + ok(hr == S_OK, "Got hr %#x.\n", hr); + + IMediaControl_Release(control); +} + static void test_connect_pin(void) { VIDEOINFOHEADER vih = @@ -1357,6 +1428,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=60546
Your paranoid android.
=== w864 (64 bit report) ===
Report errors: quartz:vmr9 crashed (c0000374)
=== w1064v1507 (64 bit report) ===
Report errors: quartz:vmr9 crashed (c0000374)
=== w1064v1809 (64 bit report) ===
Report errors: quartz:vmr9 crashed (c0000374)