[PATCH 3/5] quartz/tests: Add some tests for sample presentation time on the VMR9.

Zebediah Figura z.figura12 at gmail.com
Thu Apr 30 21:51:45 CDT 2020


Signed-off-by: Zebediah Figura <z.figura12 at 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);
-- 
2.26.2




More information about the wine-devel mailing list