Signed-off-by: Anton Baskanov baskanov@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);