Signed-off-by: Derek Lesho dlesho@codeweavers.com --- dlls/mfreadwrite/main.c | 114 +++++++++++++++++++++++++++++++--------- 1 file changed, 90 insertions(+), 24 deletions(-)
diff --git a/dlls/mfreadwrite/main.c b/dlls/mfreadwrite/main.c index 34b394f77d..d69daddc65 100644 --- a/dlls/mfreadwrite/main.c +++ b/dlls/mfreadwrite/main.c @@ -963,7 +963,7 @@ static HRESULT WINAPI src_reader_SetCurrentPosition(IMFSourceReader *iface, REFG return IMFMediaSource_Start(reader->source, reader->descriptor, format, position); }
-static IMFSample *media_stream_pop_sample(struct media_stream *stream, DWORD *stream_flags) +static IMFSample *media_stream_pop_sample(struct media_stream *stream) { IMFSample *ret = NULL; struct list *head; @@ -976,8 +976,6 @@ static IMFSample *media_stream_pop_sample(struct media_stream *stream, DWORD *st heap_free(pending_sample); }
- *stream_flags = stream->state == STREAM_STATE_EOS ? MF_SOURCE_READERF_ENDOFSTREAM : 0; - return ret; }
@@ -1016,6 +1014,91 @@ static HRESULT source_reader_start_source(struct source_reader *reader) return hr; }
+static IMFSample *next_source_sample(struct media_stream *stream) +{ + IMFSample *ret; + HRESULT hr; + + EnterCriticalSection(&stream->cs); + + while (list_empty(&stream->samples) && stream->state != STREAM_STATE_EOS) + { + if (stream->stream) + { + if (FAILED(hr = IMFMediaStream_RequestSample(stream->stream, NULL))) + WARN("Sample request failed, hr %#x.\n", hr); + } + SleepConditionVariableCS(&stream->sample_event, &stream->cs, INFINITE); + } + + ret = media_stream_pop_sample(stream); + + LeaveCriticalSection(&stream->cs); + + return ret; +} + +static HRESULT next_sample(struct media_stream *stream, IMFSample **out_sample, DWORD *stream_flags, BOOL drain) +{ + HRESULT hr = S_OK; + + *stream_flags = 0; + *out_sample = NULL; + + if (stream->decoder) + { + DWORD status; + MFT_OUTPUT_DATA_BUFFER out_buffer = {}; + + out_buffer.dwStreamID = 0; + for(;;) + { + if (list_empty(&stream->samples) && (stream->state == STREAM_STATE_EOS || drain)) + { + hr = IMFTransform_ProcessMessage(stream->decoder, MFT_MESSAGE_COMMAND_DRAIN, 0); + if (FAILED(hr)) + return hr; + } + + hr = IMFTransform_ProcessOutput(stream->decoder, 0, 1, &out_buffer, &status); + if (hr == S_OK) + { + *out_sample = out_buffer.pSample; + return hr; + } + else if (hr == MF_E_TRANSFORM_NEED_MORE_INPUT) + { + IMFSample *next_sample = drain ? media_stream_pop_sample(stream) : next_source_sample(stream); + if (!next_sample) + { + *stream_flags = MF_SOURCE_READERF_ENDOFSTREAM; + return S_OK; + } + + hr = IMFTransform_ProcessInput(stream->decoder, 0, next_sample, 0); + if (hr == MF_E_NOTACCEPTING) + { + ERR("ProcessInput returned MF_E_NOTACCEPTING after ProcessOutput returned MF_E_TRANSFORM_NEED_MORE_INPUT\n"); + IMFSample_Release(next_sample); + } + if (hr != S_OK) + return hr; + } + else + { + return hr; + } + } + } + else + { + *out_sample = drain ? media_stream_pop_sample(stream) : next_source_sample(stream); + if (stream->state == STREAM_STATE_EOS) + *stream_flags = MF_SOURCE_READERF_ENDOFSTREAM; + return S_OK; + } +} + static HRESULT source_reader_read_sample(struct source_reader *reader, DWORD index, DWORD flags, DWORD *actual_index, DWORD *stream_flags, LONGLONG *timestamp, IMFSample **sample) { @@ -1062,31 +1145,14 @@ static HRESULT source_reader_read_sample(struct source_reader *reader, DWORD ind *actual_index = stream_index;
stream = &reader->streams[stream_index]; - - EnterCriticalSection(&stream->cs); - if (SUCCEEDED(hr = source_reader_start_source(reader))) { - if (!(flags & MF_SOURCE_READER_CONTROLF_DRAIN)) - { - while (list_empty(&stream->samples) && stream->state != STREAM_STATE_EOS) - { - if (stream->stream) - { - if (FAILED(hr = IMFMediaStream_RequestSample(stream->stream, NULL))) - WARN("Sample request failed, hr %#x.\n", hr); - } - SleepConditionVariableCS(&stream->sample_event, &stream->cs, INFINITE); - } - } - - *sample = media_stream_pop_sample(stream, stream_flags); + if (FAILED(hr = next_sample(stream, sample, stream_flags, flags & MF_SOURCE_READER_CONTROLF_DRAIN))) + WARN("Failed to get sample, hr = %#x.\n", hr); + else + TRACE("Got sample %p.\n", *sample); }
- LeaveCriticalSection(&stream->cs); - - TRACE("Got sample %p.\n", *sample); - if (timestamp) { /* TODO: it's possible timestamp has to be set for some events.