Currently the source reader creates a sample allocator as soon as SetCurrentMediaType() is called. However on Windows if the output attribute MF_SA_D3D11_SHARED_WITHOUT_MUTEX is set on the transform after SetCurrentMediaType() is called, but before ReadSample() is called, the sample allocator will generate shareable samples.
In order to emulate the same behavior, we defer creating the sample allocator to the first ReadSample() call, so the most updated attributes are picked up.
With this and the previous two patches, some video playback bugs are solved for some games (e.g. Trailmakers, Rustler, TOHU and others) when using DXVK (wined3d doesn't currently support shared resources, so there is no way to check with it).
Signed-off-by: Giovanni Mascellani gmascellani@codeweavers.com --- Again, it's not easy to check that this is what's really happening on Windows. OTOH, AFAIK, neither we know that the sample allocator is created in SetCurrentMediaType(). --- dlls/mfreadwrite/reader.c | 30 ++++++++++++++++++++++++++---- 1 file changed, 26 insertions(+), 4 deletions(-)
diff --git a/dlls/mfreadwrite/reader.c b/dlls/mfreadwrite/reader.c index 2ff56f6e978..7ae9f88c4c4 100644 --- a/dlls/mfreadwrite/reader.c +++ b/dlls/mfreadwrite/reader.c @@ -1696,6 +1696,8 @@ static HRESULT source_reader_flush(struct source_reader *reader, unsigned int in return hr; }
+static HRESULT source_reader_setup_sample_allocator(struct source_reader *reader, unsigned int index); + static HRESULT WINAPI source_reader_async_commands_callback_Invoke(IMFAsyncCallback *iface, IMFAsyncResult *result) { struct source_reader *reader = impl_from_async_commands_callback_IMFAsyncCallback(iface); @@ -1725,7 +1727,15 @@ static HRESULT WINAPI source_reader_async_commands_callback_Invoke(IMFAsyncCallb { stream = &reader->streams[stream_index];
- if (!(report_sample = source_reader_get_read_result(reader, stream, command->u.read.flags, &status, + if (!stream->allocator) + { + hr = source_reader_setup_sample_allocator(reader, stream_index); + + if (FAILED(hr)) + WARN("Failed to setup the sample allocator, hr %#x.\n", hr); + } + + if (SUCCEEDED(hr) && !(report_sample = source_reader_get_read_result(reader, stream, command->u.read.flags, &status, &stream_index, &stream_flags, ×tamp, &sample))) { stream->requests++; @@ -2359,8 +2369,12 @@ static HRESULT WINAPI src_reader_SetCurrentMediaType(IMFSourceReader *iface, DWO hr = source_reader_create_decoder_for_stream(reader, index, type); else if (hr == S_OK) hr = source_reader_add_passthrough_transform(reader, index, reader->streams[index].current); - if (SUCCEEDED(hr)) - hr = source_reader_setup_sample_allocator(reader, index); + + if (reader->streams[index].allocator) + { + IMFVideoSampleAllocatorEx_Release(reader->streams[index].allocator); + reader->streams[index].allocator = NULL; + }
LeaveCriticalSection(&reader->cs);
@@ -2454,7 +2468,15 @@ static HRESULT source_reader_read_sample(struct source_reader *reader, DWORD ind
stream = &reader->streams[stream_index];
- if (!source_reader_get_read_result(reader, stream, flags, &hr, actual_index, stream_flags, + if (!stream->allocator) + { + hr = source_reader_setup_sample_allocator(reader, stream_index); + + if (FAILED(hr)) + WARN("Failed to setup the sample allocator, hr %#x.\n", hr); + } + + if (SUCCEEDED(hr) && !source_reader_get_read_result(reader, stream, flags, &hr, actual_index, stream_flags, timestamp, sample)) { while (!source_reader_got_response_for_stream(reader, stream) && stream->state != STREAM_STATE_EOS)