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