On 10/22/20 2:06 PM, Anton Baskanov wrote:
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);
This implies that if you:
* queue sample 1 * queue sample 2 * call Receive * remove sample 1 * signal presentation time
that Receive() won't return, and moreover that if you
* queue sample 1 * queue sample 2 * call Receive * remove sample 1 * queue sample 1 * signal presentation time
that it will return (and fill sample 1). Which seems plausible, but also not the simplest way to implement this behaviour—that seems to me to be to just wait for presentation time and then pick the first sample queued if there is one.
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);
Mildly weird to pass INFINITE without COMPSTAT_WAIT.
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);