First part of some refactor to implement the source reader pipeline.
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/mfreadwrite/reader.c | 27 +++++++++++++-------------- 1 file changed, 13 insertions(+), 14 deletions(-)
diff --git a/dlls/mfreadwrite/reader.c b/dlls/mfreadwrite/reader.c index 057e771ca99..2ef8ade360d 100644 --- a/dlls/mfreadwrite/reader.c +++ b/dlls/mfreadwrite/reader.c @@ -463,6 +463,17 @@ static HRESULT source_reader_queue_response(struct source_reader *reader, struct return S_OK; }
+static HRESULT source_reader_queue_sample(struct source_reader *reader, struct media_stream *stream, + IMFSample *sample) +{ + LONGLONG timestamp = 0; + + if (FAILED(IMFSample_GetSampleTime(sample, ×tamp))) + WARN("Sample time wasn't set.\n"); + + return source_reader_queue_response(reader, stream, S_OK, 0, timestamp, sample); +} + static HRESULT source_reader_request_sample(struct source_reader *reader, struct media_stream *stream) { HRESULT hr = S_OK; @@ -650,7 +661,6 @@ static HRESULT source_reader_pull_stream_samples(struct source_reader *reader, s MFT_OUTPUT_DATA_BUFFER out_buffer; unsigned int buffer_size; IMFMediaBuffer *buffer; - LONGLONG timestamp; DWORD status; HRESULT hr;
@@ -688,11 +698,7 @@ static HRESULT source_reader_pull_stream_samples(struct source_reader *reader, s break; }
- timestamp = 0; - if (FAILED(IMFSample_GetSampleTime(out_buffer.pSample, ×tamp))) - WARN("Sample time wasn't set.\n"); - - source_reader_queue_response(reader, stream, S_OK /* FIXME */, 0, timestamp, out_buffer.pSample); + source_reader_queue_sample(reader, stream, out_buffer.pSample); if (out_buffer.pSample) IMFSample_Release(out_buffer.pSample); if (out_buffer.pEvents) @@ -705,17 +711,10 @@ static HRESULT source_reader_pull_stream_samples(struct source_reader *reader, s static HRESULT source_reader_process_sample(struct source_reader *reader, struct media_stream *stream, IMFSample *sample) { - LONGLONG timestamp; HRESULT hr;
if (!stream->decoder.transform) - { - timestamp = 0; - if (FAILED(IMFSample_GetSampleTime(sample, ×tamp))) - WARN("Sample time wasn't set.\n"); - - return source_reader_queue_response(reader, stream, S_OK, 0, timestamp, sample); - } + return source_reader_queue_sample(reader, stream, sample);
/* It's assumed that decoder has 1 input and 1 output, both id's are 0. */
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/mfreadwrite/reader.c | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-)
diff --git a/dlls/mfreadwrite/reader.c b/dlls/mfreadwrite/reader.c index 2ef8ade360d..3d3d8a2c31f 100644 --- a/dlls/mfreadwrite/reader.c +++ b/dlls/mfreadwrite/reader.c @@ -71,7 +71,7 @@ enum media_stream_flags STREAM_FLAG_STOPPED = 0x8, /* Received MEStreamStopped */ };
-struct stream_transform +struct transform_entry { IMFTransform *transform; unsigned int min_buffer_size; @@ -81,7 +81,7 @@ struct media_stream { IMFMediaStream *stream; IMFMediaType *current; - struct stream_transform decoder; + struct transform_entry decoder; IMFVideoSampleAllocatorEx *allocator; DWORD id; unsigned int index; @@ -655,7 +655,8 @@ static ULONG WINAPI source_reader_stream_events_callback_Release(IMFAsyncCallbac return source_reader_release(reader); }
-static HRESULT source_reader_pull_stream_samples(struct source_reader *reader, struct media_stream *stream) +static HRESULT source_reader_pull_transform_samples(struct source_reader *reader, struct media_stream *stream, + struct transform_entry *entry) { MFT_OUTPUT_STREAM_INFO stream_info = { 0 }; MFT_OUTPUT_DATA_BUFFER out_buffer; @@ -664,7 +665,7 @@ static HRESULT source_reader_pull_stream_samples(struct source_reader *reader, s DWORD status; HRESULT hr;
- if (FAILED(hr = IMFTransform_GetOutputStreamInfo(stream->decoder.transform, 0, &stream_info))) + if (FAILED(hr = IMFTransform_GetOutputStreamInfo(entry->transform, 0, &stream_info))) { WARN("Failed to get output stream info, hr %#lx.\n", hr); return hr; @@ -679,7 +680,7 @@ static HRESULT source_reader_pull_stream_samples(struct source_reader *reader, s if (FAILED(hr = MFCreateSample(&out_buffer.pSample))) break;
- buffer_size = max(stream_info.cbSize, stream->decoder.min_buffer_size); + buffer_size = max(stream_info.cbSize, entry->min_buffer_size);
if (FAILED(hr = MFCreateAlignedMemoryBuffer(buffer_size, stream_info.cbAlignment, &buffer))) { @@ -691,7 +692,7 @@ static HRESULT source_reader_pull_stream_samples(struct source_reader *reader, s IMFMediaBuffer_Release(buffer); }
- if (FAILED(hr = IMFTransform_ProcessOutput(stream->decoder.transform, 0, 1, &out_buffer, &status))) + if (FAILED(hr = IMFTransform_ProcessOutput(entry->transform, 0, 1, &out_buffer, &status))) { if (out_buffer.pSample) IMFSample_Release(out_buffer.pSample); @@ -718,7 +719,7 @@ static HRESULT source_reader_process_sample(struct source_reader *reader, struct
/* It's assumed that decoder has 1 input and 1 output, both id's are 0. */
- hr = source_reader_pull_stream_samples(reader, stream); + hr = source_reader_pull_transform_samples(reader, stream, &stream->decoder); if (hr == MF_E_TRANSFORM_NEED_MORE_INPUT) { if (FAILED(hr = IMFTransform_ProcessInput(stream->decoder.transform, 0, sample, 0))) @@ -727,7 +728,7 @@ static HRESULT source_reader_process_sample(struct source_reader *reader, struct return hr; }
- if ((hr = source_reader_pull_stream_samples(reader, stream)) == MF_E_TRANSFORM_NEED_MORE_INPUT) + if ((hr = source_reader_pull_transform_samples(reader, stream, &stream->decoder)) == MF_E_TRANSFORM_NEED_MORE_INPUT) return S_OK; } else @@ -821,7 +822,7 @@ static HRESULT source_reader_media_stream_state_handler(struct source_reader *re 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) + if ((hr = source_reader_pull_transform_samples(reader, stream, &stream->decoder)) != MF_E_TRANSFORM_NEED_MORE_INPUT) WARN("Failed to pull pending samples, hr %#lx.\n", hr); }
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/mfreadwrite/reader.c | 51 +++++++++++++++++++++------------------ 1 file changed, 28 insertions(+), 23 deletions(-)
diff --git a/dlls/mfreadwrite/reader.c b/dlls/mfreadwrite/reader.c index 3d3d8a2c31f..ed5ffa3b759 100644 --- a/dlls/mfreadwrite/reader.c +++ b/dlls/mfreadwrite/reader.c @@ -655,42 +655,47 @@ 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) +{ + IMFMediaBuffer *buffer; + IMFSample *sample; + HRESULT hr; + + *out = NULL; + if (FAILED(hr = MFCreateSample(&sample))) + return hr; + if (SUCCEEDED(hr = MFCreateAlignedMemoryBuffer(info->cbSize, info->cbAlignment, &buffer))) + { + if (SUCCEEDED(hr = IMFSample_AddBuffer(sample, buffer))) + { + *out = sample; + IMFSample_AddRef(sample); + } + IMFMediaBuffer_Release(buffer); + } + + IMFSample_Release(sample); + return hr; +} + static HRESULT source_reader_pull_transform_samples(struct source_reader *reader, struct media_stream *stream, struct transform_entry *entry) { MFT_OUTPUT_STREAM_INFO stream_info = { 0 }; - MFT_OUTPUT_DATA_BUFFER out_buffer; - unsigned int buffer_size; - IMFMediaBuffer *buffer; DWORD status; HRESULT hr;
if (FAILED(hr = IMFTransform_GetOutputStreamInfo(entry->transform, 0, &stream_info))) - { - WARN("Failed to get output stream info, hr %#lx.\n", hr); return hr; - } + stream_info.cbSize = max(stream_info.cbSize, entry->min_buffer_size);
for (;;) { - memset(&out_buffer, 0, sizeof(out_buffer)); - - if (!(stream_info.dwFlags & (MFT_OUTPUT_STREAM_PROVIDES_SAMPLES | MFT_OUTPUT_STREAM_CAN_PROVIDE_SAMPLES))) - { - if (FAILED(hr = MFCreateSample(&out_buffer.pSample))) - break; + MFT_OUTPUT_DATA_BUFFER out_buffer = {0};
- buffer_size = max(stream_info.cbSize, entry->min_buffer_size); - - if (FAILED(hr = MFCreateAlignedMemoryBuffer(buffer_size, stream_info.cbAlignment, &buffer))) - { - IMFSample_Release(out_buffer.pSample); - break; - } - - IMFSample_AddBuffer(out_buffer.pSample, buffer); - IMFMediaBuffer_Release(buffer); - } + 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))) + break;
if (FAILED(hr = IMFTransform_ProcessOutput(entry->transform, 0, 1, &out_buffer, &status))) {
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/mfreadwrite/reader.c | 40 ++++++++++++++++++++++++++++++++++----- 1 file changed, 35 insertions(+), 5 deletions(-)
diff --git a/dlls/mfreadwrite/reader.c b/dlls/mfreadwrite/reader.c index ed5ffa3b759..c47cd499985 100644 --- a/dlls/mfreadwrite/reader.c +++ b/dlls/mfreadwrite/reader.c @@ -714,6 +714,31 @@ static HRESULT source_reader_pull_transform_samples(struct source_reader *reader return hr; }
+static HRESULT source_reader_drain_transform_samples(struct source_reader *reader, struct media_stream *stream, + struct transform_entry *entry) +{ + HRESULT hr; + + if (FAILED(hr = IMFTransform_ProcessMessage(entry->transform, MFT_MESSAGE_COMMAND_DRAIN, 0))) + WARN("Failed to drain transform %p, hr %#lx\n", entry->transform, hr); + if (FAILED(hr = source_reader_pull_transform_samples(reader, stream, entry)) + && hr != MF_E_TRANSFORM_NEED_MORE_INPUT) + WARN("Failed to pull pending samples, hr %#lx.\n", hr); + + return S_OK; +} + +static HRESULT source_reader_flush_transform_samples(struct source_reader *reader, struct media_stream *stream, + struct transform_entry *entry) +{ + HRESULT hr; + + if (FAILED(hr = IMFTransform_ProcessMessage(entry->transform, MFT_MESSAGE_COMMAND_FLUSH, 0))) + WARN("Failed to flush transform %p, hr %#lx\n", entry->transform, hr); + + return S_OK; +} + static HRESULT source_reader_process_sample(struct source_reader *reader, struct media_stream *stream, IMFSample *sample) { @@ -824,11 +849,10 @@ 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.transform && SUCCEEDED(IMFTransform_ProcessMessage(stream->decoder.transform, - MFT_MESSAGE_COMMAND_DRAIN, 0))) + if (stream->decoder.transform) { - if ((hr = source_reader_pull_transform_samples(reader, stream, &stream->decoder)) != MF_E_TRANSFORM_NEED_MORE_INPUT) - WARN("Failed to pull pending samples, hr %#lx.\n", hr); + if (FAILED(hr = source_reader_drain_transform_samples(reader, stream, &stream->decoder))) + WARN("Failed to drain pending samples, hr %#lx.\n", hr); }
while (stream->requests) @@ -1187,10 +1211,16 @@ static void source_reader_release_responses(struct source_reader *reader, struct static void source_reader_flush_stream(struct source_reader *reader, DWORD stream_index) { struct media_stream *stream = &reader->streams[stream_index]; + HRESULT hr;
source_reader_release_responses(reader, stream); + if (stream->decoder.transform) - IMFTransform_ProcessMessage(stream->decoder.transform, MFT_MESSAGE_COMMAND_FLUSH, 0); + { + if (FAILED(hr = source_reader_flush_transform_samples(reader, stream, &stream->decoder))) + WARN("Failed to drain pending samples, hr %#lx.\n", hr); + } + stream->requests = 0; }
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/mfreadwrite/reader.c | 51 ++++++++++++++++++++------------------- 1 file changed, 26 insertions(+), 25 deletions(-)
diff --git a/dlls/mfreadwrite/reader.c b/dlls/mfreadwrite/reader.c index c47cd499985..6e895667ef6 100644 --- a/dlls/mfreadwrite/reader.c +++ b/dlls/mfreadwrite/reader.c @@ -678,6 +678,26 @@ static HRESULT source_reader_allocate_stream_sample(MFT_OUTPUT_STREAM_INFO *info return hr; }
+static HRESULT source_reader_pull_transform_samples(struct source_reader *reader, struct media_stream *stream, + struct transform_entry *entry); +static HRESULT source_reader_push_transform_samples(struct source_reader *reader, struct media_stream *stream, + struct transform_entry *entry, IMFSample *sample) +{ + HRESULT hr; + + do + { + if (FAILED(hr = source_reader_pull_transform_samples(reader, stream, entry)) + && hr != MF_E_TRANSFORM_NEED_MORE_INPUT) + return hr; + if (SUCCEEDED(hr = IMFTransform_ProcessInput(entry->transform, 0, sample, 0))) + return source_reader_pull_transform_samples(reader, stream, entry); + } + while (hr == MF_E_NOTACCEPTING); + + return hr; +} + static HRESULT source_reader_pull_transform_samples(struct source_reader *reader, struct media_stream *stream, struct transform_entry *entry) { @@ -689,7 +709,7 @@ static HRESULT source_reader_pull_transform_samples(struct source_reader *reader return hr; stream_info.cbSize = max(stream_info.cbSize, entry->min_buffer_size);
- for (;;) + while (SUCCEEDED(hr)) { MFT_OUTPUT_DATA_BUFFER out_buffer = {0};
@@ -697,14 +717,9 @@ static HRESULT source_reader_pull_transform_samples(struct source_reader *reader && FAILED(hr = source_reader_allocate_stream_sample(&stream_info, &out_buffer.pSample))) break;
- if (FAILED(hr = IMFTransform_ProcessOutput(entry->transform, 0, 1, &out_buffer, &status))) - { - if (out_buffer.pSample) - IMFSample_Release(out_buffer.pSample); - break; - } + if (SUCCEEDED(hr = IMFTransform_ProcessOutput(stream->decoder.transform, 0, 1, &out_buffer, &status))) + hr = source_reader_queue_sample(reader, stream, out_buffer.pSample);
- source_reader_queue_sample(reader, stream, out_buffer.pSample); if (out_buffer.pSample) IMFSample_Release(out_buffer.pSample); if (out_buffer.pEvents) @@ -748,19 +763,9 @@ static HRESULT source_reader_process_sample(struct source_reader *reader, struct return source_reader_queue_sample(reader, stream, sample);
/* It's assumed that decoder has 1 input and 1 output, both id's are 0. */ - - hr = source_reader_pull_transform_samples(reader, stream, &stream->decoder); - if (hr == MF_E_TRANSFORM_NEED_MORE_INPUT) - { - if (FAILED(hr = IMFTransform_ProcessInput(stream->decoder.transform, 0, sample, 0))) - { - WARN("Transform failed to process input, hr %#lx.\n", hr); - return hr; - } - - if ((hr = source_reader_pull_transform_samples(reader, stream, &stream->decoder)) == MF_E_TRANSFORM_NEED_MORE_INPUT) - return S_OK; - } + if (SUCCEEDED(hr = source_reader_push_transform_samples(reader, stream, &stream->decoder, sample)) + || hr == MF_E_TRANSFORM_NEED_MORE_INPUT) + hr = stream->requests ? source_reader_request_sample(reader, stream) : S_OK; else WARN("Transform failed to process output, hr %#lx.\n", hr);
@@ -797,12 +802,8 @@ static HRESULT source_reader_media_sample_handler(struct source_reader *reader, if (id == reader->streams[i].id) { /* FIXME: propagate processing errors? */ - reader->streams[i].flags &= ~STREAM_FLAG_SAMPLE_REQUESTED; hr = source_reader_process_sample(reader, &reader->streams[i], sample); - if (reader->streams[i].requests) - source_reader_request_sample(reader, &reader->streams[i]); - break; } }
This merge request was approved by Nikolay Sivov.