[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