[PATCH] amstream: Implement SSUPDATE_CONTINUOUS flag in IDirectDrawStreamSample::Update.

Anton Baskanov baskanov at gmail.com
Thu Oct 8 14:02:51 CDT 2020


Signed-off-by: Anton Baskanov <baskanov at gmail.com>
---
 dlls/amstream/ddrawstream.c    | 36 ++++++++++++++---------
 dlls/amstream/tests/amstream.c | 53 ++++++++++++++++++++++++++++++++++
 2 files changed, 75 insertions(+), 14 deletions(-)

diff --git a/dlls/amstream/ddrawstream.c b/dlls/amstream/ddrawstream.c
index 5e6e1555d7c..0e5e54bd80d 100644
--- a/dlls/amstream/ddrawstream.c
+++ b/dlls/amstream/ddrawstream.c
@@ -75,10 +75,12 @@ struct ddraw_sample
     RECT rect;
     STREAM_TIME start_time;
     STREAM_TIME end_time;
+    BOOL continuous_update;
     CONDITION_VARIABLE update_cv;
 
     struct list entry;
     HRESULT update_hr;
+    BOOL busy;
 };
 
 static HRESULT ddrawstreamsample_create(struct ddraw_stream *parent, IDirectDrawSurface *surface,
@@ -86,6 +88,7 @@ static HRESULT ddrawstreamsample_create(struct ddraw_stream *parent, IDirectDraw
 
 static void remove_queued_update(struct ddraw_sample *sample)
 {
+    sample->busy = FALSE;
     list_remove(&sample->entry);
     WakeConditionVariable(&sample->update_cv);
 }
@@ -1348,7 +1351,16 @@ static HRESULT WINAPI ddraw_meminput_Receive(IMemInputPin *iface, IMediaSample *
             sample->update_hr = process_update(sample, top_down_stride, top_down_pointer,
                     start_stream_time, end_stream_time);
 
-            remove_queued_update(sample);
+            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;
         }
@@ -1540,12 +1552,6 @@ static HRESULT WINAPI ddraw_sample_Update(IDirectDrawStreamSample *iface,
         return E_NOTIMPL;
     }
 
-    if (flags & ~SSUPDATE_ASYNC)
-    {
-        FIXME("Unsupported flags %#x.\n", flags);
-        return E_NOTIMPL;
-    }
-
     EnterCriticalSection(&sample->parent->cs);
 
     if (sample->parent->state != State_Running)
@@ -1559,13 +1565,16 @@ static HRESULT WINAPI ddraw_sample_Update(IDirectDrawStreamSample *iface,
         LeaveCriticalSection(&sample->parent->cs);
         return MS_S_ENDOFSTREAM;
     }
-    if (MS_S_PENDING == sample->update_hr)
+    if (sample->busy)
     {
         LeaveCriticalSection(&sample->parent->cs);
         return MS_E_BUSY;
     }
 
-    sample->update_hr = MS_S_PENDING;
+    sample->continuous_update = (flags & SSUPDATE_ASYNC) && (flags & SSUPDATE_CONTINUOUS);
+
+    sample->update_hr = MS_S_NOUPDATE;
+    sample->busy = TRUE;
     list_add_tail(&sample->parent->update_queue, &sample->entry);
     WakeConditionVariable(&sample->parent->update_queued_cv);
 
@@ -1575,7 +1584,7 @@ static HRESULT WINAPI ddraw_sample_Update(IDirectDrawStreamSample *iface,
         return MS_S_PENDING;
     }
 
-    while (sample->update_hr == MS_S_PENDING)
+    while (sample->busy)
         SleepConditionVariableCS(&sample->update_cv, &sample->parent->cs, INFINITE);
 
     LeaveCriticalSection(&sample->parent->cs);
@@ -1592,18 +1601,17 @@ static HRESULT WINAPI ddraw_sample_CompletionStatus(IDirectDrawStreamSample *ifa
 
     EnterCriticalSection(&sample->parent->cs);
 
-    if (sample->update_hr == MS_S_PENDING)
+    if (sample->busy)
     {
         if (flags & (COMPSTAT_NOUPDATEOK | COMPSTAT_ABORT))
         {
-            sample->update_hr = MS_S_NOUPDATE;
             remove_queued_update(sample);
         }
         else if (flags & COMPSTAT_WAIT)
         {
             DWORD start_time = GetTickCount();
             DWORD elapsed = 0;
-            while (sample->update_hr == MS_S_PENDING && elapsed < milliseconds)
+            while (sample->busy && elapsed < milliseconds)
             {
                 DWORD sleep_time = milliseconds - elapsed;
                 if (!SleepConditionVariableCS(&sample->update_cv, &sample->parent->cs, sleep_time))
@@ -1613,7 +1621,7 @@ static HRESULT WINAPI ddraw_sample_CompletionStatus(IDirectDrawStreamSample *ifa
         }
     }
 
-    hr = sample->update_hr;
+    hr = sample->busy ? MS_S_PENDING : sample->update_hr;
 
     LeaveCriticalSection(&sample->parent->cs);
 
diff --git a/dlls/amstream/tests/amstream.c b/dlls/amstream/tests/amstream.c
index 9dda5882a4f..6e6f7483b49 100644
--- a/dlls/amstream/tests/amstream.c
+++ b/dlls/amstream/tests/amstream.c
@@ -7665,6 +7665,59 @@ static void test_ddrawstreamsample_completion_status(void)
     hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_RUN);
     ok(hr == S_OK, "Got hr %#x.\n", hr);
 
+    hr = IDirectDrawStreamSample_Update(stream_sample1, SSUPDATE_ASYNC | SSUPDATE_CONTINUOUS, NULL, NULL, 0);
+    ok(hr == MS_S_PENDING, "Got hr %#x.\n", hr);
+
+    hr = IDirectDrawStreamSample_CompletionStatus(stream_sample1, COMPSTAT_NOUPDATEOK, 0);
+    ok(hr == MS_S_NOUPDATE, "Got hr %#x.\n", hr);
+
+    hr = IDirectDrawStreamSample_Update(stream_sample1, SSUPDATE_ASYNC | SSUPDATE_CONTINUOUS, NULL, NULL, 0);
+    ok(hr == MS_S_PENDING, "Got hr %#x.\n", hr);
+
+    hr = IDirectDrawStreamSample_Update(stream_sample2, SSUPDATE_ASYNC, NULL, NULL, 0);
+    ok(hr == MS_S_PENDING, "Got hr %#x.\n", hr);
+
+    hr = IDirectDrawStreamSample_CompletionStatus(stream_sample1, 0, 0);
+    ok(hr == MS_S_PENDING, "Got hr %#x.\n", hr);
+
+    media_sample = ammediastream_allocate_sample(&source, test_data, sizeof(test_data));
+    hr = IMemInputPin_Receive(source.source.pMemInputPin, media_sample);
+    ok(hr == S_OK, "Got hr %#x.\n", hr);
+    ref = IMediaSample_Release(media_sample);
+    ok(!ref, "Got outstanding refcount %d.\n", ref);
+
+    hr = IDirectDrawStreamSample_CompletionStatus(stream_sample1, 0, 0);
+    ok(hr == MS_S_PENDING, "Got hr %#x.\n", hr);
+
+    media_sample = ammediastream_allocate_sample(&source, test_data, sizeof(test_data));
+    hr = IMemInputPin_Receive(source.source.pMemInputPin, media_sample);
+    ok(hr == S_OK, "Got hr %#x.\n", hr);
+    ref = IMediaSample_Release(media_sample);
+    ok(!ref, "Got outstanding refcount %d.\n", ref);
+
+    hr = IDirectDrawStreamSample_CompletionStatus(stream_sample1, 0, 0);
+    ok(hr == MS_S_PENDING, "Got hr %#x.\n", hr);
+
+    hr = IDirectDrawStreamSample_CompletionStatus(stream_sample2, 0, 0);
+    ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+    hr = IDirectDrawStreamSample_CompletionStatus(stream_sample1, COMPSTAT_NOUPDATEOK, 0);
+    ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+    hr = IDirectDrawStreamSample_Update(stream_sample1, SSUPDATE_ASYNC | SSUPDATE_CONTINUOUS, NULL, NULL, 0);
+    ok(hr == MS_S_PENDING, "Got hr %#x.\n", hr);
+
+    hr = IPin_EndOfStream(pin);
+    ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+    hr = IDirectDrawStreamSample_CompletionStatus(stream_sample1, 0, 0);
+    ok(hr == MS_S_ENDOFSTREAM, "Got hr %#x.\n", hr);
+
+    hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_STOP);
+    ok(hr == S_OK, "Got hr %#x.\n", hr);
+    hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_RUN);
+    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);
 
-- 
2.17.1




More information about the wine-devel mailing list