Signed-off-by: Anton Baskanov baskanov@gmail.com --- dlls/amstream/tests/amstream.c | 233 ++++++++++++++++++++++++++++++++- 1 file changed, 230 insertions(+), 3 deletions(-)
diff --git a/dlls/amstream/tests/amstream.c b/dlls/amstream/tests/amstream.c index 9cefec12442..2f7854606f4 100644 --- a/dlls/amstream/tests/amstream.c +++ b/dlls/amstream/tests/amstream.c @@ -1313,6 +1313,208 @@ static const IMediaSeekingVtbl testsource_seeking_vtbl = testsource_seeking_GetPreroll, };
+struct testmediastreamfilter +{ + IMediaStreamFilter IMediaStreamFilter_iface; + LONG refcount; + unsigned int got_end_of_stream; +}; + +static inline struct testmediastreamfilter *impl_from_IMediaStreamFilter(IMediaStreamFilter *iface) +{ + return CONTAINING_RECORD(iface, struct testmediastreamfilter, IMediaStreamFilter_iface); +} + +static HRESULT WINAPI testmediastreamfilter_QueryInterface(IMediaStreamFilter *iface, REFIID iid, void **out) +{ + if (IsEqualGUID(iid, &IID_IUnknown) + || IsEqualGUID(iid, &IID_IPersist) + || IsEqualGUID(iid, &IID_IMediaFilter) + || IsEqualGUID(iid, &IID_IBaseFilter) + || IsEqualGUID(iid, &IID_IMediaStreamFilter)) + { + IMediaStreamFilter_AddRef(iface); + *out = iface; + return S_OK; + } + + ok(0, "Unexpected interface %s.\n", wine_dbgstr_guid(iid)); + return E_NOINTERFACE; +} + +static ULONG WINAPI testmediastreamfilter_AddRef(IMediaStreamFilter *iface) +{ + struct testmediastreamfilter *filter = impl_from_IMediaStreamFilter(iface); + return InterlockedIncrement(&filter->refcount); +} + +static ULONG WINAPI testmediastreamfilter_Release(IMediaStreamFilter *iface) +{ + struct testmediastreamfilter *filter = impl_from_IMediaStreamFilter(iface); + return InterlockedDecrement(&filter->refcount); +} + +static HRESULT WINAPI testmediastreamfilter_GetClassID(IMediaStreamFilter *iface, CLSID *clsid) +{ + ok(0, "Unexpected call.\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI testmediastreamfilter_Stop(IMediaStreamFilter *iface) +{ + ok(0, "Unexpected call.\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI testmediastreamfilter_Pause(IMediaStreamFilter *iface) +{ + ok(0, "Unexpected call.\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI testmediastreamfilter_Run(IMediaStreamFilter *iface, REFERENCE_TIME start) +{ + ok(0, "Unexpected call.\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI testmediastreamfilter_GetState(IMediaStreamFilter *iface, DWORD timeout, FILTER_STATE *state) +{ + ok(0, "Unexpected call.\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI testmediastreamfilter_SetSyncSource(IMediaStreamFilter *iface, IReferenceClock *clock) +{ + ok(0, "Unexpected call.\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI testmediastreamfilter_GetSyncSource(IMediaStreamFilter *iface, IReferenceClock **clock) +{ + ok(0, "Unexpected call.\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI testmediastreamfilter_EnumPins(IMediaStreamFilter *iface, IEnumPins **enum_pins) +{ + ok(0, "Unexpected call.\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI testmediastreamfilter_FindPin(IMediaStreamFilter *iface, const WCHAR *id, IPin **pin) +{ + ok(0, "Unexpected call.\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI testmediastreamfilter_QueryFilterInfo(IMediaStreamFilter *iface, FILTER_INFO *pInfo) +{ + ok(0, "Unexpected call.\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI testmediastreamfilter_JoinFilterGraph(IMediaStreamFilter *iface, IFilterGraph *graph, const WCHAR *name) +{ + ok(0, "Unexpected call.\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI testmediastreamfilter_QueryVendorInfo(IMediaStreamFilter *iface, WCHAR **vendor_info) +{ + ok(0, "Unexpected call.\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI testmediastreamfilter_AddMediaStream(IMediaStreamFilter *iface, IAMMediaStream *stream) +{ + ok(0, "Unexpected call.\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI testmediastreamfilter_GetMediaStream(IMediaStreamFilter *iface, const MSPID *purpose_id, IMediaStream **stream) +{ + ok(0, "Unexpected call.\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI testmediastreamfilter_EnumMediaStreams(IMediaStreamFilter *iface, LONG index, IMediaStream **stream) +{ + ok(0, "Unexpected call.\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI testmediastreamfilter_SupportSeeking(IMediaStreamFilter *iface, BOOL renderer) +{ + ok(0, "Unexpected call.\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI testmediastreamfilter_ReferenceTimeToStreamTime(IMediaStreamFilter *iface, REFERENCE_TIME *time) +{ + ok(0, "Unexpected call.\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI testmediastreamfilter_GetCurrentStreamTime(IMediaStreamFilter *iface, REFERENCE_TIME *time) +{ + ok(0, "Unexpected call.\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI testmediastreamfilter_WaitUntil(IMediaStreamFilter *iface, REFERENCE_TIME time) +{ + ok(0, "Unexpected call.\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI testmediastreamfilter_Flush(IMediaStreamFilter *iface, BOOL cancel_eos) +{ + ok(0, "Unexpected call.\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI testmediastreamfilter_EndOfStream(IMediaStreamFilter *iface) +{ + struct testmediastreamfilter *filter = impl_from_IMediaStreamFilter(iface); + ++filter->got_end_of_stream; + return S_OK; +} + +static IMediaStreamFilterVtbl testmediastreamfilter_vtbl = +{ + testmediastreamfilter_QueryInterface, + testmediastreamfilter_AddRef, + testmediastreamfilter_Release, + testmediastreamfilter_GetClassID, + testmediastreamfilter_Stop, + testmediastreamfilter_Pause, + testmediastreamfilter_Run, + testmediastreamfilter_GetState, + testmediastreamfilter_SetSyncSource, + testmediastreamfilter_GetSyncSource, + testmediastreamfilter_EnumPins, + testmediastreamfilter_FindPin, + testmediastreamfilter_QueryFilterInfo, + testmediastreamfilter_JoinFilterGraph, + testmediastreamfilter_QueryVendorInfo, + testmediastreamfilter_AddMediaStream, + testmediastreamfilter_GetMediaStream, + testmediastreamfilter_EnumMediaStreams, + testmediastreamfilter_SupportSeeking, + testmediastreamfilter_ReferenceTimeToStreamTime, + testmediastreamfilter_GetCurrentStreamTime, + testmediastreamfilter_WaitUntil, + testmediastreamfilter_Flush, + testmediastreamfilter_EndOfStream, +}; + +static void testmediastreamfilter_init(struct testmediastreamfilter *filter) +{ + memset(filter, 0, sizeof(*filter)); + filter->IMediaStreamFilter_iface.lpVtbl = &testmediastreamfilter_vtbl; +} + #define check_get_stream(a,b,c,d) check_get_stream_(__LINE__,a,b,c,d) static void check_get_stream_(int line, IAMMultiMediaStream *mmstream, IMediaStreamFilter *filter, const GUID *mspid, IMediaStream *expect) @@ -6065,9 +6267,11 @@ static void test_ammediastream_set_state(void) check_ammediastream_set_state(&MSPID_PrimaryVideo); }
-static void check_ammediastream_end_of_stream(const MSPID *id, const AM_MEDIA_TYPE *mt) +static void check_ammediastream_end_of_stream(const CLSID *clsid, const MSPID *id, const AM_MEDIA_TYPE *mt) { IAMMultiMediaStream *mmstream = create_ammultimediastream(); + struct testmediastreamfilter filter; + IAMMediaStream *am_stream; struct testfilter source; IGraphBuilder *graph; IMediaStream *stream; @@ -6122,12 +6326,35 @@ static void check_ammediastream_end_of_stream(const MSPID *id, const AM_MEDIA_TY IPin_Release(pin); ref = IMediaStream_Release(stream); ok(!ref, "Got outstanding refcount %d.\n", ref); + + testmediastreamfilter_init(&filter); + + hr = CoCreateInstance(clsid, NULL, CLSCTX_INPROC_SERVER, &IID_IAMMediaStream, (void **)&am_stream); + ok(hr == S_OK, "Got hr %#x.\n", hr); + hr = IAMMediaStream_QueryInterface(am_stream, &IID_IPin, (void **)&pin); + ok(hr == S_OK, "Got hr %#x.\n", hr); + hr = IAMMediaStream_JoinFilter(am_stream, &filter.IMediaStreamFilter_iface); + ok(hr == S_OK, "Got hr %#x.\n", hr); + + filter.got_end_of_stream = 0; + + hr = IPin_EndOfStream(pin); + ok(hr == S_OK, "Got hr %#x.\n", hr); + todo_wine ok(filter.got_end_of_stream == 1, "Got %d calls to IMediaStreamFilter::EndOfStream().\n", filter.got_end_of_stream); + + hr = IPin_EndOfStream(pin); + ok(hr == E_FAIL, "Got hr %#x.\n", hr); + todo_wine ok(filter.got_end_of_stream == 1, "Got %d calls to IMediaStreamFilter::EndOfStream().\n", filter.got_end_of_stream); + + IPin_Release(pin); + ref = IAMMediaStream_Release(am_stream); + ok(!ref, "Got outstanding refcount %d.\n", ref); }
static void test_ammediastream_end_of_stream(void) { - check_ammediastream_end_of_stream(&MSPID_PrimaryAudio, &audio_mt); - check_ammediastream_end_of_stream(&MSPID_PrimaryVideo, &rgb32_mt); + check_ammediastream_end_of_stream(&CLSID_AMAudioStream, &MSPID_PrimaryAudio, &audio_mt); + check_ammediastream_end_of_stream(&CLSID_AMDirectDrawStream, &MSPID_PrimaryVideo, &rgb32_mt); }
void test_mediastreamfilter_get_state(void)
Signed-off-by: Anton Baskanov baskanov@gmail.com --- dlls/amstream/audiostream.c | 5 +++++ dlls/amstream/ddrawstream.c | 5 +++++ dlls/amstream/tests/amstream.c | 4 ++-- 3 files changed, 12 insertions(+), 2 deletions(-)
diff --git a/dlls/amstream/audiostream.c b/dlls/amstream/audiostream.c index dc6c810d19a..a07e62a4672 100644 --- a/dlls/amstream/audiostream.c +++ b/dlls/amstream/audiostream.c @@ -1157,6 +1157,11 @@ static HRESULT WINAPI audio_sink_EndOfStream(IPin *iface)
LeaveCriticalSection(&stream->cs);
+ /* Calling IMediaStreamFilter::EndOfStream() inside the critical section + * would invert the locking order, so we must leave it first to avoid + * the streaming thread deadlocking on the filter's critical section. */ + IMediaStreamFilter_EndOfStream(stream->filter); + return S_OK; }
diff --git a/dlls/amstream/ddrawstream.c b/dlls/amstream/ddrawstream.c index d6f07e1b10a..e04e3a1c56f 100644 --- a/dlls/amstream/ddrawstream.c +++ b/dlls/amstream/ddrawstream.c @@ -1177,6 +1177,11 @@ static HRESULT WINAPI ddraw_sink_EndOfStream(IPin *iface)
LeaveCriticalSection(&stream->cs);
+ /* Calling IMediaStreamFilter::EndOfStream() inside the critical section + * would invert the locking order, so we must leave it first to avoid + * the streaming thread deadlocking on the filter's critical section. */ + IMediaStreamFilter_EndOfStream(stream->filter); + return S_OK; }
diff --git a/dlls/amstream/tests/amstream.c b/dlls/amstream/tests/amstream.c index 2f7854606f4..e42651bb97c 100644 --- a/dlls/amstream/tests/amstream.c +++ b/dlls/amstream/tests/amstream.c @@ -6340,11 +6340,11 @@ static void check_ammediastream_end_of_stream(const CLSID *clsid, const MSPID *i
hr = IPin_EndOfStream(pin); ok(hr == S_OK, "Got hr %#x.\n", hr); - todo_wine ok(filter.got_end_of_stream == 1, "Got %d calls to IMediaStreamFilter::EndOfStream().\n", filter.got_end_of_stream); + ok(filter.got_end_of_stream == 1, "Got %d calls to IMediaStreamFilter::EndOfStream().\n", filter.got_end_of_stream);
hr = IPin_EndOfStream(pin); ok(hr == E_FAIL, "Got hr %#x.\n", hr); - todo_wine ok(filter.got_end_of_stream == 1, "Got %d calls to IMediaStreamFilter::EndOfStream().\n", filter.got_end_of_stream); + ok(filter.got_end_of_stream == 1, "Got %d calls to IMediaStreamFilter::EndOfStream().\n", filter.got_end_of_stream);
IPin_Release(pin); ref = IAMMediaStream_Release(am_stream);
Signed-off-by: Anton Baskanov baskanov@gmail.com --- dlls/amstream/tests/amstream.c | 98 +++++++++++++++++++++++++++++++++- 1 file changed, 96 insertions(+), 2 deletions(-)
diff --git a/dlls/amstream/tests/amstream.c b/dlls/amstream/tests/amstream.c index e42651bb97c..df3cac48754 100644 --- a/dlls/amstream/tests/amstream.c +++ b/dlls/amstream/tests/amstream.c @@ -1318,6 +1318,8 @@ struct testmediastreamfilter IMediaStreamFilter IMediaStreamFilter_iface; LONG refcount; unsigned int got_end_of_stream; + unsigned int got_flush; + BOOL flush_cancel_eos; };
static inline struct testmediastreamfilter *impl_from_IMediaStreamFilter(IMediaStreamFilter *iface) @@ -1470,8 +1472,10 @@ static HRESULT WINAPI testmediastreamfilter_WaitUntil(IMediaStreamFilter *iface,
static HRESULT WINAPI testmediastreamfilter_Flush(IMediaStreamFilter *iface, BOOL cancel_eos) { - ok(0, "Unexpected call.\n"); - return E_NOTIMPL; + struct testmediastreamfilter *filter = impl_from_IMediaStreamFilter(iface); + ++filter->got_flush; + filter->flush_cancel_eos = cancel_eos; + return S_OK; }
static HRESULT WINAPI testmediastreamfilter_EndOfStream(IMediaStreamFilter *iface) @@ -4273,9 +4277,11 @@ static void test_audiostream_initialize(void) static void test_audiostream_begin_flush_end_flush(void) { IAMMultiMediaStream *mmstream = create_ammultimediastream(); + struct testmediastreamfilter filter; IAudioStreamSample *stream_sample; IAudioMediaStream *audio_stream; IMediaSample *media_sample; + IAMMediaStream *am_stream; struct testfilter source; IAudioData *audio_data; IGraphBuilder *graph; @@ -4372,6 +4378,49 @@ static void test_audiostream_begin_flush_end_flush(void) IAudioMediaStream_Release(audio_stream); ref = IMediaStream_Release(stream); ok(!ref, "Got outstanding refcount %d.\n", ref); + + testmediastreamfilter_init(&filter); + + hr = CoCreateInstance(&CLSID_AMAudioStream, NULL, CLSCTX_INPROC_SERVER, &IID_IAMMediaStream, (void **)&am_stream); + ok(hr == S_OK, "Got hr %#x.\n", hr); + hr = IAMMediaStream_QueryInterface(am_stream, &IID_IPin, (void **)&pin); + ok(hr == S_OK, "Got hr %#x.\n", hr); + hr = IAMMediaStream_JoinFilter(am_stream, &filter.IMediaStreamFilter_iface); + ok(hr == S_OK, "Got hr %#x.\n", hr); + + filter.got_flush = 0; + filter.flush_cancel_eos = FALSE; + + hr = IPin_BeginFlush(pin); + ok(hr == S_OK, "Got hr %#x.\n", hr); + todo_wine ok(filter.got_flush == 1, "Got %d calls to IMediaStreamFilter::EndOfStream().\n", filter.got_flush); + ok(!filter.flush_cancel_eos, "Got cancel_eos %d.\n", filter.flush_cancel_eos); + + hr = IPin_EndFlush(pin); + ok(hr == S_OK, "Got hr %#x.\n", hr); + + hr = IPin_EndOfStream(pin); + ok(hr == S_OK, "Got hr %#x.\n", hr); + + hr = IPin_BeginFlush(pin); + ok(hr == S_OK, "Got hr %#x.\n", hr); + todo_wine ok(filter.got_flush == 2, "Got %d calls to IMediaStreamFilter::EndOfStream().\n", filter.got_flush); + todo_wine ok(filter.flush_cancel_eos, "Got cancel_eos %d.\n", filter.flush_cancel_eos); + + hr = IPin_EndFlush(pin); + ok(hr == S_OK, "Got hr %#x.\n", hr); + + hr = IPin_BeginFlush(pin); + ok(hr == S_OK, "Got hr %#x.\n", hr); + todo_wine ok(filter.got_flush == 3, "Got %d calls to IMediaStreamFilter::EndOfStream().\n", filter.got_flush); + ok(!filter.flush_cancel_eos, "Got cancel_eos %d.\n", filter.flush_cancel_eos); + + hr = IPin_EndFlush(pin); + ok(hr == S_OK, "Got hr %#x.\n", hr); + + IPin_Release(pin); + ref = IAMMediaStream_Release(am_stream); + ok(!ref, "Got outstanding refcount %d.\n", ref); }
static IMediaSample *ammediastream_allocate_sample(struct testfilter *source, const BYTE *input_data, DWORD input_length) @@ -5752,8 +5801,10 @@ static void test_ddrawstream_begin_flush_end_flush(void) IAMMultiMediaStream *mmstream = create_ammultimediastream(); IDirectDrawStreamSample *stream_sample; IDirectDrawMediaStream *ddraw_stream; + struct testmediastreamfilter filter; IMediaSample *media_sample; IMediaFilter *media_filter; + IAMMediaStream *am_stream; struct testfilter source; IGraphBuilder *graph; IMediaStream *stream; @@ -5860,6 +5911,49 @@ static void test_ddrawstream_begin_flush_end_flush(void) IDirectDrawMediaStream_Release(ddraw_stream); ref = IMediaStream_Release(stream); ok(!ref, "Got outstanding refcount %d.\n", ref); + + testmediastreamfilter_init(&filter); + + hr = CoCreateInstance(&CLSID_AMDirectDrawStream, NULL, CLSCTX_INPROC_SERVER, &IID_IAMMediaStream, (void **)&am_stream); + ok(hr == S_OK, "Got hr %#x.\n", hr); + hr = IAMMediaStream_QueryInterface(am_stream, &IID_IPin, (void **)&pin); + ok(hr == S_OK, "Got hr %#x.\n", hr); + hr = IAMMediaStream_JoinFilter(am_stream, &filter.IMediaStreamFilter_iface); + ok(hr == S_OK, "Got hr %#x.\n", hr); + + filter.got_flush = 0; + filter.flush_cancel_eos = FALSE; + + hr = IPin_BeginFlush(pin); + ok(hr == S_OK, "Got hr %#x.\n", hr); + todo_wine ok(filter.got_flush == 1, "Got %d calls to IMediaStreamFilter::EndOfStream().\n", filter.got_flush); + ok(!filter.flush_cancel_eos, "Got cancel_eos %d.\n", filter.flush_cancel_eos); + + hr = IPin_EndFlush(pin); + ok(hr == S_OK, "Got hr %#x.\n", hr); + + hr = IPin_EndOfStream(pin); + ok(hr == S_OK, "Got hr %#x.\n", hr); + + hr = IPin_BeginFlush(pin); + ok(hr == S_OK, "Got hr %#x.\n", hr); + todo_wine ok(filter.got_flush == 2, "Got %d calls to IMediaStreamFilter::EndOfStream().\n", filter.got_flush); + todo_wine ok(filter.flush_cancel_eos, "Got cancel_eos %d.\n", filter.flush_cancel_eos); + + hr = IPin_EndFlush(pin); + ok(hr == S_OK, "Got hr %#x.\n", hr); + + hr = IPin_BeginFlush(pin); + ok(hr == S_OK, "Got hr %#x.\n", hr); + todo_wine ok(filter.got_flush == 3, "Got %d calls to IMediaStreamFilter::EndOfStream().\n", filter.got_flush); + ok(!filter.flush_cancel_eos, "Got cancel_eos %d.\n", filter.flush_cancel_eos); + + hr = IPin_EndFlush(pin); + ok(hr == S_OK, "Got hr %#x.\n", hr); + + IPin_Release(pin); + ref = IAMMediaStream_Release(am_stream); + ok(!ref, "Got outstanding refcount %d.\n", ref); }
static void test_ddrawstream_new_segment(void)
Signed-off-by: Anton Baskanov baskanov@gmail.com --- dlls/amstream/audiostream.c | 5 +++++ dlls/amstream/ddrawstream.c | 5 +++++ dlls/amstream/tests/amstream.c | 16 ++++++++-------- 3 files changed, 18 insertions(+), 8 deletions(-)
diff --git a/dlls/amstream/audiostream.c b/dlls/amstream/audiostream.c index a07e62a4672..a46c8707e65 100644 --- a/dlls/amstream/audiostream.c +++ b/dlls/amstream/audiostream.c @@ -1168,15 +1168,20 @@ static HRESULT WINAPI audio_sink_EndOfStream(IPin *iface) static HRESULT WINAPI audio_sink_BeginFlush(IPin *iface) { struct audio_stream *stream = impl_from_IPin(iface); + BOOL cancel_eos;
TRACE("stream %p.\n", stream);
EnterCriticalSection(&stream->cs);
+ cancel_eos = stream->eos; + stream->flushing = TRUE; stream->eos = FALSE; flush_receive_queue(stream);
+ IMediaStreamFilter_Flush(stream->filter, cancel_eos); + LeaveCriticalSection(&stream->cs);
return S_OK; diff --git a/dlls/amstream/ddrawstream.c b/dlls/amstream/ddrawstream.c index e04e3a1c56f..94270b83e38 100644 --- a/dlls/amstream/ddrawstream.c +++ b/dlls/amstream/ddrawstream.c @@ -1188,15 +1188,20 @@ static HRESULT WINAPI ddraw_sink_EndOfStream(IPin *iface) static HRESULT WINAPI ddraw_sink_BeginFlush(IPin *iface) { struct ddraw_stream *stream = impl_from_IPin(iface); + BOOL cancel_eos;
TRACE("stream %p.\n", stream);
EnterCriticalSection(&stream->cs);
+ cancel_eos = stream->eos; + stream->flushing = TRUE; stream->eos = FALSE; WakeConditionVariable(&stream->update_queued_cv);
+ IMediaStreamFilter_Flush(stream->filter, cancel_eos); + LeaveCriticalSection(&stream->cs);
return S_OK; diff --git a/dlls/amstream/tests/amstream.c b/dlls/amstream/tests/amstream.c index df3cac48754..b7d4d89d8fd 100644 --- a/dlls/amstream/tests/amstream.c +++ b/dlls/amstream/tests/amstream.c @@ -4393,7 +4393,7 @@ static void test_audiostream_begin_flush_end_flush(void)
hr = IPin_BeginFlush(pin); ok(hr == S_OK, "Got hr %#x.\n", hr); - todo_wine ok(filter.got_flush == 1, "Got %d calls to IMediaStreamFilter::EndOfStream().\n", filter.got_flush); + ok(filter.got_flush == 1, "Got %d calls to IMediaStreamFilter::EndOfStream().\n", filter.got_flush); ok(!filter.flush_cancel_eos, "Got cancel_eos %d.\n", filter.flush_cancel_eos);
hr = IPin_EndFlush(pin); @@ -4404,15 +4404,15 @@ static void test_audiostream_begin_flush_end_flush(void)
hr = IPin_BeginFlush(pin); ok(hr == S_OK, "Got hr %#x.\n", hr); - todo_wine ok(filter.got_flush == 2, "Got %d calls to IMediaStreamFilter::EndOfStream().\n", filter.got_flush); - todo_wine ok(filter.flush_cancel_eos, "Got cancel_eos %d.\n", filter.flush_cancel_eos); + ok(filter.got_flush == 2, "Got %d calls to IMediaStreamFilter::EndOfStream().\n", filter.got_flush); + ok(filter.flush_cancel_eos, "Got cancel_eos %d.\n", filter.flush_cancel_eos);
hr = IPin_EndFlush(pin); ok(hr == S_OK, "Got hr %#x.\n", hr);
hr = IPin_BeginFlush(pin); ok(hr == S_OK, "Got hr %#x.\n", hr); - todo_wine ok(filter.got_flush == 3, "Got %d calls to IMediaStreamFilter::EndOfStream().\n", filter.got_flush); + ok(filter.got_flush == 3, "Got %d calls to IMediaStreamFilter::EndOfStream().\n", filter.got_flush); ok(!filter.flush_cancel_eos, "Got cancel_eos %d.\n", filter.flush_cancel_eos);
hr = IPin_EndFlush(pin); @@ -5926,7 +5926,7 @@ static void test_ddrawstream_begin_flush_end_flush(void)
hr = IPin_BeginFlush(pin); ok(hr == S_OK, "Got hr %#x.\n", hr); - todo_wine ok(filter.got_flush == 1, "Got %d calls to IMediaStreamFilter::EndOfStream().\n", filter.got_flush); + ok(filter.got_flush == 1, "Got %d calls to IMediaStreamFilter::EndOfStream().\n", filter.got_flush); ok(!filter.flush_cancel_eos, "Got cancel_eos %d.\n", filter.flush_cancel_eos);
hr = IPin_EndFlush(pin); @@ -5937,15 +5937,15 @@ static void test_ddrawstream_begin_flush_end_flush(void)
hr = IPin_BeginFlush(pin); ok(hr == S_OK, "Got hr %#x.\n", hr); - todo_wine ok(filter.got_flush == 2, "Got %d calls to IMediaStreamFilter::EndOfStream().\n", filter.got_flush); - todo_wine ok(filter.flush_cancel_eos, "Got cancel_eos %d.\n", filter.flush_cancel_eos); + ok(filter.got_flush == 2, "Got %d calls to IMediaStreamFilter::EndOfStream().\n", filter.got_flush); + ok(filter.flush_cancel_eos, "Got cancel_eos %d.\n", filter.flush_cancel_eos);
hr = IPin_EndFlush(pin); ok(hr == S_OK, "Got hr %#x.\n", hr);
hr = IPin_BeginFlush(pin); ok(hr == S_OK, "Got hr %#x.\n", hr); - todo_wine ok(filter.got_flush == 3, "Got %d calls to IMediaStreamFilter::EndOfStream().\n", filter.got_flush); + ok(filter.got_flush == 3, "Got %d calls to IMediaStreamFilter::EndOfStream().\n", filter.got_flush); ok(!filter.flush_cancel_eos, "Got cancel_eos %d.\n", filter.flush_cancel_eos);
hr = IPin_EndFlush(pin);
On 4/14/21 2:18 AM, Anton Baskanov wrote:
Signed-off-by: Anton Baskanov baskanov@gmail.com
dlls/amstream/audiostream.c | 5 +++++ dlls/amstream/ddrawstream.c | 5 +++++ dlls/amstream/tests/amstream.c | 16 ++++++++-------- 3 files changed, 18 insertions(+), 8 deletions(-)
diff --git a/dlls/amstream/audiostream.c b/dlls/amstream/audiostream.c index a07e62a4672..a46c8707e65 100644 --- a/dlls/amstream/audiostream.c +++ b/dlls/amstream/audiostream.c @@ -1168,15 +1168,20 @@ static HRESULT WINAPI audio_sink_EndOfStream(IPin *iface) static HRESULT WINAPI audio_sink_BeginFlush(IPin *iface) { struct audio_stream *stream = impl_from_IPin(iface);
BOOL cancel_eos;
TRACE("stream %p.\n", stream);
EnterCriticalSection(&stream->cs);
cancel_eos = stream->eos;
stream->flushing = TRUE; stream->eos = FALSE; flush_receive_queue(stream);
IMediaStreamFilter_Flush(stream->filter, cancel_eos);
Doesn't this also invert the locking order?
LeaveCriticalSection(&stream->cs); return S_OK;
diff --git a/dlls/amstream/ddrawstream.c b/dlls/amstream/ddrawstream.c index e04e3a1c56f..94270b83e38 100644 --- a/dlls/amstream/ddrawstream.c +++ b/dlls/amstream/ddrawstream.c @@ -1188,15 +1188,20 @@ static HRESULT WINAPI ddraw_sink_EndOfStream(IPin *iface) static HRESULT WINAPI ddraw_sink_BeginFlush(IPin *iface) { struct ddraw_stream *stream = impl_from_IPin(iface);
BOOL cancel_eos;
TRACE("stream %p.\n", stream);
EnterCriticalSection(&stream->cs);
cancel_eos = stream->eos;
stream->flushing = TRUE; stream->eos = FALSE; WakeConditionVariable(&stream->update_queued_cv);
IMediaStreamFilter_Flush(stream->filter, cancel_eos);
LeaveCriticalSection(&stream->cs); return S_OK;
diff --git a/dlls/amstream/tests/amstream.c b/dlls/amstream/tests/amstream.c index df3cac48754..b7d4d89d8fd 100644 --- a/dlls/amstream/tests/amstream.c +++ b/dlls/amstream/tests/amstream.c @@ -4393,7 +4393,7 @@ static void test_audiostream_begin_flush_end_flush(void)
hr = IPin_BeginFlush(pin); ok(hr == S_OK, "Got hr %#x.\n", hr);
- todo_wine ok(filter.got_flush == 1, "Got %d calls to IMediaStreamFilter::EndOfStream().\n", filter.got_flush);
ok(filter.got_flush == 1, "Got %d calls to IMediaStreamFilter::EndOfStream().\n", filter.got_flush); ok(!filter.flush_cancel_eos, "Got cancel_eos %d.\n", filter.flush_cancel_eos);
hr = IPin_EndFlush(pin);
@@ -4404,15 +4404,15 @@ static void test_audiostream_begin_flush_end_flush(void)
hr = IPin_BeginFlush(pin); ok(hr == S_OK, "Got hr %#x.\n", hr);
- todo_wine ok(filter.got_flush == 2, "Got %d calls to IMediaStreamFilter::EndOfStream().\n", filter.got_flush);
- todo_wine ok(filter.flush_cancel_eos, "Got cancel_eos %d.\n", filter.flush_cancel_eos);
ok(filter.got_flush == 2, "Got %d calls to IMediaStreamFilter::EndOfStream().\n", filter.got_flush);
ok(filter.flush_cancel_eos, "Got cancel_eos %d.\n", filter.flush_cancel_eos);
hr = IPin_EndFlush(pin); ok(hr == S_OK, "Got hr %#x.\n", hr);
hr = IPin_BeginFlush(pin); ok(hr == S_OK, "Got hr %#x.\n", hr);
- todo_wine ok(filter.got_flush == 3, "Got %d calls to IMediaStreamFilter::EndOfStream().\n", filter.got_flush);
ok(filter.got_flush == 3, "Got %d calls to IMediaStreamFilter::EndOfStream().\n", filter.got_flush); ok(!filter.flush_cancel_eos, "Got cancel_eos %d.\n", filter.flush_cancel_eos);
hr = IPin_EndFlush(pin);
@@ -5926,7 +5926,7 @@ static void test_ddrawstream_begin_flush_end_flush(void)
hr = IPin_BeginFlush(pin); ok(hr == S_OK, "Got hr %#x.\n", hr);
- todo_wine ok(filter.got_flush == 1, "Got %d calls to IMediaStreamFilter::EndOfStream().\n", filter.got_flush);
ok(filter.got_flush == 1, "Got %d calls to IMediaStreamFilter::EndOfStream().\n", filter.got_flush); ok(!filter.flush_cancel_eos, "Got cancel_eos %d.\n", filter.flush_cancel_eos);
hr = IPin_EndFlush(pin);
@@ -5937,15 +5937,15 @@ static void test_ddrawstream_begin_flush_end_flush(void)
hr = IPin_BeginFlush(pin); ok(hr == S_OK, "Got hr %#x.\n", hr);
- todo_wine ok(filter.got_flush == 2, "Got %d calls to IMediaStreamFilter::EndOfStream().\n", filter.got_flush);
- todo_wine ok(filter.flush_cancel_eos, "Got cancel_eos %d.\n", filter.flush_cancel_eos);
ok(filter.got_flush == 2, "Got %d calls to IMediaStreamFilter::EndOfStream().\n", filter.got_flush);
ok(filter.flush_cancel_eos, "Got cancel_eos %d.\n", filter.flush_cancel_eos);
hr = IPin_EndFlush(pin); ok(hr == S_OK, "Got hr %#x.\n", hr);
hr = IPin_BeginFlush(pin); ok(hr == S_OK, "Got hr %#x.\n", hr);
- todo_wine ok(filter.got_flush == 3, "Got %d calls to IMediaStreamFilter::EndOfStream().\n", filter.got_flush);
ok(filter.got_flush == 3, "Got %d calls to IMediaStreamFilter::EndOfStream().\n", filter.got_flush); ok(!filter.flush_cancel_eos, "Got cancel_eos %d.\n", filter.flush_cancel_eos);
hr = IPin_EndFlush(pin);
It's probably not the first time, but I feel like this is reaching a little too deep into the inner workings. Yes, it's documented, but unlike e.g. custom IAMMediaStream or IFilterGraph implementations, applications aren't really expected to plug in their own filters. Better to test it indirectly, especially when the behaviour isn't surprising.