[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