[PATCH v2 2/2] mfreadwrite: Decode source's samples in IMFSourceReader::ReadSample.
Derek Lesho
dlesho at codeweavers.com
Wed Mar 18 12:50:12 CDT 2020
Signed-off-by: Derek Lesho <dlesho at 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.
--
2.25.1
More information about the wine-devel
mailing list