[PATCH 5/5] amstream: Wait for presentation time in AMDirectDrawStream::Receive.

Anton Baskanov baskanov at gmail.com
Thu Oct 22 14:06:16 CDT 2020


Signed-off-by: Anton Baskanov <baskanov at gmail.com>
---
 dlls/amstream/ddrawstream.c    |  44 ++++++++---
 dlls/amstream/tests/amstream.c | 137 +++++++++++++++++++++++++++++++++
 2 files changed, 172 insertions(+), 9 deletions(-)

diff --git a/dlls/amstream/ddrawstream.c b/dlls/amstream/ddrawstream.c
index 190034fa008..da1d65ff170 100644
--- a/dlls/amstream/ddrawstream.c
+++ b/dlls/amstream/ddrawstream.c
@@ -1344,25 +1344,51 @@ static HRESULT WINAPI ddraw_meminput_Receive(IMemInputPin *iface, IMediaSample *
             LeaveCriticalSection(&stream->cs);
             return S_FALSE;
         }
-        if (!list_empty(&stream->update_queue))
+        while (!list_empty(&stream->update_queue))
         {
             struct ddraw_sample *sample = LIST_ENTRY(list_head(&stream->update_queue), struct ddraw_sample, entry);
+            struct ddraw_sample *sample2;
+            IMediaStreamFilter *filter;
+            HRESULT update_hr;
 
-            sample->update_hr = process_update(sample, top_down_stride, top_down_pointer,
+            update_hr = process_update(sample, top_down_stride, top_down_pointer,
                     start_stream_time, end_stream_time);
 
-            if (sample->continuous_update && SUCCEEDED(sample->update_hr))
+            filter = stream->filter;
+
+            LeaveCriticalSection(&stream->cs);
+            IMediaStreamFilter_WaitUntil(filter, start_time);
+            EnterCriticalSection(&stream->cs);
+
+            if (stream->state == State_Stopped)
             {
-                list_remove(&sample->entry);
-                list_add_tail(&sample->parent->update_queue, &sample->entry);
+                LeaveCriticalSection(&stream->cs);
+                return S_OK;
             }
-            else
+            if (stream->flushing)
             {
-                remove_queued_update(sample);
+                LeaveCriticalSection(&stream->cs);
+                return S_FALSE;
             }
 
-            LeaveCriticalSection(&stream->cs);
-            return S_OK;
+            LIST_FOR_EACH_ENTRY(sample2, &stream->update_queue, struct ddraw_sample, entry)
+            {
+                if (sample2 == sample)
+                {
+                    sample->update_hr = update_hr;
+                    if (sample->continuous_update && SUCCEEDED(sample->update_hr))
+                    {
+                        list_remove(&sample->entry);
+                        list_add_tail(&sample->parent->update_queue, &sample->entry);
+                    }
+                    else
+                    {
+                        remove_queued_update(sample);
+                    }
+                    LeaveCriticalSection(&stream->cs);
+                    return S_OK;
+                }
+            }
         }
 
         SleepConditionVariableCS(&stream->update_queued_cv, &stream->cs, INFINITE);
diff --git a/dlls/amstream/tests/amstream.c b/dlls/amstream/tests/amstream.c
index d89f1ecb109..50e75fd0395 100644
--- a/dlls/amstream/tests/amstream.c
+++ b/dlls/amstream/tests/amstream.c
@@ -7861,9 +7861,11 @@ static void test_ddrawstreamsample_completion_status(void)
     IDirectDrawStreamSample *stream_sample1;
     IDirectDrawStreamSample *stream_sample2;
     IDirectDrawMediaStream *ddraw_stream;
+    struct advise_time_cookie cookie = { 0 };
     IMediaSample *media_sample;
     IMediaFilter *media_filter;
     struct testfilter source;
+    struct testclock clock;
     VIDEOINFO video_info;
     IGraphBuilder *graph;
     IMediaStream *stream;
@@ -7889,6 +7891,8 @@ static void test_ddrawstreamsample_completion_status(void)
     testfilter_init(&source);
     hr = IGraphBuilder_AddFilter(graph, &source.filter.IBaseFilter_iface, NULL);
     ok(hr == S_OK, "Got hr %#x.\n", hr);
+    testclock_init(&clock);
+    cookie.advise_time_called_event = CreateEventW(NULL, FALSE, FALSE, NULL);
 
     hr = IMediaFilter_SetSyncSource(media_filter, NULL);
     ok(hr == S_OK, "Got hr %#x.\n", hr);
@@ -8246,9 +8250,142 @@ static void test_ddrawstreamsample_completion_status(void)
     hr = IDirectDrawStreamSample_CompletionStatus(stream_sample1, COMPSTAT_WAIT, INFINITE);
     ok(hr == S_OK, "Got hr %#x.\n", hr);
 
+    hr = IMediaFilter_SetSyncSource(media_filter, &clock.IReferenceClock_iface);
+    ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+    hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_RUN);
+    ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+    clock.advise_time_cookie = &cookie;
+
+    hr = IDirectDrawStreamSample_Update(stream_sample1, SSUPDATE_ASYNC, NULL, NULL, 0);
+    ok(hr == MS_S_PENDING, "Got hr %#x.\n", hr);
+
+    media_sample = ammediastream_allocate_sample(&source, test_data, sizeof(test_data));
+
+    ammediastream_mem_input_pin = source.source.pMemInputPin;
+    ammediastream_media_sample = media_sample;
+    ammediastream_sleep_time = 0;
+    ammediastream_expected_hr = S_OK;
+    thread = CreateThread(NULL, 0, ammediastream_receive, NULL, 0, NULL);
+    ok(WaitForSingleObject(thread, 100) == WAIT_TIMEOUT, "Receive returned prematurely.\n");
+
+    hr = IDirectDrawStreamSample_CompletionStatus(stream_sample1, 0, INFINITE);
+    ok(hr == MS_S_PENDING, "Got hr %#x.\n", hr);
+
+    SetEvent(cookie.event);
+
+    ok(!WaitForSingleObject(thread, 2000), "Wait timed out.\n");
+    CloseHandle(thread);
+
+    ref = IMediaSample_Release(media_sample);
+    ok(!ref, "Got outstanding refcount %d.\n", ref);
+
+    hr = IDirectDrawStreamSample_CompletionStatus(stream_sample1, 0, INFINITE);
+    ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+    hr = IDirectDrawStreamSample_Update(stream_sample1, SSUPDATE_ASYNC, NULL, NULL, 0);
+    ok(hr == MS_S_PENDING, "Got hr %#x.\n", hr);
+
+    media_sample = ammediastream_allocate_sample(&source, test_data, sizeof(test_data));
+
+    ammediastream_mem_input_pin = source.source.pMemInputPin;
+    ammediastream_media_sample = media_sample;
+    ammediastream_sleep_time = 0;
+    ammediastream_expected_hr = S_OK;
+    thread = CreateThread(NULL, 0, ammediastream_receive, NULL, 0, NULL);
+    ok(WaitForSingleObject(thread, 100) == WAIT_TIMEOUT, "Receive returned prematurely.\n");
+
+    hr = IDirectDrawStreamSample_CompletionStatus(stream_sample1, COMPSTAT_NOUPDATEOK, INFINITE);
+    ok(hr == MS_S_NOUPDATE, "Got hr %#x.\n", hr);
+
+    ok(WaitForSingleObject(thread, 100) == WAIT_TIMEOUT, "Receive returned prematurely.\n");
+
+    SetEvent(cookie.event);
+
+    ok(WaitForSingleObject(thread, 100) == WAIT_TIMEOUT, "Receive returned prematurely.\n");
+
+    hr = IDirectDrawStreamSample_Update(stream_sample1, SSUPDATE_ASYNC, NULL, NULL, 0);
+    ok(hr == MS_S_PENDING, "Got hr %#x.\n", hr);
+
+    ok(WaitForSingleObject(thread, 100) == WAIT_TIMEOUT, "Receive returned prematurely.\n");
+
+    SetEvent(cookie.event);
+
+    ok(!WaitForSingleObject(thread, 2000), "Wait timed out.\n");
+    CloseHandle(thread);
+
+    hr = IDirectDrawStreamSample_CompletionStatus(stream_sample1, 0, INFINITE);
+    ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+    ref = IMediaSample_Release(media_sample);
+    ok(!ref, "Got outstanding refcount %d.\n", ref);
+
+    hr = IDirectDrawStreamSample_Update(stream_sample1, SSUPDATE_ASYNC, NULL, NULL, 0);
+    ok(hr == MS_S_PENDING, "Got hr %#x.\n", hr);
+
+    media_sample = ammediastream_allocate_sample(&source, test_data, sizeof(test_data));
+
+    ammediastream_mem_input_pin = source.source.pMemInputPin;
+    ammediastream_media_sample = media_sample;
+    ammediastream_sleep_time = 0;
+    ammediastream_expected_hr = S_OK;
+    thread = CreateThread(NULL, 0, ammediastream_receive, NULL, 0, NULL);
+    ok(WaitForSingleObject(thread, 100) == WAIT_TIMEOUT, "Receive returned prematurely.\n");
+
+    hr = IDirectDrawStreamSample_CompletionStatus(stream_sample1, COMPSTAT_ABORT, INFINITE);
+    ok(hr == MS_S_NOUPDATE, "Got hr %#x.\n", hr);
+
+    ok(WaitForSingleObject(thread, 100) == WAIT_TIMEOUT, "Receive returned prematurely.\n");
+
+    SetEvent(cookie.event);
+
+    ok(WaitForSingleObject(thread, 100) == WAIT_TIMEOUT, "Receive returned prematurely.\n");
+
+    hr = IDirectDrawStreamSample_Update(stream_sample1, SSUPDATE_ASYNC, NULL, NULL, 0);
+    ok(hr == MS_S_PENDING, "Got hr %#x.\n", hr);
+
+    ok(WaitForSingleObject(thread, 100) == WAIT_TIMEOUT, "Receive returned prematurely.\n");
+
+    SetEvent(cookie.event);
+
+    ok(!WaitForSingleObject(thread, 2000), "Wait timed out.\n");
+    CloseHandle(thread);
+
+    hr = IDirectDrawStreamSample_CompletionStatus(stream_sample1, 0, INFINITE);
+    ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+    ref = IMediaSample_Release(media_sample);
+    ok(!ref, "Got outstanding refcount %d.\n", ref);
+
+    hr = IDirectDrawStreamSample_Update(stream_sample1, SSUPDATE_ASYNC, NULL, NULL, 0);
+    ok(hr == MS_S_PENDING, "Got hr %#x.\n", hr);
+
+    media_sample = ammediastream_allocate_sample(&source, test_data, sizeof(test_data));
+
+    ammediastream_mem_input_pin = source.source.pMemInputPin;
+    ammediastream_media_sample = media_sample;
+    ammediastream_sleep_time = 0;
+    ammediastream_expected_hr = S_OK;
+    thread = CreateThread(NULL, 0, ammediastream_receive, NULL, 0, NULL);
+    ok(WaitForSingleObject(thread, 100) == WAIT_TIMEOUT, "Receive returned prematurely.\n");
+
+    hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_STOP);
+    ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+    ok(!WaitForSingleObject(thread, 2000), "Wait timed out.\n");
+    CloseHandle(thread);
+
+    ref = IMediaSample_Release(media_sample);
+    ok(!ref, "Got outstanding refcount %d.\n", ref);
+
+    hr = IDirectDrawStreamSample_CompletionStatus(stream_sample1, 0, INFINITE);
+    ok(hr == MS_S_PENDING, "Got hr %#x.\n", hr);
+
     IGraphBuilder_Disconnect(graph, pin);
     IGraphBuilder_Disconnect(graph, &source.source.pin.IPin_iface);
 
+    CloseHandle(cookie.advise_time_called_event);
     ref = IDirectDrawStreamSample_Release(stream_sample1);
     ok(!ref, "Got outstanding refcount %d.\n", ref);
     ref = IDirectDrawStreamSample_Release(stream_sample2);
-- 
2.17.1




More information about the wine-devel mailing list