Rémi Bernon : mfreadwrite/reader: Use separate refcount for events callbacks.

Alexandre Julliard julliard at winehq.org
Fri Feb 11 14:33:57 CST 2022


Module: wine
Branch: master
Commit: be85638b5b38f9f07ccd23024485d4f90c57e5de
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=be85638b5b38f9f07ccd23024485d4f90c57e5de

Author: Rémi Bernon <rbernon at codeweavers.com>
Date:   Fri Feb 11 09:51:20 2022 +0300

mfreadwrite/reader: Use separate refcount for events callbacks.

This resolves circular dependency, with source and streams holding
references to the callbacks, subscribed to their event queues.

Signed-off-by: Nikolay Sivov <nsivov at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/mfreadwrite/reader.c       | 91 +++++++++++++++++++++++++----------------
 dlls/mfreadwrite/tests/mfplat.c |  3 +-
 2 files changed, 58 insertions(+), 36 deletions(-)

diff --git a/dlls/mfreadwrite/reader.c b/dlls/mfreadwrite/reader.c
index 6d35a59f3a8..0b6c6fa8583 100644
--- a/dlls/mfreadwrite/reader.c
+++ b/dlls/mfreadwrite/reader.c
@@ -154,6 +154,7 @@ struct source_reader
     IMFAsyncCallback stream_events_callback;
     IMFAsyncCallback async_commands_callback;
     LONG refcount;
+    LONG public_refcount;
     IMFMediaSource *source;
     IMFPresentationDescriptor *descriptor;
     IMFSourceReaderCallback *async_callback;
@@ -203,6 +204,51 @@ static struct media_stream *impl_stream_from_IMFVideoSampleAllocatorNotify(IMFVi
     return CONTAINING_RECORD(iface, struct media_stream, notify_cb);
 }
 
+static void source_reader_release_responses(struct source_reader *reader, struct media_stream *stream);
+
+static ULONG source_reader_addref(struct source_reader *reader)
+{
+    return InterlockedIncrement(&reader->refcount);
+}
+
+static ULONG source_reader_release(struct source_reader *reader)
+{
+    ULONG refcount = InterlockedDecrement(&reader->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)
+            IMFAttributes_Release(reader->attributes);
+        IMFMediaSource_Release(reader->source);
+
+        for (i = 0; i < reader->stream_count; ++i)
+        {
+            struct media_stream *stream = &reader->streams[i];
+
+            if (stream->stream)
+                IMFMediaStream_Release(stream->stream);
+            if (stream->current)
+                IMFMediaType_Release(stream->current);
+            if (stream->decoder.transform)
+                IMFTransform_Release(stream->decoder.transform);
+            if (stream->allocator)
+                IMFVideoSampleAllocatorEx_Release(stream->allocator);
+        }
+        source_reader_release_responses(reader, NULL);
+        free(reader->streams);
+        MFUnlockWorkQueue(reader->queue);
+        DeleteCriticalSection(&reader->cs);
+        free(reader);
+    }
+
+    return refcount;
+}
+
 static HRESULT WINAPI source_reader_async_command_QueryInterface(IUnknown *iface, REFIID riid, void **obj)
 {
     if (IsEqualIID(riid, &IID_IUnknown))
@@ -325,13 +371,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 source_reader_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 source_reader_release(reader);
 }
 
 static HRESULT WINAPI source_reader_callback_GetParameters(IMFAsyncCallback *iface,
@@ -611,13 +657,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 source_reader_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 source_reader_release(reader);
 }
 
 static HRESULT source_reader_pull_stream_samples(struct source_reader *reader, struct media_stream *stream)
@@ -888,13 +934,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 source_reader_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 source_reader_release(reader);
 }
 
 static struct stream_response * media_stream_detach_response(struct source_reader *reader, struct stream_response *response)
@@ -1326,7 +1372,7 @@ static HRESULT WINAPI src_reader_QueryInterface(IMFSourceReader *iface, REFIID r
 static ULONG WINAPI src_reader_AddRef(IMFSourceReader *iface)
 {
     struct source_reader *reader = impl_from_IMFSourceReader(iface);
-    ULONG refcount = InterlockedIncrement(&reader->refcount);
+    ULONG refcount = InterlockedIncrement(&reader->public_refcount);
 
     TRACE("%p, refcount %u.\n", iface, refcount);
 
@@ -1336,41 +1382,15 @@ static ULONG WINAPI src_reader_AddRef(IMFSourceReader *iface)
 static ULONG WINAPI src_reader_Release(IMFSourceReader *iface)
 {
     struct source_reader *reader = impl_from_IMFSourceReader(iface);
-    ULONG refcount = InterlockedDecrement(&reader->refcount);
-    unsigned int i;
+    ULONG refcount = InterlockedDecrement(&reader->public_refcount);
 
     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);
-        if (reader->descriptor)
-            IMFPresentationDescriptor_Release(reader->descriptor);
-        if (reader->attributes)
-            IMFAttributes_Release(reader->attributes);
-        IMFMediaSource_Release(reader->source);
-
-        for (i = 0; i < reader->stream_count; ++i)
-        {
-            struct media_stream *stream = &reader->streams[i];
-
-            if (stream->stream)
-                IMFMediaStream_Release(stream->stream);
-            if (stream->current)
-                IMFMediaType_Release(stream->current);
-            if (stream->decoder.transform)
-                IMFTransform_Release(stream->decoder.transform);
-            if (stream->allocator)
-                IMFVideoSampleAllocatorEx_Release(stream->allocator);
-        }
-        source_reader_release_responses(reader, NULL);
-        free(reader->streams);
-        MFUnlockWorkQueue(reader->queue);
-        DeleteCriticalSection(&reader->cs);
-        free(reader);
+        source_reader_release(reader);
     }
 
     return refcount;
@@ -2268,6 +2288,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->public_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 f484925b28a..8417a0d37b7 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, "Unexpected refcount %u.\n", refcount);
 
     /* Async mode. */
     callback = create_async_callback();




More information about the wine-cvs mailing list