[v3 PATCH 2/2] mfreadwrite: Pass source samples through decoder as they arrive.

Nikolay Sivov nsivov at codeweavers.com
Fri Mar 20 07:16:57 CDT 2020


From: Derek Lesho <dlesho at codeweavers.com>

Signed-off-by: Nikolay Sivov <nsivov at codeweavers.com>
---

- moved decoding calls to event handler, queue now always contains processed samples;
- removed draining logic for now, I believe we can do that explicitly on ReadSample() or
  on EndOfStream instead. Same helper could be used for sync/async read and EOS event;
- added a check for output transform flags;

 dlls/mfreadwrite/main.c | 81 +++++++++++++++++++++++++++++++++++------
 1 file changed, 69 insertions(+), 12 deletions(-)

diff --git a/dlls/mfreadwrite/main.c b/dlls/mfreadwrite/main.c
index d3c10a4d11..052575c100 100644
--- a/dlls/mfreadwrite/main.c
+++ b/dlls/mfreadwrite/main.c
@@ -366,6 +366,71 @@ static ULONG WINAPI source_reader_stream_events_callback_Release(IMFAsyncCallbac
     return IMFSourceReader_Release(&reader->IMFSourceReader_iface);
 }
 
+static void source_reader_queue_sample(struct media_stream *stream, IMFSample *sample)
+{
+    struct sample *pending_sample;
+
+    if (!sample)
+        return;
+
+    pending_sample = heap_alloc(sizeof(*pending_sample));
+    pending_sample->sample = sample;
+    IMFSample_AddRef(pending_sample->sample);
+
+    list_add_tail(&stream->samples, &pending_sample->entry);
+}
+
+static HRESULT source_reader_process_sample(struct media_stream *stream, IMFSample *sample)
+{
+    MFT_OUTPUT_STREAM_INFO stream_info = { 0 };
+    MFT_OUTPUT_DATA_BUFFER out_buffer;
+    DWORD status;
+    HRESULT hr;
+
+    if (!stream->decoder)
+    {
+        source_reader_queue_sample(stream, sample);
+        return S_OK;
+    }
+
+    /* It's assumed that decoder has 1 input and 1 output, both id's are 0. */
+
+    if (FAILED(hr = IMFTransform_GetOutputStreamInfo(stream->decoder, 0, &stream_info)))
+    {
+        WARN("Failed to get output stream info, hr %#x.\n", hr);
+        return hr;
+    }
+
+    if (!(stream_info.dwFlags & MFT_OUTPUT_STREAM_PROVIDES_SAMPLES))
+    {
+        FIXME("Transform does not provide samples.\n");
+        return E_NOTIMPL;
+    }
+
+    while (hr == S_OK)
+    {
+        memset(&out_buffer, 0, sizeof(out_buffer));
+        if (SUCCEEDED(hr = IMFTransform_ProcessOutput(stream->decoder, 0, 1, &out_buffer, &status)))
+        {
+            source_reader_queue_sample(stream, out_buffer.pSample);
+            if (out_buffer.pSample)
+                IMFSample_Release(out_buffer.pSample);
+            if (out_buffer.pEvents)
+                IMFCollection_Release(out_buffer.pEvents);
+        }
+    }
+
+    if (hr == MF_E_TRANSFORM_NEED_MORE_INPUT)
+    {
+        if (FAILED(hr = IMFTransform_ProcessInput(stream->decoder, 0, sample, 0)))
+            WARN("Transform failed to process input, hr %#x.\n", hr);
+    }
+    else
+        WARN("Transform failed to process output, hr %#x.\n", hr);
+
+    return hr;
+}
+
 static HRESULT source_reader_media_sample_handler(struct source_reader *reader, IMFMediaStream *stream,
         IMFMediaEvent *event)
 {
@@ -393,21 +458,14 @@ static HRESULT source_reader_media_sample_handler(struct source_reader *reader,
     {
         if (id == reader->streams[i].id)
         {
-            struct sample *pending_sample;
-
-            if (!(pending_sample = heap_alloc(sizeof(*pending_sample))))
-            {
-                hr = E_OUTOFMEMORY;
-                goto failed;
-            }
+            EnterCriticalSection(&reader->streams[i].cs);
 
-            pending_sample->sample = sample;
-            IMFSample_AddRef(pending_sample->sample);
+            hr = source_reader_process_sample(&reader->streams[i], sample);
 
-            EnterCriticalSection(&reader->streams[i].cs);
-            list_add_tail(&reader->streams[i].samples, &pending_sample->entry);
             LeaveCriticalSection(&reader->streams[i].cs);
 
+            /* FIXME: propagate processing errors? */
+
             WakeAllConditionVariable(&reader->streams[i].sample_event);
 
             break;
@@ -417,7 +475,6 @@ static HRESULT source_reader_media_sample_handler(struct source_reader *reader,
     if (i == reader->stream_count)
         WARN("Stream with id %#x was not present in presentation descriptor.\n", id);
 
-failed:
     IMFSample_Release(sample);
 
     return hr;
-- 
2.25.1




More information about the wine-devel mailing list