From: RĂ©mi Bernon rbernon@codeweavers.com
This resolves circular dependency, with source and streams holding references to the callbacks, subscribed to their event queues.
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com ---
Replaces 226173.
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();