Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/quartz/tests/vmr9.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/dlls/quartz/tests/vmr9.c b/dlls/quartz/tests/vmr9.c index 367d7df568f..d8c2ee8b4a7 100644 --- a/dlls/quartz/tests/vmr9.c +++ b/dlls/quartz/tests/vmr9.c @@ -378,12 +378,12 @@ static void test_aggregation(void) ULONG ref;
filter = (IBaseFilter *)0xdeadbeef; - hr = CoCreateInstance(&CLSID_VideoMixingRenderer, &test_outer, CLSCTX_INPROC_SERVER, + hr = CoCreateInstance(&CLSID_VideoMixingRenderer9, &test_outer, CLSCTX_INPROC_SERVER, &IID_IBaseFilter, (void **)&filter); ok(hr == E_NOINTERFACE, "Got hr %#x.\n", hr); ok(!filter, "Got interface %p.\n", filter);
- hr = CoCreateInstance(&CLSID_VideoMixingRenderer, &test_outer, CLSCTX_INPROC_SERVER, + hr = CoCreateInstance(&CLSID_VideoMixingRenderer9, &test_outer, CLSCTX_INPROC_SERVER, &IID_IUnknown, (void **)&unk); ok(hr == S_OK, "Got hr %#x.\n", hr); ok(outer_ref == 1, "Got unexpected refcount %d.\n", outer_ref);
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/quartz/tests/vmr9.c | 88 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 88 insertions(+)
diff --git a/dlls/quartz/tests/vmr9.c b/dlls/quartz/tests/vmr9.c index d8c2ee8b4a7..9485d055f09 100644 --- a/dlls/quartz/tests/vmr9.c +++ b/dlls/quartz/tests/vmr9.c @@ -2896,6 +2896,93 @@ out: DestroyWindow(window); }
+static void test_mixing_mode(void) +{ + IVMRWindowlessControl9 *windowless_control; + IVMRMixerControl9 *mixer_control; + IVMRFilterConfig9 *config; + DWORD stream_count = 0; + IBaseFilter *filter; + unsigned int i; + HWND window; + HRESULT hr; + ULONG ref; + + static const VMR9Mode modes[] = + { + 0, + VMR9Mode_Windowed, + VMR9Mode_Windowless, + VMR9Mode_Renderless, + }; + + for (i = 0; i < ARRAY_SIZE(modes); ++i) + { + filter = create_vmr9(modes[i]); + IBaseFilter_QueryInterface(filter, &IID_IVMRFilterConfig9, (void **)&config); + + hr = IBaseFilter_QueryInterface(filter, &IID_IVMRMixerControl9, (void **)&mixer_control); + ok(hr == E_NOINTERFACE, "Got hr %#x.\n", hr); + + hr = IVMRFilterConfig9_GetNumberOfStreams(config, &stream_count); + todo_wine ok(hr == VFW_E_VMR_NOT_IN_MIXER_MODE, "Got hr %#x.\n", hr); + + hr = IVMRFilterConfig9_SetNumberOfStreams(config, 1); + ok(hr == S_OK, "Got hr %#x.\n", hr); + + hr = IVMRFilterConfig9_GetNumberOfStreams(config, &stream_count); + todo_wine ok(hr == S_OK, "Got hr %#x.\n", hr); + todo_wine ok(stream_count == 1, "Got %u streams.\n", stream_count); + + hr = IBaseFilter_QueryInterface(filter, &IID_IVMRMixerControl9, (void **)&mixer_control); + todo_wine ok(hr == S_OK, "Got hr %#x.\n", hr); + if (hr == S_OK) + IVMRMixerControl9_Release(mixer_control); + + hr = IVMRFilterConfig9_SetNumberOfStreams(config, 2); + todo_wine ok(hr == VFW_E_WRONG_STATE, "Got hr %#x.\n", hr); + + hr = IVMRFilterConfig9_GetNumberOfStreams(config, &stream_count); + todo_wine ok(hr == S_OK, "Got hr %#x.\n", hr); + todo_wine ok(stream_count == 1, "Got %u streams.\n", stream_count); + + IVMRFilterConfig9_Release(config); + ref = IBaseFilter_Release(filter); + ok(!ref, "Got outstanding refcount %d.\n", ref); + } + + filter = create_vmr9(VMR9Mode_Windowless); + IBaseFilter_QueryInterface(filter, &IID_IVMRFilterConfig9, (void **)&config); + IBaseFilter_QueryInterface(filter, &IID_IVMRWindowlessControl9, (void **)&windowless_control); + + window = CreateWindowA("static", "quartz_test", WS_OVERLAPPEDWINDOW, 0, 0, 640, 480, 0, 0, 0, 0); + ok(!!window, "Failed to create a window.\n"); + hr = IVMRWindowlessControl9_SetVideoClippingWindow(windowless_control, window); + ok(hr == S_OK, "Got hr %#x.\n", hr); + + hr = IVMRFilterConfig9_GetNumberOfStreams(config, &stream_count); + todo_wine ok(hr == S_OK, "Got hr %#x.\n", hr); + todo_wine ok(stream_count == 4, "Got %u streams.\n", stream_count); + + hr = IBaseFilter_QueryInterface(filter, &IID_IVMRMixerControl9, (void **)&mixer_control); + todo_wine ok(hr == S_OK, "Got hr %#x.\n", hr); + if (hr == S_OK) + IVMRMixerControl9_Release(mixer_control); + + hr = IVMRFilterConfig9_SetNumberOfStreams(config, 2); + todo_wine ok(hr == VFW_E_WRONG_STATE, "Got hr %#x.\n", hr); + + hr = IVMRFilterConfig9_GetNumberOfStreams(config, &stream_count); + todo_wine ok(hr == S_OK, "Got hr %#x.\n", hr); + todo_wine ok(stream_count == 4, "Got %u streams.\n", stream_count); + + IVMRWindowlessControl9_Release(windowless_control); + IVMRFilterConfig9_Release(config); + ref = IBaseFilter_Release(filter); + ok(!ref, "Got outstanding refcount %d.\n", ref); + DestroyWindow(window); +} + START_TEST(vmr9) { IBaseFilter *filter; @@ -2925,6 +3012,7 @@ START_TEST(vmr9) test_video_window(); test_allocate_surface_helper(); test_renderless_formats(); + test_mixing_mode();
CoUninitialize(); }
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/quartz/tests/vmr9.c | 154 ++++++++++++++++++++++++++++----------- 1 file changed, 111 insertions(+), 43 deletions(-)
diff --git a/dlls/quartz/tests/vmr9.c b/dlls/quartz/tests/vmr9.c index 9485d055f09..0e02de64522 100644 --- a/dlls/quartz/tests/vmr9.c +++ b/dlls/quartz/tests/vmr9.c @@ -964,13 +964,14 @@ 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, DWORD 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; + LONG size, i; HRESULT hr; BYTE *data;
@@ -980,14 +981,16 @@ static HANDLE send_frame(IMemInputPin *sink) hr = IMemAllocator_GetBuffer(allocator, &sample, NULL, NULL, 0); ok(hr == S_OK, "Got hr %#x.\n", hr);
+ size = IMediaSample_GetSize(sample); hr = IMediaSample_GetPointer(sample, &data); ok(hr == S_OK, "Got hr %#x.\n", hr); - memset(data, 0x55, IMediaSample_GetSize(sample)); + for (i = 0; i < size / sizeof(DWORD); ++i) + ((DWORD *)data)[i] = color;
- hr = IMediaSample_SetActualDataLength(sample, IMediaSample_GetSize(sample)); + hr = IMediaSample_SetActualDataLength(sample, size); 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); @@ -1000,6 +1003,11 @@ static HANDLE send_frame(IMemInputPin *sink) return thread; }
+static HANDLE send_frame(IMemInputPin *sink) +{ + return send_frame_time(sink, 0, 0x007f007f); +} + static HRESULT join_thread_(int line, HANDLE thread) { DWORD ret; @@ -1010,17 +1018,26 @@ static HRESULT join_thread_(int line, HANDLE thread) } #define join_thread(a) join_thread_(__LINE__, a)
-static void test_filter_state(IMemInputPin *input, IFilterGraph2 *graph) +static void commit_allocator(IMemInputPin *input) +{ + IMemAllocator *allocator; + HRESULT hr; + + 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); +} + +static void test_filter_state(IMemInputPin *input, IMediaControl *control) { 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); @@ -1122,9 +1139,7 @@ static void test_filter_state(IMemInputPin *input, IFilterGraph2 *graph) 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); - + commit_allocator(input); hr = IMediaControl_Pause(control); ok(hr == S_FALSE, "Got hr %#x.\n", hr);
@@ -1151,25 +1166,15 @@ static void test_filter_state(IMemInputPin *input, IFilterGraph2 *graph) ok(hr == S_OK, "Got hr %#x.\n", hr);
IMemAllocator_Release(allocator); - IMediaControl_Release(control); }
-static void test_flushing(IPin *pin, IMemInputPin *input, IFilterGraph2 *graph) +static void test_flushing(IPin *pin, IMemInputPin *input, IMediaControl *control) { - 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); - + commit_allocator(input); hr = IMediaControl_Pause(control); ok(hr == S_FALSE, "Got hr %#x.\n", hr);
@@ -1221,19 +1226,85 @@ static void test_flushing(IPin *pin, IMemInputPin *input, IFilterGraph2 *graph)
hr = IMediaControl_Stop(control); ok(hr == S_OK, "Got hr %#x.\n", hr); +}
- IMediaControl_Release(control); +static void test_sample_time(IPin *pin, IMemInputPin *input, IMediaControl *control) +{ + OAFilterState state; + HANDLE thread; + HRESULT hr; + + commit_allocator(input); + hr = IMediaControl_Pause(control); + ok(hr == S_FALSE, "Got hr %#x.\n", hr); + + hr = IMediaControl_GetState(control, 0, &state); + ok(hr == VFW_S_STATE_INTERMEDIATE, "Got hr %#x.\n", hr); + + thread = send_frame_time(input, 1, 0x000000ff); /* 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); + 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 + * cyan and green frames. Thus the VMR 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, 0x0000ffff)); /* cyan */ + ok(hr == S_OK, "Got hr %#x.\n", hr); + + hr = join_thread(send_frame_time(input, 0, 0x0000ff00)); /* green */ + ok(hr == S_OK, "Got hr %#x.\n", hr); + + hr = join_thread(send_frame_time(input, -2, 0x00ff0000)); /* red */ + ok(hr == S_OK, "Got hr %#x.\n", hr); + + thread = send_frame_time(input, 2, 0x00ff00ff); /* magenta */ + 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, 0x00ffffff); /* 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, 0x00ffff00); /* yellow */ + 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); }
static void test_current_image(IBaseFilter *filter, IMemInputPin *input, - IFilterGraph2 *graph, const BITMAPINFOHEADER *req_bih) + IMediaControl *control, const BITMAPINFOHEADER *req_bih) { LONG buffer[(sizeof(BITMAPINFOHEADER) + 32 * 16 * 4) / 4]; const BITMAPINFOHEADER *bih = (BITMAPINFOHEADER *)buffer; const DWORD *data = (DWORD *)((char *)buffer + sizeof(BITMAPINFOHEADER)); BITMAPINFOHEADER expect_bih = *req_bih; - IMemAllocator *allocator; - IMediaControl *control; OAFilterState state; IBasicVideo *video; unsigned int i; @@ -1243,7 +1314,6 @@ static void test_current_image(IBaseFilter *filter, IMemInputPin *input,
expect_bih.biSizeImage = 32 * 16 * 4;
- IFilterGraph2_QueryInterface(graph, &IID_IMediaControl, (void **)&control); IBaseFilter_QueryInterface(filter, &IID_IBasicVideo, (void **)&video);
hr = IBasicVideo_GetCurrentImage(video, NULL, NULL); @@ -1264,12 +1334,7 @@ static void test_current_image(IBaseFilter *filter, IMemInputPin *input, ok(!memcmp(bih, &expect_bih, sizeof(BITMAPINFOHEADER)), "Bitmap headers didn't match.\n"); /* The contents seem to reflect the last frame rendered. */
- 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); - + commit_allocator(input); hr = IMediaControl_Pause(control); ok(hr == S_FALSE, "Got hr %#x.\n", hr);
@@ -1299,7 +1364,7 @@ static void test_current_image(IBaseFilter *filter, IMemInputPin *input, if (0) /* FIXME: Rendering is currently broken on Wine. */ { for (i = 0; i < 32 * 16; ++i) - ok((data[i] & 0xffffff) == 0x555555, "Got unexpected color %08x at %u.\n", data[i], i); + ok((data[i] & 0xffffff) == 0x7f007f, "Got unexpected color %08x at %u.\n", data[i], i); }
hr = IMediaControl_Run(control); @@ -1315,14 +1380,13 @@ static void test_current_image(IBaseFilter *filter, IMemInputPin *input, if (0) /* FIXME: Rendering is currently broken on Wine. */ { for (i = 0; i < 32 * 16; ++i) - ok((data[i] & 0xffffff) == 0x555555, "Got unexpected color %08x at %u.\n", data[i], i); + ok((data[i] & 0xffffff) == 0x7f007f, "Got unexpected color %08x at %u.\n", data[i], i); }
hr = IMediaControl_Stop(control); ok(hr == S_OK, "Got hr %#x.\n", hr);
IBasicVideo_Release(video); - IMediaControl_Release(control); }
static void test_connect_pin(void) @@ -1348,6 +1412,7 @@ static void test_connect_pin(void) IFilterGraph2 *graph = create_graph(); struct testfilter source; IMemAllocator *allocator; + IMediaControl *control; IMemInputPin *input; unsigned int i, j; AM_MEDIA_TYPE mt; @@ -1368,6 +1433,7 @@ static void test_connect_pin(void)
IFilterGraph2_AddFilter(graph, &source.filter.IBaseFilter_iface, NULL); IFilterGraph2_AddFilter(graph, filter, NULL); + IFilterGraph2_QueryInterface(graph, &IID_IMediaControl, (void **)&control);
IBaseFilter_FindPin(filter, L"VMR Input0", &pin); IPin_QueryInterface(pin, &IID_IMemInputPin, (void **)&input); @@ -1453,9 +1519,10 @@ static void test_connect_pin(void) hr = IMemInputPin_ReceiveCanBlock(input); ok(hr == S_OK, "Got hr %#x.\n", hr);
- test_filter_state(input, graph); - test_flushing(pin, input, graph); - test_current_image(filter, input, graph, &vih.bmiHeader); + test_filter_state(input, control); + test_flushing(pin, input, control); + test_sample_time(pin, input, control); + test_current_image(filter, input, control, &vih.bmiHeader);
hr = IFilterGraph2_Disconnect(graph, pin); ok(hr == S_OK, "Got hr %#x.\n", hr); @@ -1473,10 +1540,11 @@ static void test_connect_pin(void) ok(hr == VFW_E_NOT_CONNECTED, "Got hr %#x.\n", hr);
out: - IMemInputPin_Release(input); - IPin_Release(pin); + IMediaControl_Release(control); ref = IFilterGraph2_Release(graph); ok(!ref, "Got outstanding refcount %d.\n", ref); + IMemInputPin_Release(input); + IPin_Release(pin); ref = IBaseFilter_Release(filter); ok(!ref, "Got outstanding refcount %d.\n", ref); ref = IBaseFilter_Release(&source.filter.IBaseFilter_iface);
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/quartz/tests/vmr9.c | 140 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 140 insertions(+)
diff --git a/dlls/quartz/tests/vmr9.c b/dlls/quartz/tests/vmr9.c index 0e02de64522..cb04d0b4aa5 100644 --- a/dlls/quartz/tests/vmr9.c +++ b/dlls/quartz/tests/vmr9.c @@ -1228,6 +1228,145 @@ static void test_flushing(IPin *pin, IMemInputPin *input, IMediaControl *control ok(hr == S_OK, "Got hr %#x.\n", hr); }
+static unsigned int check_ec_complete(IMediaEvent *eventsrc, DWORD timeout) +{ + LONG_PTR param1, param2; + unsigned int ret = 0; + HRESULT hr; + LONG code; + + while ((hr = IMediaEvent_GetEvent(eventsrc, &code, ¶m1, ¶m2, timeout)) == S_OK) + { + if (code == EC_COMPLETE) + { + ok(param1 == S_OK, "Got param1 %#lx.\n", param1); + ok(!param2, "Got param2 %#lx.\n", param2); + ret++; + } + IMediaEvent_FreeEventParams(eventsrc, code, param1, param2); + timeout = 0; + } + ok(hr == E_ABORT, "Got hr %#x.\n", hr); + + return ret; +} + +static void test_eos(IPin *pin, IMemInputPin *input, IMediaControl *control) +{ + IMediaEvent *eventsrc; + OAFilterState state; + HRESULT hr; + BOOL ret; + + IMediaControl_QueryInterface(control, &IID_IMediaEvent, (void **)&eventsrc); + + commit_allocator(input); + hr = IMediaControl_Pause(control); + ok(hr == S_FALSE, "Got hr %#x.\n", hr); + ret = check_ec_complete(eventsrc, 0); + ok(!ret, "Got unexpected EC_COMPLETE.\n"); + + hr = IPin_EndOfStream(pin); + ok(hr == S_OK, "Got hr %#x.\n", hr); + + hr = IMediaControl_GetState(control, 1000, &state); + ok(hr == S_OK, "Got hr %#x.\n", hr); + ret = check_ec_complete(eventsrc, 0); + todo_wine ok(!ret, "Got unexpected EC_COMPLETE.\n"); + + hr = join_thread(send_frame(input)); + todo_wine ok(hr == E_UNEXPECTED, "Got hr %#x.\n", hr); + + hr = IMediaControl_Run(control); + ok(hr == S_OK, "Got hr %#x.\n", hr); + ret = check_ec_complete(eventsrc, 0); + todo_wine ok(ret == 1, "Expected EC_COMPLETE.\n"); + + hr = IMediaControl_Stop(control); + ok(hr == S_OK, "Got hr %#x.\n", hr); + ret = check_ec_complete(eventsrc, 0); + ok(!ret, "Got unexpected EC_COMPLETE.\n"); + + /* We do not receive an EC_COMPLETE notification until the last sample is + * done rendering. */ + + commit_allocator(input); + hr = IMediaControl_Run(control); + todo_wine ok(hr == S_FALSE, "Got hr %#x.\n", hr); + hr = join_thread(send_frame(input)); + ok(hr == S_OK, "Got hr %#x.\n", hr); + hr = IMediaControl_GetState(control, 1000, &state); + ok(hr == S_OK, "Got hr %#x.\n", hr); + ret = check_ec_complete(eventsrc, 0); + ok(!ret, "Got unexpected EC_COMPLETE.\n"); + + hr = IPin_EndOfStream(pin); + ok(hr == S_OK, "Got hr %#x.\n", hr); + ret = check_ec_complete(eventsrc, 0); + todo_wine ok(!ret, "Got unexpected EC_COMPLETE.\n"); + ret = check_ec_complete(eventsrc, 1600); + todo_wine ok(ret == 1, "Expected EC_COMPLETE.\n"); + + hr = IMediaControl_Stop(control); + ok(hr == S_OK, "Got hr %#x.\n", hr); + ret = check_ec_complete(eventsrc, 0); + ok(!ret, "Got unexpected EC_COMPLETE.\n"); + + /* Test sending EOS while flushing. */ + + commit_allocator(input); + hr = IMediaControl_Run(control); + todo_wine ok(hr == S_FALSE, "Got hr %#x.\n", hr); + hr = join_thread(send_frame(input)); + ok(hr == S_OK, "Got hr %#x.\n", hr); + + hr = IPin_BeginFlush(pin); + ok(hr == S_OK, "Got hr %#x.\n", hr); + hr = IPin_EndOfStream(pin); + todo_wine ok(hr == S_FALSE, "Got hr %#x.\n", hr); + hr = IPin_EndFlush(pin); + ok(hr == S_OK, "Got hr %#x.\n", hr); + + hr = IMediaControl_Stop(control); + ok(hr == S_OK, "Got hr %#x.\n", hr); + ret = check_ec_complete(eventsrc, 0); + todo_wine ok(!ret, "Got unexpected EC_COMPLETE.\n"); + + /* Test sending EOS and then flushing or stopping. */ + + commit_allocator(input); + hr = IMediaControl_Run(control); + todo_wine ok(hr == S_FALSE, "Got hr %#x.\n", hr); + hr = join_thread(send_frame(input)); + ok(hr == S_OK, "Got hr %#x.\n", hr); + hr = IMediaControl_GetState(control, 1000, &state); + ok(hr == S_OK, "Got hr %#x.\n", hr); + + hr = IPin_EndOfStream(pin); + ok(hr == S_OK, "Got hr %#x.\n", hr); + ret = check_ec_complete(eventsrc, 0); + todo_wine ok(!ret, "Got unexpected EC_COMPLETE.\n"); + + hr = IPin_BeginFlush(pin); + ok(hr == S_OK, "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 = IPin_EndOfStream(pin); + ok(hr == S_OK, "Got hr %#x.\n", hr); + ret = check_ec_complete(eventsrc, 0); + ok(!ret, "Got unexpected EC_COMPLETE.\n"); + + hr = IMediaControl_Stop(control); + ok(hr == S_OK, "Got hr %#x.\n", hr); + ret = check_ec_complete(eventsrc, 0); + ok(!ret, "Got unexpected EC_COMPLETE.\n"); + + IMediaEvent_Release(eventsrc); +} + static void test_sample_time(IPin *pin, IMemInputPin *input, IMediaControl *control) { OAFilterState state; @@ -1521,6 +1660,7 @@ static void test_connect_pin(void)
test_filter_state(input, control); test_flushing(pin, input, control); + test_eos(pin, input, control); test_sample_time(pin, input, control); test_current_image(filter, input, control, &vih.bmiHeader);
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/quartz/tests/videorenderer.c | 186 +++++++++++++++++++++++++++++- 1 file changed, 184 insertions(+), 2 deletions(-)
diff --git a/dlls/quartz/tests/videorenderer.c b/dlls/quartz/tests/videorenderer.c index 3722a6f9ddd..90d1e019324 100644 --- a/dlls/quartz/tests/videorenderer.c +++ b/dlls/quartz/tests/videorenderer.c @@ -489,6 +489,7 @@ struct testfilter { struct strmbase_filter filter; struct strmbase_source source; + IMediaSeeking IMediaSeeking_iface; };
static inline struct testfilter *impl_from_BaseFilter(struct strmbase_filter *iface) @@ -517,6 +518,19 @@ static const struct strmbase_filter_ops testfilter_ops = .filter_destroy = testfilter_destroy, };
+static HRESULT testsource_query_interface(struct strmbase_pin *iface, REFIID iid, void **out) +{ + struct testfilter *filter = impl_from_BaseFilter(iface->filter); + + if (IsEqualGUID(iid, &IID_IMediaSeeking)) + *out = &filter->IMediaSeeking_iface; + else + return E_NOINTERFACE; + + IUnknown_AddRef((IUnknown *)*out); + return S_OK; +} + static HRESULT WINAPI testsource_DecideAllocator(struct strmbase_source *iface, IMemInputPin *peer, IMemAllocator **allocator) { @@ -525,15 +539,172 @@ static HRESULT WINAPI testsource_DecideAllocator(struct strmbase_source *iface,
static const struct strmbase_source_ops testsource_ops = { + .base.pin_query_interface = testsource_query_interface, .pfnAttemptConnection = BaseOutputPinImpl_AttemptConnection, .pfnDecideAllocator = testsource_DecideAllocator, };
+static struct testfilter *impl_from_IMediaSeeking(IMediaSeeking *iface) +{ + return CONTAINING_RECORD(iface, struct testfilter, IMediaSeeking_iface); +} + +static HRESULT WINAPI testseek_QueryInterface(IMediaSeeking *iface, REFIID iid, void **out) +{ + struct testfilter *filter = impl_from_IMediaSeeking(iface); + return IUnknown_QueryInterface(filter->filter.outer_unk, iid, out); +} + +static ULONG WINAPI testseek_AddRef(IMediaSeeking *iface) +{ + struct testfilter *filter = impl_from_IMediaSeeking(iface); + return IUnknown_AddRef(filter->filter.outer_unk); +} + +static ULONG WINAPI testseek_Release(IMediaSeeking *iface) +{ + struct testfilter *filter = impl_from_IMediaSeeking(iface); + return IUnknown_Release(filter->filter.outer_unk); +} + +static HRESULT WINAPI testseek_GetCapabilities(IMediaSeeking *iface, DWORD *caps) +{ + ok(0, "Unexpected call.\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI testseek_CheckCapabilities(IMediaSeeking *iface, DWORD *caps) +{ + ok(0, "Unexpected call.\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI testseek_IsFormatSupported(IMediaSeeking *iface, const GUID *format) +{ + if (winetest_debug > 1) trace("IsFormatSupported()\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI testseek_QueryPreferredFormat(IMediaSeeking *iface, GUID *format) +{ + if (winetest_debug > 1) trace("%p->QueryPreferredFormat()\n", iface); + return E_NOTIMPL; +} + +static HRESULT WINAPI testseek_GetTimeFormat(IMediaSeeking *iface, GUID *format) +{ + if (winetest_debug > 1) trace("%p->GetTimeFormat()\n", iface); + return E_NOTIMPL; +} + +static HRESULT WINAPI testseek_IsUsingTimeFormat(IMediaSeeking *iface, const GUID *format) +{ + ok(0, "Unexpected call.\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI testseek_SetTimeFormat(IMediaSeeking *iface, const GUID *format) +{ + ok(0, "Unexpected call.\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI testseek_GetDuration(IMediaSeeking *iface, LONGLONG *duration) +{ + ok(0, "Unexpected call.\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI testseek_GetStopPosition(IMediaSeeking *iface, LONGLONG *stop) +{ + if (winetest_debug > 1) trace("GetStopPosition()\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI testseek_GetCurrentPosition(IMediaSeeking *iface, LONGLONG *current) +{ + if (winetest_debug > 1) trace("GetCurrentPosition()\n"); + return 0xdeadbeef; +} + +static HRESULT WINAPI testseek_ConvertTimeFormat(IMediaSeeking *iface, LONGLONG *target, + const GUID *target_format, LONGLONG source, const GUID *source_format) +{ + if (winetest_debug > 1) trace("ConvertTimeFormat()\n"); + ok(IsEqualGUID(source_format, &TIME_FORMAT_MEDIA_TIME), + "Got source format %s.\n", debugstr_guid(source_format)); + ok(!target_format, "Got target format %s.\n", debugstr_guid(target_format)); + *target = source; + return S_OK; +} + +static HRESULT WINAPI testseek_SetPositions(IMediaSeeking *iface, LONGLONG *current, + DWORD current_flags, LONGLONG *stop, DWORD stop_flags ) +{ + if (winetest_debug > 1) trace("SetPositions()\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI testseek_GetPositions(IMediaSeeking *iface, LONGLONG *current, LONGLONG *stop) +{ + ok(0, "Unexpected call.\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI testseek_GetAvailable(IMediaSeeking *iface, LONGLONG *earliest, LONGLONG *latest) +{ + ok(0, "Unexpected call.\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI testseek_SetRate(IMediaSeeking *iface, double rate) +{ + ok(0, "Unexpected call.\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI testseek_GetRate(IMediaSeeking *iface, double *rate) +{ + ok(0, "Unexpected call.\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI testseek_GetPreroll(IMediaSeeking *iface, LONGLONG *preroll) +{ + if (winetest_debug > 1) trace("%p->GetPreroll()\n", iface); + return E_NOTIMPL; +} + +static const IMediaSeekingVtbl testseek_vtbl = +{ + testseek_QueryInterface, + testseek_AddRef, + testseek_Release, + testseek_GetCapabilities, + testseek_CheckCapabilities, + testseek_IsFormatSupported, + testseek_QueryPreferredFormat, + testseek_GetTimeFormat, + testseek_IsUsingTimeFormat, + testseek_SetTimeFormat, + testseek_GetDuration, + testseek_GetStopPosition, + testseek_GetCurrentPosition, + testseek_ConvertTimeFormat, + testseek_SetPositions, + testseek_GetPositions, + testseek_GetAvailable, + testseek_SetRate, + testseek_GetRate, + testseek_GetPreroll, +}; + static void testfilter_init(struct testfilter *filter) { static const GUID clsid = {0xabacab}; strmbase_filter_init(&filter->filter, NULL, &clsid, &testfilter_ops); strmbase_source_init(&filter->source, &filter->filter, L"", &testsource_ops); + filter->IMediaSeeking_iface.lpVtbl = &testseek_vtbl; }
static void test_allocator(IMemInputPin *input) @@ -852,14 +1023,17 @@ static void test_flushing(IPin *pin, IMemInputPin *input, IFilterGraph2 *graph) IMediaControl_Release(control); }
-static void test_sample_time(IPin *pin, IMemInputPin *input, IFilterGraph2 *graph) +static void test_sample_time(IBaseFilter *filter, IPin *pin, IMemInputPin *input, IFilterGraph2 *graph) { IMediaControl *control; + IMediaSeeking *seeking; + REFERENCE_TIME time; OAFilterState state; HANDLE thread; HRESULT hr;
IFilterGraph2_QueryInterface(graph, &IID_IMediaControl, (void **)&control); + IBaseFilter_QueryInterface(filter, &IID_IMediaSeeking, (void **)&seeking);
hr = IMediaControl_Pause(control); ok(hr == S_FALSE, "Got hr %#x.\n", hr); @@ -867,11 +1041,18 @@ static void test_sample_time(IPin *pin, IMemInputPin *input, IFilterGraph2 *grap hr = IMediaControl_GetState(control, 0, &state); ok(hr == VFW_S_STATE_INTERMEDIATE, "Got hr %#x.\n", hr);
+ hr = IMediaSeeking_GetCurrentPosition(seeking, &time); + ok(hr == 0xdeadbeef, "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);
+ hr = IMediaSeeking_GetCurrentPosition(seeking, &time); + ok(hr == S_OK, "Got hr %#x.\n", hr); + ok(time == 10000000, "Got time %s.\n", wine_dbgstr_longlong(time)); + ok(WaitForSingleObject(thread, 100) == WAIT_TIMEOUT, "Thread should block in Receive().\n");
hr = IMediaControl_Run(control); @@ -923,6 +1104,7 @@ static void test_sample_time(IPin *pin, IMemInputPin *input, IFilterGraph2 *grap hr = join_thread(thread); ok(hr == S_OK, "Got hr %#x.\n", hr);
+ IMediaSeeking_Release(seeking); IMediaControl_Release(control); }
@@ -1241,7 +1423,7 @@ static void test_connect_pin(void)
test_filter_state(input, graph); test_flushing(pin, input, graph); - test_sample_time(pin, input, graph); + test_sample_time(filter, pin, input, graph); test_eos(pin, input, graph); test_current_image(filter, input, graph, &vih.bmiHeader);