mfreadwrite/reader: Consider audio block alignment when creating output buffers for the decoder.

Signed-off-by: Nikolay Sivov <nsivov@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Nikolay Sivov 2021-03-22 10:33:42 +03:00 committed by Alexandre Julliard
parent c6f133f635
commit ca143521ed
1 changed files with 29 additions and 15 deletions

View File

@ -105,11 +105,17 @@ enum media_stream_flags
STREAM_FLAG_PRESENTED = 0x4, /* Set if stream was selected last time Start() was called. */
};
struct stream_transform
{
IMFTransform *transform;
unsigned int min_buffer_size;
};
struct media_stream
{
IMFMediaStream *stream;
IMFMediaType *current;
IMFTransform *decoder;
struct stream_transform decoder;
IMFVideoSampleAllocatorEx *allocator;
IMFVideoSampleAllocatorNotify notify_cb;
unsigned int id;
@ -643,12 +649,13 @@ static HRESULT source_reader_pull_stream_samples(struct source_reader *reader, s
{
MFT_OUTPUT_STREAM_INFO stream_info = { 0 };
MFT_OUTPUT_DATA_BUFFER out_buffer;
unsigned int buffer_size;
IMFMediaBuffer *buffer;
LONGLONG timestamp;
DWORD status;
HRESULT hr;
if (FAILED(hr = IMFTransform_GetOutputStreamInfo(stream->decoder, 0, &stream_info)))
if (FAILED(hr = IMFTransform_GetOutputStreamInfo(stream->decoder.transform, 0, &stream_info)))
{
WARN("Failed to get output stream info, hr %#x.\n", hr);
return hr;
@ -663,7 +670,9 @@ static HRESULT source_reader_pull_stream_samples(struct source_reader *reader, s
if (FAILED(hr = MFCreateSample(&out_buffer.pSample)))
break;
if (FAILED(hr = MFCreateAlignedMemoryBuffer(stream_info.cbSize, stream_info.cbAlignment, &buffer)))
buffer_size = max(stream_info.cbSize, stream->decoder.min_buffer_size);
if (FAILED(hr = MFCreateAlignedMemoryBuffer(buffer_size, stream_info.cbAlignment, &buffer)))
{
IMFSample_Release(out_buffer.pSample);
break;
@ -673,7 +682,7 @@ static HRESULT source_reader_pull_stream_samples(struct source_reader *reader, s
IMFMediaBuffer_Release(buffer);
}
if (FAILED(hr = IMFTransform_ProcessOutput(stream->decoder, 0, 1, &out_buffer, &status)))
if (FAILED(hr = IMFTransform_ProcessOutput(stream->decoder.transform, 0, 1, &out_buffer, &status)))
{
if (out_buffer.pSample)
IMFSample_Release(out_buffer.pSample);
@ -700,7 +709,7 @@ static HRESULT source_reader_process_sample(struct source_reader *reader, struct
LONGLONG timestamp;
HRESULT hr;
if (!stream->decoder)
if (!stream->decoder.transform)
{
timestamp = 0;
if (FAILED(IMFSample_GetSampleTime(sample, &timestamp)))
@ -715,7 +724,7 @@ static HRESULT source_reader_process_sample(struct source_reader *reader, struct
hr = source_reader_pull_stream_samples(reader, stream);
if (hr == MF_E_TRANSFORM_NEED_MORE_INPUT)
{
if (FAILED(hr = IMFTransform_ProcessInput(stream->decoder, 0, sample, 0)))
if (FAILED(hr = IMFTransform_ProcessInput(stream->decoder.transform, 0, sample, 0)))
{
WARN("Transform failed to process input, hr %#x.\n", hr);
return hr;
@ -812,7 +821,7 @@ static HRESULT source_reader_media_stream_state_handler(struct source_reader *re
stream->state = STREAM_STATE_EOS;
stream->flags &= ~STREAM_FLAG_SAMPLE_REQUESTED;
if (stream->decoder && SUCCEEDED(IMFTransform_ProcessMessage(stream->decoder,
if (stream->decoder.transform && SUCCEEDED(IMFTransform_ProcessMessage(stream->decoder.transform,
MFT_MESSAGE_COMMAND_DRAIN, 0)))
{
if ((hr = source_reader_pull_stream_samples(reader, stream)) != MF_E_TRANSFORM_NEED_MORE_INPUT)
@ -1161,8 +1170,8 @@ static void source_reader_flush_stream(struct source_reader *reader, DWORD strea
struct media_stream *stream = &reader->streams[stream_index];
source_reader_release_responses(reader, stream);
if (stream->decoder)
IMFTransform_ProcessMessage(stream->decoder, MFT_MESSAGE_COMMAND_FLUSH, 0);
if (stream->decoder.transform)
IMFTransform_ProcessMessage(stream->decoder.transform, MFT_MESSAGE_COMMAND_FLUSH, 0);
stream->requests = 0;
}
@ -1378,8 +1387,8 @@ static ULONG WINAPI src_reader_Release(IMFSourceReader *iface)
IMFMediaStream_Release(stream->stream);
if (stream->current)
IMFMediaType_Release(stream->current);
if (stream->decoder)
IMFTransform_Release(stream->decoder);
if (stream->decoder.transform)
IMFTransform_Release(stream->decoder.transform);
if (stream->allocator)
IMFVideoSampleAllocatorEx_Release(stream->allocator);
}
@ -1672,8 +1681,10 @@ static HRESULT source_reader_configure_decoder(struct source_reader *reader, DWO
IMFMediaType *input_type, IMFMediaType *output_type)
{
IMFMediaTypeHandler *type_handler;
unsigned int block_alignment = 0;
IMFTransform *transform = NULL;
IMFMediaType *type = NULL;
GUID major = { 0 };
DWORD flags;
HRESULT hr;
int i = 0;
@ -1710,12 +1721,15 @@ static HRESULT source_reader_configure_decoder(struct source_reader *reader, DWO
if (FAILED(hr = IMFMediaType_CopyAllItems(type, (IMFAttributes *)reader->streams[index].current)))
WARN("Failed to copy attributes, hr %#x.\n", hr);
if (SUCCEEDED(IMFMediaType_GetMajorType(type, &major)) && IsEqualGUID(&major, &MFMediaType_Audio))
IMFMediaType_GetUINT32(type, &MF_MT_AUDIO_BLOCK_ALIGNMENT, &block_alignment);
IMFMediaType_Release(type);
if (reader->streams[index].decoder)
IMFTransform_Release(reader->streams[index].decoder);
if (reader->streams[index].decoder.transform)
IMFTransform_Release(reader->streams[index].decoder.transform);
reader->streams[index].decoder = transform;
reader->streams[index].decoder.transform = transform;
reader->streams[index].decoder.min_buffer_size = block_alignment;
return S_OK;
}
@ -2082,7 +2096,7 @@ static HRESULT WINAPI src_reader_GetServiceForStream(IMFSourceReader *iface, DWO
hr = MF_E_INVALIDSTREAMNUMBER;
else
{
obj = (IUnknown *)reader->streams[index].decoder;
obj = (IUnknown *)reader->streams[index].decoder.transform;
if (!obj) hr = E_NOINTERFACE;
}
break;