Signed-off-by: Anton Baskanov <baskanov(a)gmail.com> --- dlls/amstream/filter.c | 39 +++++++++++++++++++++++++++++++-- dlls/amstream/tests/amstream.c | 40 +++++++++++++++++----------------- 2 files changed, 57 insertions(+), 22 deletions(-) diff --git a/dlls/amstream/filter.c b/dlls/amstream/filter.c index 6fac4b9b4b7..2575f82aeef 100644 --- a/dlls/amstream/filter.c +++ b/dlls/amstream/filter.c @@ -182,6 +182,7 @@ struct filter /* Protected by stream_cs. */ struct list free_events; struct list used_events; + ULONG eos_count; }; struct event @@ -271,6 +272,22 @@ static HRESULT WINAPI filter_GetClassID(IMediaStreamFilter *iface, CLSID *clsid) return S_OK; } +static void send_ec_complete(struct filter *filter) +{ + IMediaEventSink *event_sink; + + if (!filter->graph) + return; + + if (FAILED(IFilterGraph_QueryInterface(filter->graph, &IID_IMediaEventSink, (void **)&event_sink))) + return; + + IMediaEventSink_Notify(event_sink, EC_COMPLETE, S_OK, + (LONG_PTR)&filter->IMediaStreamFilter_iface); + + IMediaEventSink_Release(event_sink); +} + static HRESULT WINAPI filter_Stop(IMediaStreamFilter *iface) { struct filter *filter = impl_from_IMediaStreamFilter(iface); @@ -293,6 +310,7 @@ static HRESULT WINAPI filter_Stop(IMediaStreamFilter *iface) EnterCriticalSection(&filter->stream_cs); filter->state = State_Stopped; + filter->eos_count = 0; LIST_FOR_EACH_ENTRY(event, &filter->used_events, struct event, entry) { @@ -354,6 +372,9 @@ static HRESULT WINAPI filter_Run(IMediaStreamFilter *iface, REFERENCE_TIME start EnterCriticalSection(&filter->stream_cs); + if (filter->seekable_stream && filter->eos_count == filter->nb_streams) + send_ec_complete(filter); + filter->state = State_Running; filter->start_time = start; @@ -809,6 +830,9 @@ static HRESULT WINAPI filter_Flush(IMediaStreamFilter *iface, BOOL cancel_eos) } } + if (cancel_eos) + --filter->eos_count; + LeaveCriticalSection(&filter->stream_cs); return S_OK; @@ -816,9 +840,20 @@ static HRESULT WINAPI filter_Flush(IMediaStreamFilter *iface, BOOL cancel_eos) static HRESULT WINAPI filter_EndOfStream(IMediaStreamFilter *iface) { - FIXME("(%p)->(): Stub!\n", iface); + struct filter *filter = impl_from_IMediaStreamFilter(iface); - return E_NOTIMPL; + TRACE("filter %p.\n", filter); + + EnterCriticalSection(&filter->stream_cs); + + ++filter->eos_count; + if (filter->state == State_Running && filter->seekable_stream && + filter->eos_count == filter->nb_streams) + send_ec_complete(filter); + + LeaveCriticalSection(&filter->stream_cs); + + return S_OK; } static const IMediaStreamFilterVtbl filter_vtbl = diff --git a/dlls/amstream/tests/amstream.c b/dlls/amstream/tests/amstream.c index 39d65ebaaad..5bdbd8b0bd0 100644 --- a/dlls/amstream/tests/amstream.c +++ b/dlls/amstream/tests/amstream.c @@ -6953,9 +6953,9 @@ static void test_mediastreamfilter_end_of_stream(void) graph.got_notify = 0; hr = IMediaStreamFilter_EndOfStream(filter); - todo_wine ok(hr == S_OK, "Got hr %#x.\n", hr); + ok(hr == S_OK, "Got hr %#x.\n", hr); hr = IMediaStreamFilter_EndOfStream(filter); - todo_wine ok(hr == S_OK, "Got hr %#x.\n", hr); + ok(hr == S_OK, "Got hr %#x.\n", hr); ok(graph.got_notify == 0, "Got %d calls to IMediaEventSink::Notify().\n", graph.got_notify); @@ -6972,9 +6972,9 @@ static void test_mediastreamfilter_end_of_stream(void) graph.got_notify = 0; hr = IMediaStreamFilter_EndOfStream(filter); - todo_wine ok(hr == S_OK, "Got hr %#x.\n", hr); + ok(hr == S_OK, "Got hr %#x.\n", hr); hr = IMediaStreamFilter_EndOfStream(filter); - todo_wine ok(hr == S_OK, "Got hr %#x.\n", hr); + ok(hr == S_OK, "Got hr %#x.\n", hr); ok(graph.got_notify == 0, "Got %d calls to IMediaEventSink::Notify().\n", graph.got_notify); @@ -6993,14 +6993,14 @@ static void test_mediastreamfilter_end_of_stream(void) graph.got_notify = 0; hr = IMediaStreamFilter_EndOfStream(filter); - todo_wine ok(hr == S_OK, "Got hr %#x.\n", hr); + ok(hr == S_OK, "Got hr %#x.\n", hr); ok(graph.got_notify == 0, "Got %d calls to IMediaEventSink::Notify().\n", graph.got_notify); hr = IMediaStreamFilter_EndOfStream(filter); - todo_wine ok(hr == S_OK, "Got hr %#x.\n", hr); + ok(hr == S_OK, "Got hr %#x.\n", hr); - todo_wine ok(graph.got_notify == 1, "Got %d calls to IMediaEventSink::Notify().\n", graph.got_notify); + ok(graph.got_notify == 1, "Got %d calls to IMediaEventSink::Notify().\n", graph.got_notify); hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_STOP); ok(hr == S_OK, "Got hr %#x.\n", hr); @@ -7010,9 +7010,9 @@ static void test_mediastreamfilter_end_of_stream(void) graph.got_notify = 0; hr = IMediaStreamFilter_EndOfStream(filter); - todo_wine ok(hr == S_OK, "Got hr %#x.\n", hr); + ok(hr == S_OK, "Got hr %#x.\n", hr); hr = IMediaStreamFilter_EndOfStream(filter); - todo_wine ok(hr == S_OK, "Got hr %#x.\n", hr); + ok(hr == S_OK, "Got hr %#x.\n", hr); ok(graph.got_notify == 0, "Got %d calls to IMediaEventSink::Notify().\n", graph.got_notify); @@ -7024,7 +7024,7 @@ static void test_mediastreamfilter_end_of_stream(void) hr = IMediaControl_Run(media_control); ok(hr == S_OK, "Got hr %#x.\n", hr); - todo_wine ok(graph.got_notify == 1, "Got %d calls to IMediaEventSink::Notify().\n", graph.got_notify); + ok(graph.got_notify == 1, "Got %d calls to IMediaEventSink::Notify().\n", graph.got_notify); hr = IMediaControl_Stop(media_control); ok(hr == S_OK, "Got hr %#x.\n", hr); @@ -7036,7 +7036,7 @@ static void test_mediastreamfilter_end_of_stream(void) graph.got_notify = 0; hr = IMediaStreamFilter_EndOfStream(filter); - todo_wine ok(hr == S_OK, "Got hr %#x.\n", hr); + ok(hr == S_OK, "Got hr %#x.\n", hr); hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_STOP); ok(hr == S_OK, "Got hr %#x.\n", hr); @@ -7044,7 +7044,7 @@ static void test_mediastreamfilter_end_of_stream(void) ok(hr == S_OK, "Got hr %#x.\n", hr); hr = IMediaStreamFilter_EndOfStream(filter); - todo_wine ok(hr == S_OK, "Got hr %#x.\n", hr); + ok(hr == S_OK, "Got hr %#x.\n", hr); ok(graph.got_notify == 0, "Got %d calls to IMediaEventSink::Notify().\n", graph.got_notify); @@ -7058,7 +7058,7 @@ static void test_mediastreamfilter_end_of_stream(void) graph.got_notify = 0; hr = IMediaStreamFilter_EndOfStream(filter); - todo_wine ok(hr == S_OK, "Got hr %#x.\n", hr); + ok(hr == S_OK, "Got hr %#x.\n", hr); hr = IMediaControl_Pause(media_control); ok(hr == S_OK, "Got hr %#x.\n", hr); @@ -7066,9 +7066,9 @@ static void test_mediastreamfilter_end_of_stream(void) ok(hr == S_OK, "Got hr %#x.\n", hr); hr = IMediaStreamFilter_EndOfStream(filter); - todo_wine ok(hr == S_OK, "Got hr %#x.\n", hr); + ok(hr == S_OK, "Got hr %#x.\n", hr); - todo_wine ok(graph.got_notify == 1, "Got %d calls to IMediaEventSink::Notify().\n", graph.got_notify); + ok(graph.got_notify == 1, "Got %d calls to IMediaEventSink::Notify().\n", graph.got_notify); hr = IMediaControl_Stop(media_control); ok(hr == S_OK, "Got hr %#x.\n", hr); @@ -7080,12 +7080,12 @@ static void test_mediastreamfilter_end_of_stream(void) graph.got_notify = 0; hr = IMediaStreamFilter_EndOfStream(filter); - todo_wine ok(hr == S_OK, "Got hr %#x.\n", hr); + ok(hr == S_OK, "Got hr %#x.\n", hr); hr = IMediaStreamFilter_Flush(filter, TRUE); hr = IMediaStreamFilter_EndOfStream(filter); - todo_wine ok(hr == S_OK, "Got hr %#x.\n", hr); + ok(hr == S_OK, "Got hr %#x.\n", hr); ok(graph.got_notify == 0, "Got %d calls to IMediaEventSink::Notify().\n", graph.got_notify); @@ -7099,14 +7099,14 @@ static void test_mediastreamfilter_end_of_stream(void) graph.got_notify = 0; hr = IMediaStreamFilter_EndOfStream(filter); - todo_wine ok(hr == S_OK, "Got hr %#x.\n", hr); + ok(hr == S_OK, "Got hr %#x.\n", hr); hr = IMediaStreamFilter_Flush(filter, FALSE); hr = IMediaStreamFilter_EndOfStream(filter); - todo_wine ok(hr == S_OK, "Got hr %#x.\n", hr); + ok(hr == S_OK, "Got hr %#x.\n", hr); - todo_wine ok(graph.got_notify == 1, "Got %d calls to IMediaEventSink::Notify().\n", graph.got_notify); + ok(graph.got_notify == 1, "Got %d calls to IMediaEventSink::Notify().\n", graph.got_notify); hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_STOP); ok(hr == S_OK, "Got hr %#x.\n", hr); -- 2.25.1