Signed-off-by: Anton Baskanov baskanov@gmail.com --- dlls/amstream/tests/amstream.c | 97 ++++++++++++++++++++++++++++++++++ 1 file changed, 97 insertions(+)
diff --git a/dlls/amstream/tests/amstream.c b/dlls/amstream/tests/amstream.c index bf0a0016beb..79cc4f52801 100644 --- a/dlls/amstream/tests/amstream.c +++ b/dlls/amstream/tests/amstream.c @@ -7027,6 +7027,35 @@ static void test_mediastreamfilter_end_of_stream(void)
todo_wine ok(graph.got_notify == 1, "Got %d calls to IMediaEventSink::Notify().\n", graph.got_notify);
+ 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); + + hr = IMediaControl_Stop(media_control); + ok(hr == S_OK, "Got hr %#x.\n", hr); + + /* EC_COMPLETE is sent on paused->running state transition + * if EndOfStream has been called for all streams. */ + graph.got_notify = 0; + + hr = IMediaStreamFilter_EndOfStream(filter); + todo_wine 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(graph.got_notify == 0, "Got %d calls to IMediaEventSink::Notify().\n", graph.got_notify); + + hr = IMediaControl_Pause(media_control); + 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 = 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); + hr = IMediaControl_Stop(media_control); ok(hr == S_OK, "Got hr %#x.\n", hr);
@@ -7074,6 +7103,26 @@ static void test_mediastreamfilter_end_of_stream(void) hr = IMediaControl_Stop(media_control); ok(hr == S_OK, "Got hr %#x.\n", hr);
+ /* EndOfStream count is not reset when Stop() is called on an already stopped filter. */ + hr = IMediaStreamFilter_EndOfStream(filter); + todo_wine ok(hr == S_OK, "Got hr %#x.\n", hr); + + hr = IMediaStreamFilter_Stop(filter); + ok(hr == S_OK, "Got hr %#x.\n", hr); + + hr = IMediaStreamFilter_EndOfStream(filter); + todo_wine ok(hr == S_OK, "Got hr %#x.\n", hr); + + graph.got_notify = 0; + + hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_RUN); + 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); + + hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_STOP); + ok(hr == S_OK, "Got hr %#x.\n", hr); + /* Flush with cancel_eos=TRUE decrements EOS count. */ hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_RUN); ok(hr == S_OK, "Got hr %#x.\n", hr); @@ -7093,6 +7142,54 @@ static void test_mediastreamfilter_end_of_stream(void) hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_STOP); ok(hr == S_OK, "Got hr %#x.\n", hr);
+ /* Flush followed by EndOfStream causes another EC_COMPLETE to be sent. */ + hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_RUN); + ok(hr == S_OK, "Got hr %#x.\n", hr); + + graph.got_notify = 0; + + hr = IMediaStreamFilter_EndOfStream(filter); + todo_wine ok(hr == S_OK, "Got hr %#x.\n", hr); + hr = IMediaStreamFilter_EndOfStream(filter); + todo_wine 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); + + hr = IMediaStreamFilter_Flush(filter, TRUE); + ok(hr == S_OK, "Got hr %#x.\n", hr); + + hr = IMediaStreamFilter_EndOfStream(filter); + todo_wine ok(hr == S_OK, "Got hr %#x.\n", hr); + + todo_wine ok(graph.got_notify == 2, "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); + + /* Flush decrements EOS count event when it is 0. */ + hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_RUN); + ok(hr == S_OK, "Got hr %#x.\n", hr); + + graph.got_notify = 0; + + hr = IMediaStreamFilter_Flush(filter, TRUE); + ok(hr == S_OK, "Got hr %#x.\n", hr); + + hr = IMediaStreamFilter_EndOfStream(filter); + todo_wine 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(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); + + todo_wine 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); + /* Flush with cancel_eos=FALSE does not decrement EOS count. */ hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_RUN); ok(hr == S_OK, "Got hr %#x.\n", hr);
Signed-off-by: Anton Baskanov baskanov@gmail.com --- dlls/amstream/filter.c | 42 +++++++++++++++++++- dlls/amstream/tests/amstream.c | 72 +++++++++++++++++----------------- 2 files changed, 76 insertions(+), 38 deletions(-)
diff --git a/dlls/amstream/filter.c b/dlls/amstream/filter.c index 3c0436a294f..881ddb114e2 100644 --- a/dlls/amstream/filter.c +++ b/dlls/amstream/filter.c @@ -178,6 +178,7 @@ struct filter REFERENCE_TIME start_time; struct list free_events; struct list used_events; + LONG eos_count; };
struct event @@ -266,6 +267,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 void set_state(struct filter *filter, FILTER_STATE state) { if (filter->state != state) @@ -275,6 +292,13 @@ static void set_state(struct filter *filter, FILTER_STATE state) for (i = 0; i < filter->nb_streams; ++i) IAMMediaStream_SetState(filter->streams[i], state); filter->state = state; + + if (state == State_Stopped) + filter->eos_count = 0; + + if (state == State_Running && filter->seekable_stream + && filter->eos_count == (LONG)filter->nb_streams) + send_ec_complete(filter); } }
@@ -769,6 +793,9 @@ static HRESULT WINAPI filter_Flush(IMediaStreamFilter *iface, BOOL cancel_eos) } }
+ if (cancel_eos) + --filter->eos_count; + LeaveCriticalSection(&filter->cs);
return S_OK; @@ -776,9 +803,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->cs); + + ++filter->eos_count; + if (filter->state == State_Running && filter->seekable_stream && + filter->eos_count == (LONG)filter->nb_streams) + send_ec_complete(filter); + + LeaveCriticalSection(&filter->cs); + + return S_OK; }
static const IMediaStreamFilterVtbl filter_vtbl = diff --git a/dlls/amstream/tests/amstream.c b/dlls/amstream/tests/amstream.c index 79cc4f52801..9cefec12442 100644 --- a/dlls/amstream/tests/amstream.c +++ b/dlls/amstream/tests/amstream.c @@ -6954,9 +6954,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);
@@ -6973,9 +6973,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);
@@ -6994,14 +6994,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); @@ -7011,9 +7011,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);
@@ -7025,12 +7025,12 @@ 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_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); @@ -7040,9 +7040,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);
@@ -7054,7 +7054,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); @@ -7066,7 +7066,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); @@ -7074,7 +7074,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);
@@ -7088,7 +7088,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); @@ -7096,29 +7096,29 @@ 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);
/* EndOfStream count is not reset when Stop() is called on an already stopped filter. */ 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_Stop(filter); 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);
graph.got_notify = 0;
hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_RUN); 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); @@ -7130,12 +7130,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);
@@ -7149,19 +7149,19 @@ 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);
- 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 = IMediaStreamFilter_Flush(filter, TRUE); 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 == 2, "Got %d calls to IMediaEventSink::Notify().\n", graph.got_notify); + ok(graph.got_notify == 2, "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); @@ -7176,16 +7176,16 @@ 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); 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); @@ -7197,14 +7197,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);
Sorry for not noticing this before, but...
On 4/9/21 2:02 PM, Anton Baskanov wrote:
@@ -275,6 +292,13 @@ static void set_state(struct filter *filter, FILTER_STATE state) for (i = 0; i < filter->nb_streams; ++i) IAMMediaStream_SetState(filter->streams[i], state); filter->state = state;
if (state == State_Stopped)
filter->eos_count = 0;
if (state == State_Running && filter->seekable_stream
&& filter->eos_count == (LONG)filter->nb_streams)
}send_ec_complete(filter); }
Is there a reason not to put these in filter_Stop() and filter_Run() respectively?
On суббота, 10 апреля 2021 г. 23:35:53 +07 you wrote:
Sorry for not noticing this before, but...
On 4/9/21 2:02 PM, Anton Baskanov wrote:
@@ -275,6 +292,13 @@ static void set_state(struct filter *filter, FILTER_STATE state)> for (i = 0; i < filter->nb_streams; ++i)
IAMMediaStream_SetState(filter->streams[i], state); filter->state = state;
if (state == State_Stopped)
filter->eos_count = 0;
if (state == State_Running && filter->seekable_stream
&& filter->eos_count == (LONG)filter->nb_streams)
send_ec_complete(filter); }
}
Is there a reason not to put these in filter_Stop() and filter_Run() respectively?
There is no particular reason. And yeah, putting these in filter_Stop() and filter_Run() probably makes more sense. Fixed in v3.
Signed-off-by: Anton Baskanov baskanov@gmail.com --- This is required to avoid deadlocks, e.g. when MediaStreamFilter sends EC_COMPLETE while the graph is being stopped. --- dlls/quartz/filtergraph.c | 28 +++++++++++++++++++++------- 1 file changed, 21 insertions(+), 7 deletions(-)
diff --git a/dlls/quartz/filtergraph.c b/dlls/quartz/filtergraph.c index a8c6cc3391c..774659616e4 100644 --- a/dlls/quartz/filtergraph.c +++ b/dlls/quartz/filtergraph.c @@ -104,6 +104,9 @@ struct filter_graph IReferenceClock *refClock; IBaseFilter *refClockProvider;
+ /* Separate critical section is used for event state to avoid deadlocks, + * e.g. when MediaStreamFilter sends EC_COMPLETE while the graph is being stopped. */ + CRITICAL_SECTION event_cs; struct list media_events; HANDLE media_event_handle; HWND media_event_window; @@ -116,6 +119,8 @@ struct filter_graph int HandleEcComplete; int HandleEcRepaint; int HandleEcClockChanged; + unsigned int got_ec_complete : 1; + unsigned int media_events_disabled : 1;
CRITICAL_SECTION cs; ITF_CACHE_ENTRY ItfCacheEntries[MAX_ITF_CACHE_ENTRIES]; @@ -135,8 +140,6 @@ struct filter_graph LONGLONG current_pos;
unsigned int needs_async_run : 1; - unsigned int got_ec_complete : 1; - unsigned int media_events_disabled : 1; };
struct enum_filters @@ -467,6 +470,7 @@ static ULONG WINAPI FilterGraphInner_Release(IUnknown *iface) CloseHandle(This->message_thread); CloseHandle(This->message_thread_ret); } + DeleteCriticalSection(&This->event_cs); DeleteCriticalSection(&This->cs); free(This);
@@ -1695,8 +1699,10 @@ static HRESULT graph_start(struct filter_graph *graph, REFERENCE_TIME stream_sta struct filter *filter; HRESULT hr = S_OK;
+ EnterCriticalSection(&graph->event_cs); graph->EcCompleteCount = 0; update_render_count(graph); + LeaveCriticalSection(&graph->event_cs);
LIST_FOR_EACH_ENTRY_SAFE(event, next, &graph->media_events, struct media_event, entry) { @@ -1813,7 +1819,10 @@ static HRESULT WINAPI MediaControl_Run(IMediaControl *iface) }
sort_filters(graph); + + EnterCriticalSection(&graph->event_cs); update_render_count(graph); + LeaveCriticalSection(&graph->event_cs);
if (graph->state == State_Stopped) { @@ -4752,12 +4761,12 @@ static HRESULT WINAPI MediaEvent_GetEvent(IMediaEventEx *iface, LONG *code, if (WaitForSingleObject(graph->media_event_handle, timeout)) return E_ABORT;
- EnterCriticalSection(&graph->cs); + EnterCriticalSection(&graph->event_cs);
if (!(entry = list_head(&graph->media_events))) { ResetEvent(graph->media_event_handle); - LeaveCriticalSection(&graph->cs); + LeaveCriticalSection(&graph->event_cs); return E_ABORT; } event = LIST_ENTRY(entry, struct media_event, entry); @@ -4767,7 +4776,7 @@ static HRESULT WINAPI MediaEvent_GetEvent(IMediaEventEx *iface, LONG *code, *param2 = event->param2; free(event);
- LeaveCriticalSection(&graph->cs); + LeaveCriticalSection(&graph->event_cs); return S_OK; }
@@ -5015,7 +5024,10 @@ static HRESULT WINAPI MediaFilter_Pause(IMediaFilter *iface) }
sort_filters(graph); + + EnterCriticalSection(&graph->event_cs); update_render_count(graph); + LeaveCriticalSection(&graph->event_cs);
if (graph->defaultclock && !graph->refClock) IFilterGraph2_SetDefaultSyncSource(&graph->IFilterGraph2_iface); @@ -5261,7 +5273,7 @@ static HRESULT WINAPI MediaEventSink_Notify(IMediaEventSink *iface, LONG code,
TRACE("graph %p, code %#x, param1 %#Ix, param2 %#Ix.\n", graph, code, param1, param2);
- EnterCriticalSection(&graph->cs); + EnterCriticalSection(&graph->event_cs);
if (code == EC_COMPLETE && graph->HandleEcComplete) { @@ -5285,7 +5297,7 @@ static HRESULT WINAPI MediaEventSink_Notify(IMediaEventSink *iface, LONG code, queue_media_event(graph, code, param1, param2); }
- LeaveCriticalSection(&graph->cs); + LeaveCriticalSection(&graph->event_cs); return S_OK; }
@@ -5591,6 +5603,8 @@ static HRESULT filter_graph_common_create(IUnknown *outer, IUnknown **out, BOOL
InitializeCriticalSection(&object->cs); object->cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": filter_graph.cs"); + InitializeCriticalSection(&object->event_cs); + object->event_cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": filter_graph.event_cs");
object->defaultclock = TRUE;