[PATCH] mfreadwrite: Introduce an internal source reader refcount.

Rémi Bernon rbernon at codeweavers.com
Wed Feb 9 08:45:32 CST 2022


To decide when to shutdown the media source. Otherwise the references
hold by the callbacks from BeginGetEvent and others are keeping the
source reader alive and the IMFMediaSource_Shutdown is never called.

Signed-off-by: Rémi Bernon <rbernon at codeweavers.com>
---
 dlls/mfreadwrite/reader.c       | 41 +++++++++++++++++++++++++--------
 dlls/mfreadwrite/tests/mfplat.c |  8 +++++--
 2 files changed, 38 insertions(+), 11 deletions(-)

diff --git a/dlls/mfreadwrite/reader.c b/dlls/mfreadwrite/reader.c
index be77e1c5b1d..18509e067b3 100644
--- a/dlls/mfreadwrite/reader.c
+++ b/dlls/mfreadwrite/reader.c
@@ -153,6 +153,7 @@ struct source_reader
     IMFAsyncCallback source_events_callback;
     IMFAsyncCallback stream_events_callback;
     IMFAsyncCallback async_commands_callback;
+    LONG internal_refcount;
     LONG refcount;
     IMFMediaSource *source;
     IMFPresentationDescriptor *descriptor;
@@ -203,6 +204,9 @@ static struct media_stream *impl_stream_from_IMFVideoSampleAllocatorNotify(IMFVi
     return CONTAINING_RECORD(iface, struct media_stream, notify_cb);
 }
 
+static ULONG WINAPI src_reader_internal_addref(struct source_reader *reader);
+static ULONG WINAPI src_reader_internal_release(struct source_reader *reader);
+
 static HRESULT WINAPI source_reader_async_command_QueryInterface(IUnknown *iface, REFIID riid, void **obj)
 {
     if (IsEqualIID(riid, &IID_IUnknown))
@@ -325,13 +329,13 @@ static HRESULT WINAPI source_reader_callback_QueryInterface(IMFAsyncCallback *if
 static ULONG WINAPI source_reader_source_events_callback_AddRef(IMFAsyncCallback *iface)
 {
     struct source_reader *reader = impl_from_source_callback_IMFAsyncCallback(iface);
-    return IMFSourceReader_AddRef(&reader->IMFSourceReader_iface);
+    return src_reader_internal_addref(reader);
 }
 
 static ULONG WINAPI source_reader_source_events_callback_Release(IMFAsyncCallback *iface)
 {
     struct source_reader *reader = impl_from_source_callback_IMFAsyncCallback(iface);
-    return IMFSourceReader_Release(&reader->IMFSourceReader_iface);
+    return src_reader_internal_release(reader);
 }
 
 static HRESULT WINAPI source_reader_callback_GetParameters(IMFAsyncCallback *iface,
@@ -611,13 +615,13 @@ static const IMFAsyncCallbackVtbl source_events_callback_vtbl =
 static ULONG WINAPI source_reader_stream_events_callback_AddRef(IMFAsyncCallback *iface)
 {
     struct source_reader *reader = impl_from_stream_callback_IMFAsyncCallback(iface);
-    return IMFSourceReader_AddRef(&reader->IMFSourceReader_iface);
+    return src_reader_internal_addref(reader);
 }
 
 static ULONG WINAPI source_reader_stream_events_callback_Release(IMFAsyncCallback *iface)
 {
     struct source_reader *reader = impl_from_stream_callback_IMFAsyncCallback(iface);
-    return IMFSourceReader_Release(&reader->IMFSourceReader_iface);
+    return src_reader_internal_release(reader);
 }
 
 static HRESULT source_reader_pull_stream_samples(struct source_reader *reader, struct media_stream *stream)
@@ -888,13 +892,13 @@ static const IMFAsyncCallbackVtbl stream_events_callback_vtbl =
 static ULONG WINAPI source_reader_async_commands_callback_AddRef(IMFAsyncCallback *iface)
 {
     struct source_reader *reader = impl_from_async_commands_callback_IMFAsyncCallback(iface);
-    return IMFSourceReader_AddRef(&reader->IMFSourceReader_iface);
+    return src_reader_internal_addref(reader);
 }
 
 static ULONG WINAPI source_reader_async_commands_callback_Release(IMFAsyncCallback *iface)
 {
     struct source_reader *reader = impl_from_async_commands_callback_IMFAsyncCallback(iface);
-    return IMFSourceReader_Release(&reader->IMFSourceReader_iface);
+    return src_reader_internal_release(reader);
 }
 
 static struct stream_response * media_stream_detach_response(struct source_reader *reader, struct stream_response *response)
@@ -1337,16 +1341,34 @@ static ULONG WINAPI src_reader_Release(IMFSourceReader *iface)
 {
     struct source_reader *reader = impl_from_IMFSourceReader(iface);
     ULONG refcount = InterlockedDecrement(&reader->refcount);
-    unsigned int i;
 
     TRACE("%p, refcount %u.\n", iface, refcount);
 
     if (!refcount)
     {
-        if (reader->async_callback)
-            IMFSourceReaderCallback_Release(reader->async_callback);
         if (reader->flags & SOURCE_READER_SHUTDOWN_ON_RELEASE)
             IMFMediaSource_Shutdown(reader->source);
+        src_reader_internal_release(reader);
+    }
+
+    return refcount;
+}
+
+static ULONG WINAPI src_reader_internal_addref(struct source_reader *reader)
+{
+    ULONG refcount = InterlockedIncrement(&reader->internal_refcount);
+    return refcount;
+}
+
+static ULONG WINAPI src_reader_internal_release(struct source_reader *reader)
+{
+    ULONG refcount = InterlockedDecrement(&reader->internal_refcount);
+    unsigned int i;
+
+    if (!refcount)
+    {
+        if (reader->async_callback)
+            IMFSourceReaderCallback_Release(reader->async_callback);
         if (reader->descriptor)
             IMFPresentationDescriptor_Release(reader->descriptor);
         if (reader->attributes)
@@ -2267,6 +2289,7 @@ static HRESULT create_source_reader_from_source(IMFMediaSource *source, IMFAttri
     object->source_events_callback.lpVtbl = &source_events_callback_vtbl;
     object->stream_events_callback.lpVtbl = &stream_events_callback_vtbl;
     object->async_commands_callback.lpVtbl = &async_commands_callback_vtbl;
+    object->internal_refcount = 1;
     object->refcount = 1;
     list_init(&object->responses);
     if (shutdown_on_release)
diff --git a/dlls/mfreadwrite/tests/mfplat.c b/dlls/mfreadwrite/tests/mfplat.c
index 7e724344168..0791f51fa37 100644
--- a/dlls/mfreadwrite/tests/mfplat.c
+++ b/dlls/mfreadwrite/tests/mfplat.c
@@ -862,7 +862,8 @@ skip_read_sample:
     hr = IMFSourceReader_Flush(reader, MF_SOURCE_READER_ALL_STREAMS);
     ok(hr == S_OK, "Failed to flush all streams, hr %#x.\n", hr);
 
-    IMFSourceReader_Release(reader);
+    refcount = IMFSourceReader_Release(reader);
+    ok(refcount == 0, "Release returned %u.\n", refcount);
 
     /* Async mode. */
     callback = create_async_callback();
@@ -883,7 +884,10 @@ todo_wine {
 }
     IMFAttributes_Release(attributes);
     if (hr == S_OK)
-        IMFSourceReader_Release(reader);
+    {
+        refcount = IMFSourceReader_Release(reader);
+        ok(refcount == 0, "Release returned %u.\n", refcount);
+    }
 
     IMFByteStream_Release(stream);
 }
-- 
2.34.1




More information about the wine-devel mailing list