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@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
bbfb164e0a
commit
be85638b5b
|
@ -154,6 +154,7 @@ struct source_reader
|
||||||
IMFAsyncCallback stream_events_callback;
|
IMFAsyncCallback stream_events_callback;
|
||||||
IMFAsyncCallback async_commands_callback;
|
IMFAsyncCallback async_commands_callback;
|
||||||
LONG refcount;
|
LONG refcount;
|
||||||
|
LONG public_refcount;
|
||||||
IMFMediaSource *source;
|
IMFMediaSource *source;
|
||||||
IMFPresentationDescriptor *descriptor;
|
IMFPresentationDescriptor *descriptor;
|
||||||
IMFSourceReaderCallback *async_callback;
|
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);
|
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)
|
static HRESULT WINAPI source_reader_async_command_QueryInterface(IUnknown *iface, REFIID riid, void **obj)
|
||||||
{
|
{
|
||||||
if (IsEqualIID(riid, &IID_IUnknown))
|
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)
|
static ULONG WINAPI source_reader_source_events_callback_AddRef(IMFAsyncCallback *iface)
|
||||||
{
|
{
|
||||||
struct source_reader *reader = impl_from_source_callback_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)
|
static ULONG WINAPI source_reader_source_events_callback_Release(IMFAsyncCallback *iface)
|
||||||
{
|
{
|
||||||
struct source_reader *reader = impl_from_source_callback_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,
|
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)
|
static ULONG WINAPI source_reader_stream_events_callback_AddRef(IMFAsyncCallback *iface)
|
||||||
{
|
{
|
||||||
struct source_reader *reader = impl_from_stream_callback_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)
|
static ULONG WINAPI source_reader_stream_events_callback_Release(IMFAsyncCallback *iface)
|
||||||
{
|
{
|
||||||
struct source_reader *reader = impl_from_stream_callback_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)
|
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)
|
static ULONG WINAPI source_reader_async_commands_callback_AddRef(IMFAsyncCallback *iface)
|
||||||
{
|
{
|
||||||
struct source_reader *reader = impl_from_async_commands_callback_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)
|
static ULONG WINAPI source_reader_async_commands_callback_Release(IMFAsyncCallback *iface)
|
||||||
{
|
{
|
||||||
struct source_reader *reader = impl_from_async_commands_callback_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)
|
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)
|
static ULONG WINAPI src_reader_AddRef(IMFSourceReader *iface)
|
||||||
{
|
{
|
||||||
struct source_reader *reader = impl_from_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);
|
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)
|
static ULONG WINAPI src_reader_Release(IMFSourceReader *iface)
|
||||||
{
|
{
|
||||||
struct source_reader *reader = impl_from_IMFSourceReader(iface);
|
struct source_reader *reader = impl_from_IMFSourceReader(iface);
|
||||||
ULONG refcount = InterlockedDecrement(&reader->refcount);
|
ULONG refcount = InterlockedDecrement(&reader->public_refcount);
|
||||||
unsigned int i;
|
|
||||||
|
|
||||||
TRACE("%p, refcount %u.\n", iface, refcount);
|
TRACE("%p, refcount %u.\n", iface, refcount);
|
||||||
|
|
||||||
if (!refcount)
|
if (!refcount)
|
||||||
{
|
{
|
||||||
if (reader->async_callback)
|
|
||||||
IMFSourceReaderCallback_Release(reader->async_callback);
|
|
||||||
if (reader->flags & SOURCE_READER_SHUTDOWN_ON_RELEASE)
|
if (reader->flags & SOURCE_READER_SHUTDOWN_ON_RELEASE)
|
||||||
IMFMediaSource_Shutdown(reader->source);
|
IMFMediaSource_Shutdown(reader->source);
|
||||||
if (reader->descriptor)
|
source_reader_release(reader);
|
||||||
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;
|
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->source_events_callback.lpVtbl = &source_events_callback_vtbl;
|
||||||
object->stream_events_callback.lpVtbl = &stream_events_callback_vtbl;
|
object->stream_events_callback.lpVtbl = &stream_events_callback_vtbl;
|
||||||
object->async_commands_callback.lpVtbl = &async_commands_callback_vtbl;
|
object->async_commands_callback.lpVtbl = &async_commands_callback_vtbl;
|
||||||
|
object->public_refcount = 1;
|
||||||
object->refcount = 1;
|
object->refcount = 1;
|
||||||
list_init(&object->responses);
|
list_init(&object->responses);
|
||||||
if (shutdown_on_release)
|
if (shutdown_on_release)
|
||||||
|
|
|
@ -862,7 +862,8 @@ skip_read_sample:
|
||||||
hr = IMFSourceReader_Flush(reader, MF_SOURCE_READER_ALL_STREAMS);
|
hr = IMFSourceReader_Flush(reader, MF_SOURCE_READER_ALL_STREAMS);
|
||||||
ok(hr == S_OK, "Failed to flush all streams, hr %#x.\n", hr);
|
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. */
|
/* Async mode. */
|
||||||
callback = create_async_callback();
|
callback = create_async_callback();
|
||||||
|
|
Loading…
Reference in New Issue