Nikolay Sivov : mfreadwrite/reader: Add support for reading to SA-allocated samples.

Alexandre Julliard julliard at winehq.org
Fri Feb 19 17:20:09 CST 2021


Module: wine
Branch: master
Commit: a67d7c15336ea5caa89099952da1fc1998188029
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=a67d7c15336ea5caa89099952da1fc1998188029

Author: Nikolay Sivov <nsivov at codeweavers.com>
Date:   Fri Feb 19 11:59:06 2021 +0300

mfreadwrite/reader: Add support for reading to SA-allocated samples.

Signed-off-by: Nikolay Sivov <nsivov at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/mfreadwrite/reader.c | 141 ++++++++++++++++++++++++++++++++++++----------
 1 file changed, 110 insertions(+), 31 deletions(-)

diff --git a/dlls/mfreadwrite/reader.c b/dlls/mfreadwrite/reader.c
index ec7d3fd62e6..9903898a155 100644
--- a/dlls/mfreadwrite/reader.c
+++ b/dlls/mfreadwrite/reader.c
@@ -85,6 +85,7 @@ struct stream_response
     DWORD stream_flags;
     LONGLONG timestamp;
     IMFSample *sample;
+    unsigned int sa_pending : 1;
 };
 
 enum media_stream_state
@@ -365,12 +366,83 @@ static HRESULT WINAPI source_reader_callback_GetParameters(IMFAsyncCallback *ifa
     return E_NOTIMPL;
 }
 
+static void source_reader_response_ready(struct source_reader *reader, struct stream_response *response)
+{
+    struct source_reader_async_command *command;
+    struct media_stream *stream = &reader->streams[response->stream_index];
+    HRESULT hr;
+
+    if (!stream->requests || response->sa_pending)
+        return;
+
+    if (reader->async_callback)
+    {
+        if (SUCCEEDED(source_reader_create_async_op(SOURCE_READER_ASYNC_SAMPLE_READY, &command)))
+        {
+            command->u.sample.stream_index = stream->index;
+            if (FAILED(hr = MFPutWorkItem(MFASYNC_CALLBACK_QUEUE_STANDARD, &reader->async_commands_callback,
+                    &command->IUnknown_iface)))
+                WARN("Failed to submit async result, hr %#x.\n", hr);
+            IUnknown_Release(&command->IUnknown_iface);
+        }
+    }
+    else
+        WakeAllConditionVariable(&reader->sample_event);
+
+    stream->requests--;
+}
+
+static void source_reader_copy_sample_buffer(IMFSample *src, IMFSample *dst)
+{
+    IMFMediaBuffer *buffer;
+    unsigned int flags;
+    LONGLONG time;
+    HRESULT hr;
+
+    IMFSample_CopyAllItems(src, (IMFAttributes *)dst);
+
+    IMFSample_SetSampleDuration(dst, 0);
+    IMFSample_SetSampleTime(dst, 0);
+    IMFSample_SetSampleFlags(dst, 0);
+
+    if (SUCCEEDED(IMFSample_GetSampleDuration(src, &time)))
+        IMFSample_SetSampleDuration(dst, time);
+
+    if (SUCCEEDED(IMFSample_GetSampleTime(src, &time)))
+        IMFSample_SetSampleTime(dst, time);
+
+    if (SUCCEEDED(IMFSample_GetSampleFlags(src, &flags)))
+        IMFSample_SetSampleFlags(dst, flags);
+
+    if (SUCCEEDED(IMFSample_ConvertToContiguousBuffer(src, NULL)))
+    {
+        if (SUCCEEDED(IMFSample_GetBufferByIndex(dst, 0, &buffer)))
+        {
+            if (FAILED(hr = IMFSample_CopyToBuffer(src, buffer)))
+                WARN("Failed to copy a buffer, hr %#x.\n", hr);
+            IMFMediaBuffer_Release(buffer);
+        }
+    }
+}
+
+static void source_reader_set_sa_response(struct source_reader *reader, struct stream_response *response)
+{
+    struct media_stream *stream = &reader->streams[response->stream_index];
+    IMFSample *sample;
+
+    if (SUCCEEDED(IMFVideoSampleAllocatorEx_AllocateSample(stream->allocator, &sample)))
+    {
+        source_reader_copy_sample_buffer(response->sample, sample);
+        response->sa_pending = 0;
+        IMFSample_Release(response->sample);
+        response->sample = sample;
+    }
+}
+
 static void source_reader_queue_response(struct source_reader *reader, struct media_stream *stream, HRESULT status,
         DWORD stream_flags, LONGLONG timestamp, IMFSample *sample)
 {
-    struct source_reader_async_command *command;
     struct stream_response *response;
-    HRESULT hr;
 
     response = heap_alloc_zero(sizeof(*response));
     response->status = status;
@@ -381,27 +453,16 @@ static void source_reader_queue_response(struct source_reader *reader, struct me
     if (response->sample)
         IMFSample_AddRef(response->sample);
 
+    if (response->sample && stream->allocator)
+    {
+        response->sa_pending = 1;
+        source_reader_set_sa_response(reader, response);
+    }
+
     list_add_tail(&reader->responses, &response->entry);
     stream->responses++;
 
-    if (stream->requests)
-    {
-        if (reader->async_callback)
-        {
-            if (SUCCEEDED(source_reader_create_async_op(SOURCE_READER_ASYNC_SAMPLE_READY, &command)))
-            {
-                command->u.sample.stream_index = stream->index;
-                if (FAILED(hr = MFPutWorkItem(MFASYNC_CALLBACK_QUEUE_STANDARD, &reader->async_commands_callback,
-                        &command->IUnknown_iface)))
-                    WARN("Failed to submit async result, hr %#x.\n", hr);
-                IUnknown_Release(&command->IUnknown_iface);
-            }
-        }
-        else
-            WakeAllConditionVariable(&reader->sample_event);
-
-        stream->requests--;
-    }
+    source_reader_response_ready(reader, response);
 }
 
 static HRESULT source_reader_request_sample(struct source_reader *reader, struct media_stream *stream)
@@ -874,20 +935,26 @@ static struct stream_response * media_stream_detach_response(struct source_reade
 static struct stream_response *media_stream_pop_response(struct source_reader *reader, struct media_stream *stream)
 {
     struct stream_response *response;
-    struct list *head;
 
-    if (stream)
+    LIST_FOR_EACH_ENTRY(response, &reader->responses, struct stream_response, entry)
     {
-        LIST_FOR_EACH_ENTRY(response, &reader->responses, struct stream_response, entry)
-        {
-            if (response->stream_index == stream->index)
-                return media_stream_detach_response(reader, response);
-        }
+        if ((stream && response->stream_index != stream->index) || response->sa_pending)
+            continue;
+
+        return media_stream_detach_response(reader, response);
     }
-    else
+
+    return NULL;
+}
+
+static struct stream_response *media_stream_pick_pending_response(struct source_reader *reader, unsigned int stream)
+{
+    struct stream_response *response;
+
+    LIST_FOR_EACH_ENTRY(response, &reader->responses, struct stream_response, entry)
     {
-        if ((head = list_head(&reader->responses)))
-            return media_stream_detach_response(reader, LIST_ENTRY(head, struct stream_response, entry));
+        if (response->stream_index == stream && response->sa_pending)
+            return response;
     }
 
     return NULL;
@@ -963,7 +1030,7 @@ static BOOL source_reader_got_response_for_stream(struct source_reader *reader,
 
     LIST_FOR_EACH_ENTRY(response, &reader->responses, struct stream_response, entry)
     {
-        if (response->stream_index == stream->index)
+        if (response->stream_index == stream->index && !response->sa_pending)
             return TRUE;
     }
 
@@ -1201,6 +1268,18 @@ static HRESULT WINAPI source_reader_async_commands_callback_Invoke(IMFAsyncCallb
 
             break;
 
+        case SOURCE_READER_ASYNC_SA_READY:
+
+            EnterCriticalSection(&reader->cs);
+            if ((response = media_stream_pick_pending_response(reader, command->u.sa.stream_index)))
+            {
+                source_reader_set_sa_response(reader, response);
+                source_reader_response_ready(reader, response);
+            }
+            LeaveCriticalSection(&reader->cs);
+
+            break;
+
         case SOURCE_READER_ASYNC_SAMPLE_READY:
 
             EnterCriticalSection(&reader->cs);




More information about the wine-cvs mailing list