From: Rémi Bernon rbernon@codeweavers.com
--- dlls/mfreadwrite/reader.c | 101 +++++++++++++++++++++++++++++++------- 1 file changed, 82 insertions(+), 19 deletions(-)
diff --git a/dlls/mfreadwrite/reader.c b/dlls/mfreadwrite/reader.c index b9a5667bc57..901a724e662 100644 --- a/dlls/mfreadwrite/reader.c +++ b/dlls/mfreadwrite/reader.c @@ -154,6 +154,7 @@ struct source_reader IMFAsyncCallback source_events_callback; IMFAsyncCallback stream_events_callback; IMFAsyncCallback async_commands_callback; + IMFVideoSampleAllocatorNotify sample_notify_iface; LONG refcount; LONG public_refcount; IMFMediaSource *source; @@ -1550,6 +1551,24 @@ static BOOL source_reader_is_source_stopped(const struct source_reader *reader) return TRUE; }
+static HRESULT source_reader_uninit_sample_allocator(struct source_reader *reader, unsigned int index) +{ + struct media_stream *stream = &reader->streams[index]; + IMFVideoSampleAllocatorCallback *callback; + + if (!stream->allocator) + return S_OK; + + if (SUCCEEDED(IMFVideoSampleAllocatorEx_QueryInterface(stream->allocator, + &IID_IMFVideoSampleAllocatorCallback, (void **)&callback))) + { + IMFVideoSampleAllocatorCallback_SetCallback(callback, NULL); + IMFVideoSampleAllocatorCallback_Release(callback); + } + + return IMFVideoSampleAllocatorEx_UninitializeSampleAllocator(stream->allocator); +} + static ULONG WINAPI src_reader_Release(IMFSourceReaderEx *iface) { struct source_reader *reader = impl_from_IMFSourceReaderEx(iface); @@ -1575,20 +1594,7 @@ static ULONG WINAPI src_reader_Release(IMFSourceReaderEx *iface) }
for (i = 0; i < reader->stream_count; ++i) - { - struct media_stream *stream = &reader->streams[i]; - IMFVideoSampleAllocatorCallback *callback; - - if (!stream->allocator) - continue; - - if (SUCCEEDED(IMFVideoSampleAllocatorEx_QueryInterface(stream->allocator, &IID_IMFVideoSampleAllocatorCallback, - (void **)&callback))) - { - IMFVideoSampleAllocatorCallback_SetCallback(callback, NULL); - IMFVideoSampleAllocatorCallback_Release(callback); - } - } + source_reader_uninit_sample_allocator(reader, i);
source_reader_release(reader); } @@ -1860,17 +1866,16 @@ static HRESULT source_reader_create_sample_allocator_attributes(const struct sou return hr; }
-static HRESULT source_reader_setup_sample_allocator(struct source_reader *reader, unsigned int index) +static HRESULT source_reader_init_sample_allocator(struct source_reader *reader, unsigned int index) { struct media_stream *stream = &reader->streams[index]; + IMFVideoSampleAllocatorCallback *callback; IMFAttributes *attributes = NULL; HRESULT hr;
if (!stream->allocator) return S_OK;
- IMFVideoSampleAllocatorEx_UninitializeSampleAllocator(stream->allocator); - if (FAILED(hr = source_reader_create_sample_allocator_attributes(reader, &attributes))) WARN("Failed to create allocator attributes, hr %#lx.\n", hr);
@@ -1880,6 +1885,13 @@ static HRESULT source_reader_setup_sample_allocator(struct source_reader *reader WARN("Failed to initialize sample allocator, hr %#lx.\n", hr); }
+ if (SUCCEEDED(IMFVideoSampleAllocatorEx_QueryInterface(stream->allocator, + &IID_IMFVideoSampleAllocatorCallback, (void **)&callback))) + { + IMFVideoSampleAllocatorCallback_SetCallback(callback, &reader->sample_notify_iface); + IMFVideoSampleAllocatorCallback_Release(callback); + } + if (attributes) IMFAttributes_Release(attributes);
@@ -2094,11 +2106,13 @@ static HRESULT WINAPI src_reader_SetCurrentMediaType(IMFSourceReaderEx *iface, D
EnterCriticalSection(&reader->cs);
- hr = source_reader_set_compatible_media_type(reader, index, type); + hr = source_reader_uninit_sample_allocator(reader, index); + if (SUCCEEDED(hr)) + hr = source_reader_set_compatible_media_type(reader, index, type); if (hr == S_FALSE) hr = source_reader_create_decoder_for_stream(reader, index, type); if (SUCCEEDED(hr)) - hr = source_reader_setup_sample_allocator(reader, index); + hr = source_reader_init_sample_allocator(reader, index);
LeaveCriticalSection(&reader->cs);
@@ -2534,6 +2548,54 @@ static const IMFSourceReaderExVtbl srcreader_vtbl = src_reader_GetTransformForStream, };
+static struct source_reader *impl_from_IMFVideoSampleAllocatorNotify(IMFVideoSampleAllocatorNotify *iface) +{ + return CONTAINING_RECORD(iface, struct source_reader, sample_notify_iface); +} + +static HRESULT WINAPI reader_sample_notify_QueryInterface(IMFVideoSampleAllocatorNotify *iface, REFIID riid, void **obj) +{ + TRACE("iface %p, riid %s, obj %p.\n", iface, debugstr_guid(riid), obj); + + if (IsEqualGUID(riid, &IID_IUnknown) + || IsEqualGUID(riid, &IID_IMFVideoSampleAllocatorNotify)) + { + *obj = iface; + IMFVideoSampleAllocatorNotify_AddRef(iface); + return S_OK; + } + + WARN("Unsupported %s.\n", debugstr_guid(riid)); + *obj = NULL; + return E_NOINTERFACE; +} + +static ULONG WINAPI reader_sample_notify_AddRef(IMFVideoSampleAllocatorNotify *iface) +{ + struct source_reader *reader = impl_from_IMFVideoSampleAllocatorNotify(iface); + return source_reader_addref(reader); +} + +static ULONG WINAPI reader_sample_notify_Release(IMFVideoSampleAllocatorNotify *iface) +{ + struct source_reader *reader = impl_from_IMFVideoSampleAllocatorNotify(iface); + return source_reader_release(reader); +} + +static HRESULT WINAPI reader_sample_notify_NotifyRelease(IMFVideoSampleAllocatorNotify *iface) +{ + TRACE("iface %p\n", iface); + return S_OK; +} + +static const IMFVideoSampleAllocatorNotifyVtbl reader_sample_notify_vtbl = +{ + reader_sample_notify_QueryInterface, + reader_sample_notify_AddRef, + reader_sample_notify_Release, + reader_sample_notify_NotifyRelease, +}; + static DWORD reader_get_first_stream_index(IMFPresentationDescriptor *descriptor, const GUID *major) { DWORD count, i; @@ -2589,6 +2651,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->sample_notify_iface.lpVtbl = &reader_sample_notify_vtbl; object->public_refcount = 1; object->refcount = 1; list_init(&object->responses);