Nikolay Sivov : mfreadwrite/reader: Stop media source when shutdown is not allowed.
Alexandre Julliard
julliard at winehq.org
Fri Feb 11 14:33:57 CST 2022
Module: wine
Branch: master
Commit: a5770a0402c44586aa2913a7f2e411795f51e567
URL: https://source.winehq.org/git/wine.git/?a=commit;h=a5770a0402c44586aa2913a7f2e411795f51e567
Author: Nikolay Sivov <nsivov at codeweavers.com>
Date: Fri Feb 11 09:51:21 2022 +0300
mfreadwrite/reader: Stop media source when shutdown is not allowed.
Signed-off-by: Nikolay Sivov <nsivov at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>
---
dlls/mfreadwrite/reader.c | 45 +++++++++++++++++++++++++++++++++++++++++++--
1 file changed, 43 insertions(+), 2 deletions(-)
diff --git a/dlls/mfreadwrite/reader.c b/dlls/mfreadwrite/reader.c
index 0b6c6fa8583..13fcc4278cc 100644
--- a/dlls/mfreadwrite/reader.c
+++ b/dlls/mfreadwrite/reader.c
@@ -72,6 +72,7 @@ enum media_stream_flags
STREAM_FLAG_SAMPLE_REQUESTED = 0x1, /* Protects from making multiple sample requests. */
STREAM_FLAG_SELECTED = 0x2, /* Mirrors descriptor, used to simplify tests when starting the source. */
STREAM_FLAG_PRESENTED = 0x4, /* Set if stream was selected last time Start() was called. */
+ STREAM_FLAG_STOPPED = 0x8, /* Received MEStreamStopped */
};
struct stream_transform
@@ -172,6 +173,7 @@ struct source_reader
CRITICAL_SECTION cs;
CONDITION_VARIABLE sample_event;
CONDITION_VARIABLE state_event;
+ CONDITION_VARIABLE stop_event;
};
static inline struct source_reader *impl_from_IMFSourceReader(IMFSourceReader *iface)
@@ -585,6 +587,8 @@ static HRESULT source_reader_source_state_handler(struct source_reader *reader,
LeaveCriticalSection(&reader->cs);
WakeAllConditionVariable(&reader->state_event);
+ if (event_type == MESourceStopped)
+ WakeAllConditionVariable(&reader->stop_event);
return S_OK;
}
@@ -640,7 +644,8 @@ static HRESULT WINAPI source_reader_source_events_callback_Invoke(IMFAsyncCallba
IMFMediaEvent_Release(event);
- IMFMediaSource_BeginGetEvent(source, iface, (IUnknown *)source);
+ if (event_type != MESourceStopped)
+ IMFMediaSource_BeginGetEvent(source, iface, (IUnknown *)source);
return S_OK;
}
@@ -856,6 +861,9 @@ static HRESULT source_reader_media_stream_state_handler(struct source_reader *re
case MEStreamStarted:
stream->state = STREAM_STATE_READY;
break;
+ case MEStreamStopped:
+ stream->flags |= STREAM_FLAG_STOPPED;
+ break;
case MEStreamTick:
value.vt = VT_EMPTY;
hr = SUCCEEDED(IMFMediaEvent_GetValue(event, &value)) && value.vt == VT_I8 ? S_OK : E_UNEXPECTED;
@@ -875,6 +883,9 @@ static HRESULT source_reader_media_stream_state_handler(struct source_reader *re
LeaveCriticalSection(&reader->cs);
+ if (event_type == MEStreamStopped)
+ WakeAllConditionVariable(&reader->stop_event);
+
return S_OK;
}
@@ -904,6 +915,7 @@ static HRESULT WINAPI source_reader_stream_events_callback_Invoke(IMFAsyncCallba
break;
case MEStreamSeeked:
case MEStreamStarted:
+ case MEStreamStopped:
case MEStreamTick:
case MEEndOfStream:
hr = source_reader_media_stream_state_handler(reader, stream, event);
@@ -917,7 +929,8 @@ static HRESULT WINAPI source_reader_stream_events_callback_Invoke(IMFAsyncCallba
IMFMediaEvent_Release(event);
- IMFMediaStream_BeginGetEvent(stream, iface, (IUnknown *)stream);
+ if (event_type != MEStreamStopped)
+ IMFMediaStream_BeginGetEvent(stream, iface, (IUnknown *)stream);
return S_OK;
}
@@ -1379,6 +1392,22 @@ static ULONG WINAPI src_reader_AddRef(IMFSourceReader *iface)
return refcount;
}
+static BOOL source_reader_is_source_stopped(const struct source_reader *reader)
+{
+ unsigned int i;
+
+ if (reader->source_state != SOURCE_STATE_STOPPED)
+ return FALSE;
+
+ for (i = 0; i < reader->stream_count; ++i)
+ {
+ if (reader->streams[i].stream && !(reader->streams[i].flags & STREAM_FLAG_STOPPED))
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
static ULONG WINAPI src_reader_Release(IMFSourceReader *iface)
{
struct source_reader *reader = impl_from_IMFSourceReader(iface);
@@ -1390,6 +1419,17 @@ static ULONG WINAPI src_reader_Release(IMFSourceReader *iface)
{
if (reader->flags & SOURCE_READER_SHUTDOWN_ON_RELEASE)
IMFMediaSource_Shutdown(reader->source);
+ else if (SUCCEEDED(IMFMediaSource_Stop(reader->source)))
+ {
+ EnterCriticalSection(&reader->cs);
+
+ while (!source_reader_is_source_stopped(reader))
+ {
+ SleepConditionVariableCS(&reader->stop_event, &reader->cs, INFINITE);
+ }
+
+ LeaveCriticalSection(&reader->cs);
+ }
source_reader_release(reader);
}
@@ -2298,6 +2338,7 @@ static HRESULT create_source_reader_from_source(IMFMediaSource *source, IMFAttri
InitializeCriticalSection(&object->cs);
InitializeConditionVariable(&object->sample_event);
InitializeConditionVariable(&object->state_event);
+ InitializeConditionVariable(&object->stop_event);
if (FAILED(hr = IMFMediaSource_CreatePresentationDescriptor(object->source, &object->descriptor)))
goto failed;
More information about the wine-cvs
mailing list