[PATCH 0/5] MR5399: mfreadwrite: Pass the D3D device manager to the stream transforms.
From: Rémi Bernon <rbernon(a)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); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/5399
From: Rémi Bernon <rbernon(a)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; } -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/5399
From: Rémi Bernon <rbernon(a)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); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/5399
From: Rémi Bernon <rbernon(a)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); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/5399
From: Rémi Bernon <rbernon(a)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; } -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/5399
Are you sure device manager is set regardless of d3d-awareness attributes? -- https://gitlab.winehq.org/wine/wine/-/merge_requests/5399#note_65989
I'm not sure and you're probably right, I'll see how to validate that. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/5399#note_65999
There might also be some logic to enable d3d path only when whole transform chain supports it. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/5399#note_66009
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. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/5399#note_66273
This merge request was closed by Rémi Bernon. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/5399
participants (2)
-
Nikolay Sivov (@nsivov) -
Rémi Bernon