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