From: Rémi Bernon rbernon@codeweavers.com
--- dlls/mfreadwrite/reader.c | 64 +++++++++++++++++++-------------------- 1 file changed, 32 insertions(+), 32 deletions(-)
diff --git a/dlls/mfreadwrite/reader.c b/dlls/mfreadwrite/reader.c index b77b5f9c538..6c990a17809 100644 --- a/dlls/mfreadwrite/reader.c +++ b/dlls/mfreadwrite/reader.c @@ -2620,6 +2620,38 @@ static HRESULT create_source_reader_from_source(IMFMediaSource *source, IMFAttri InitializeConditionVariable(&object->state_event); InitializeConditionVariable(&object->stop_event);
+ if (attributes) + { + object->attributes = attributes; + IMFAttributes_AddRef(object->attributes); + + IMFAttributes_GetUnknown(attributes, &MF_SOURCE_READER_ASYNC_CALLBACK, &IID_IMFSourceReaderCallback, + (void **)&object->async_callback); + if (object->async_callback) + TRACE("Using async callback %p.\n", object->async_callback); + + IMFAttributes_GetUnknown(attributes, &MF_SOURCE_READER_D3D_MANAGER, &IID_IUnknown, (void **)&object->device_manager); + if (object->device_manager) + { + IUnknown *unk = NULL; + + if (SUCCEEDED(IUnknown_QueryInterface(object->device_manager, &IID_IMFDXGIDeviceManager, (void **)&unk))) + object->flags |= SOURCE_READER_DXGI_DEVICE_MANAGER; + else if (SUCCEEDED(IUnknown_QueryInterface(object->device_manager, &IID_IDirect3DDeviceManager9, (void **)&unk))) + object->flags |= SOURCE_READER_D3D9_DEVICE_MANAGER; + + if (!(object->flags & (SOURCE_READER_HAS_DEVICE_MANAGER))) + { + WARN("Unknown device manager.\n"); + IUnknown_Release(object->device_manager); + object->device_manager = NULL; + } + + if (unk) + IUnknown_Release(unk); + } + } + if (FAILED(hr = IMFMediaSource_CreatePresentationDescriptor(object->source, &object->descriptor))) goto failed;
@@ -2689,38 +2721,6 @@ static HRESULT create_source_reader_from_source(IMFMediaSource *source, IMFAttri goto failed; }
- if (attributes) - { - object->attributes = attributes; - IMFAttributes_AddRef(object->attributes); - - IMFAttributes_GetUnknown(attributes, &MF_SOURCE_READER_ASYNC_CALLBACK, &IID_IMFSourceReaderCallback, - (void **)&object->async_callback); - if (object->async_callback) - TRACE("Using async callback %p.\n", object->async_callback); - - IMFAttributes_GetUnknown(attributes, &MF_SOURCE_READER_D3D_MANAGER, &IID_IUnknown, (void **)&object->device_manager); - if (object->device_manager) - { - IUnknown *unk = NULL; - - if (SUCCEEDED(IUnknown_QueryInterface(object->device_manager, &IID_IMFDXGIDeviceManager, (void **)&unk))) - object->flags |= SOURCE_READER_DXGI_DEVICE_MANAGER; - else if (SUCCEEDED(IUnknown_QueryInterface(object->device_manager, &IID_IDirect3DDeviceManager9, (void **)&unk))) - object->flags |= SOURCE_READER_D3D9_DEVICE_MANAGER; - - if (!(object->flags & (SOURCE_READER_HAS_DEVICE_MANAGER))) - { - WARN("Unknown device manager.\n"); - IUnknown_Release(object->device_manager); - object->device_manager = NULL; - } - - if (unk) - IUnknown_Release(unk); - } - } - if (FAILED(hr = MFLockSharedWorkQueue(L"", 0, NULL, &object->queue))) WARN("Failed to acquired shared queue, hr %#lx.\n", hr);
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/mfreadwrite/reader.c | 38 ++++++++++++++++++-------------------- 1 file changed, 18 insertions(+), 20 deletions(-)
diff --git a/dlls/mfreadwrite/reader.c b/dlls/mfreadwrite/reader.c index 6c990a17809..b9a5667bc57 100644 --- a/dlls/mfreadwrite/reader.c +++ b/dlls/mfreadwrite/reader.c @@ -1864,31 +1864,12 @@ static HRESULT source_reader_setup_sample_allocator(struct source_reader *reader { struct media_stream *stream = &reader->streams[index]; IMFAttributes *attributes = NULL; - GUID major = { 0 }; HRESULT hr;
- IMFMediaType_GetMajorType(stream->current, &major); - if (!IsEqualGUID(&major, &MFMediaType_Video)) - return S_OK; - - if (!(reader->flags & SOURCE_READER_HAS_DEVICE_MANAGER)) - return S_OK; - if (!stream->allocator) - { - if (FAILED(hr = MFCreateVideoSampleAllocatorEx(&IID_IMFVideoSampleAllocatorEx, (void **)&stream->allocator))) - { - WARN("Failed to create sample allocator, hr %#lx.\n", hr); - return hr; - } - } + return S_OK;
IMFVideoSampleAllocatorEx_UninitializeSampleAllocator(stream->allocator); - if (FAILED(hr = IMFVideoSampleAllocatorEx_SetDirectXManager(stream->allocator, reader->device_manager))) - { - WARN("Failed to set device manager, hr %#lx.\n", hr); - return hr; - }
if (FAILED(hr = source_reader_create_sample_allocator_attributes(reader, &attributes))) WARN("Failed to create allocator attributes, hr %#lx.\n", hr); @@ -2667,10 +2648,12 @@ static HRESULT create_source_reader_from_source(IMFMediaSource *source, IMFAttri /* Set initial current media types. */ for (i = 0; i < object->stream_count; ++i) { + IMFVideoSampleAllocatorEx *allocator = NULL; IMFMediaTypeHandler *handler; IMFStreamDescriptor *sd; IMFMediaType *src_type; BOOL selected; + GUID major;
list_init(&object->streams[i].transforms);
@@ -2698,6 +2681,21 @@ static HRESULT create_source_reader_from_source(IMFMediaSource *source, IMFAttri if (FAILED(hr)) break;
+ if (SUCCEEDED(IMFMediaType_GetMajorType(src_type, &major)) && IsEqualGUID(&major, &MFMediaType_Video) + && (object->flags & SOURCE_READER_HAS_DEVICE_MANAGER)) + { + if (FAILED(hr = MFCreateVideoSampleAllocatorEx(&IID_IMFVideoSampleAllocatorEx, (void **)&allocator))) + WARN("Failed to create sample allocator, hr %#lx.\n", hr); + else if (FAILED(hr = IMFVideoSampleAllocatorEx_SetDirectXManager(allocator, + object->device_manager))) + { + WARN("Failed to set device manager, hr %#lx.\n", hr); + IMFVideoSampleAllocatorEx_Release(allocator); + allocator = NULL; + } + } + + object->streams[i].allocator = allocator; object->streams[i].reader = object; object->streams[i].index = i; }
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);
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/mfreadwrite/reader.c | 72 ++++++++------------------------------- 1 file changed, 14 insertions(+), 58 deletions(-)
diff --git a/dlls/mfreadwrite/reader.c b/dlls/mfreadwrite/reader.c index 901a724e662..d926db49d1d 100644 --- a/dlls/mfreadwrite/reader.c +++ b/dlls/mfreadwrite/reader.c @@ -171,6 +171,7 @@ struct source_reader struct media_stream *streams; struct list responses; CRITICAL_SECTION cs; + CONDITION_VARIABLE allocator_cond; CONDITION_VARIABLE sample_event; CONDITION_VARIABLE state_event; CONDITION_VARIABLE stop_event; @@ -426,39 +427,6 @@ static void source_reader_response_ready(struct source_reader *reader, struct st stream->requests--; }
-static void source_reader_copy_sample_buffer(IMFSample *src, IMFSample *dst) -{ - IMFMediaBuffer *buffer; - LONGLONG time; - DWORD flags; - HRESULT hr; - - IMFSample_CopyAllItems(src, (IMFAttributes *)dst); - - IMFSample_SetSampleDuration(dst, 0); - IMFSample_SetSampleTime(dst, 0); - IMFSample_SetSampleFlags(dst, 0); - - if (SUCCEEDED(IMFSample_GetSampleDuration(src, &time))) - IMFSample_SetSampleDuration(dst, time); - - if (SUCCEEDED(IMFSample_GetSampleTime(src, &time))) - IMFSample_SetSampleTime(dst, time); - - if (SUCCEEDED(IMFSample_GetSampleFlags(src, &flags))) - IMFSample_SetSampleFlags(dst, flags); - - if (SUCCEEDED(IMFSample_ConvertToContiguousBuffer(src, NULL))) - { - if (SUCCEEDED(IMFSample_GetBufferByIndex(dst, 0, &buffer))) - { - if (FAILED(hr = IMFSample_CopyToBuffer(src, buffer))) - WARN("Failed to copy a buffer, hr %#lx.\n", hr); - IMFMediaBuffer_Release(buffer); - } - } -} - static HRESULT source_reader_queue_response(struct source_reader *reader, struct media_stream *stream, HRESULT status, DWORD stream_flags, LONGLONG timestamp, IMFSample *sample) { @@ -677,13 +645,20 @@ static ULONG WINAPI source_reader_stream_events_callback_Release(IMFAsyncCallbac return source_reader_release(reader); }
-static HRESULT source_reader_allocate_stream_sample(MFT_OUTPUT_STREAM_INFO *info, IMFSample **out) +static HRESULT source_reader_allocate_stream_sample(struct source_reader *reader, struct media_stream *stream, + MFT_OUTPUT_STREAM_INFO *info, IMFSample **out) { IMFMediaBuffer *buffer; IMFSample *sample; HRESULT hr;
- *out = NULL; + if (stream->allocator) + { + while ((hr = IMFVideoSampleAllocatorEx_AllocateSample(stream->allocator, out)) == MF_E_SAMPLEALLOCATOR_EMPTY) + SleepConditionVariableCS(&reader->allocator_cond, &reader->cs, INFINITE); + return hr; + } + if (FAILED(hr = MFCreateSample(&sample))) return hr; if (SUCCEEDED(hr = MFCreateAlignedMemoryBuffer(info->cbSize, info->cbAlignment, &buffer))) @@ -790,7 +765,7 @@ static HRESULT source_reader_pull_transform_samples(struct source_reader *reader IMFMediaType *output_type, *media_type;
if (!(stream_info.dwFlags & (MFT_OUTPUT_STREAM_PROVIDES_SAMPLES | MFT_OUTPUT_STREAM_CAN_PROVIDE_SAMPLES)) - && FAILED(hr = source_reader_allocate_stream_sample(&stream_info, &out_buffer.pSample))) + && FAILED(hr = source_reader_allocate_stream_sample(reader, stream, &stream_info, &out_buffer.pSample))) break;
if (SUCCEEDED(hr = IMFTransform_ProcessOutput(entry->transform, 0, 1, &out_buffer, &status))) @@ -1113,8 +1088,6 @@ static struct stream_response * media_stream_detach_response(struct source_reade static struct stream_response *media_stream_pop_response(struct source_reader *reader, struct media_stream *stream) { struct stream_response *response; - IMFSample *sample; - HRESULT hr;
LIST_FOR_EACH_ENTRY(response, &reader->responses, struct stream_response, entry) { @@ -1123,26 +1096,6 @@ static struct stream_response *media_stream_pop_response(struct source_reader *r
if (!stream) stream = &reader->streams[response->stream_index];
- if (response->sample && stream->allocator) - { - /* Return allocation error to the caller, while keeping original response sample in for later. */ - if (SUCCEEDED(hr = IMFVideoSampleAllocatorEx_AllocateSample(stream->allocator, &sample))) - { - source_reader_copy_sample_buffer(response->sample, sample); - IMFSample_Release(response->sample); - response->sample = sample; - } - else - { - if (!(response = calloc(1, sizeof(*response)))) - return NULL; - - response->status = hr; - response->stream_flags = MF_SOURCE_READERF_ERROR; - return response; - } - } - return media_stream_detach_response(reader, response); }
@@ -2584,7 +2537,9 @@ static ULONG WINAPI reader_sample_notify_Release(IMFVideoSampleAllocatorNotify *
static HRESULT WINAPI reader_sample_notify_NotifyRelease(IMFVideoSampleAllocatorNotify *iface) { + struct source_reader *reader = impl_from_IMFVideoSampleAllocatorNotify(iface); TRACE("iface %p\n", iface); + WakeAllConditionVariable(&reader->allocator_cond); return S_OK; }
@@ -2660,6 +2615,7 @@ static HRESULT create_source_reader_from_source(IMFMediaSource *source, IMFAttri object->source = source; IMFMediaSource_AddRef(object->source); InitializeCriticalSection(&object->cs); + InitializeConditionVariable(&object->allocator_cond); InitializeConditionVariable(&object->sample_event); InitializeConditionVariable(&object->state_event); InitializeConditionVariable(&object->stop_event);
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/mfreadwrite/reader.c | 6 ++++++ 1 file changed, 6 insertions(+)
diff --git a/dlls/mfreadwrite/reader.c b/dlls/mfreadwrite/reader.c index d926db49d1d..f59c25ae744 100644 --- a/dlls/mfreadwrite/reader.c +++ b/dlls/mfreadwrite/reader.c @@ -2022,6 +2022,12 @@ static HRESULT source_reader_create_decoder_for_stream(struct source_reader *rea IMFMediaType_Release(output_type); }
+ if (reader->device_manager) + { + IMFTransform_ProcessMessage(entry->transform, MFT_MESSAGE_SET_D3D_MANAGER, + (ULONG_PTR)reader->device_manager); + } + IMFMediaType_Release(input_type); return S_OK; }
Are you sure device manager is set regardless of d3d-awareness attributes?
I'm not sure and you're probably right, I'll see how to validate that.
There might also be some logic to enable d3d path only when whole transform chain supports it.
I wrote some tests in https://gitlab.winehq.org/wine/wine/-/merge_requests/5412, shows that D3D awareness is quite flexible. I'll update this MR after the other gets merged to adjust the implementation to what the tests are showing.
This merge request was closed by Rémi Bernon.