Nikolay Sivov : mfreadwrite/reader: Consider end-of-stream state when picking stream for MF_SOURCE_READER_ANY_STREAM requests.

Alexandre Julliard julliard at winehq.org
Fri May 15 16:55:06 CDT 2020


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

Author: Nikolay Sivov <nsivov at codeweavers.com>
Date:   Fri May 15 16:03:50 2020 +0300

mfreadwrite/reader: Consider end-of-stream state when picking stream for MF_SOURCE_READER_ANY_STREAM requests.

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

---

 dlls/mfreadwrite/reader.c | 60 +++++++++++++++++++++++++++++++++--------------
 1 file changed, 43 insertions(+), 17 deletions(-)

diff --git a/dlls/mfreadwrite/reader.c b/dlls/mfreadwrite/reader.c
index eaf52ce31e..e69c2b980b 100644
--- a/dlls/mfreadwrite/reader.c
+++ b/dlls/mfreadwrite/reader.c
@@ -114,6 +114,7 @@ struct media_stream
     enum media_stream_state state;
     unsigned int flags;
     unsigned int requests;
+    unsigned int responses;
 };
 
 enum source_reader_async_op
@@ -360,6 +361,7 @@ static void source_reader_queue_response(struct source_reader *reader, struct me
         IMFSample_AddRef(response->sample);
 
     list_add_tail(&reader->responses, &response->entry);
+    stream->responses++;
 
     if (stream->requests)
     {
@@ -831,6 +833,22 @@ static ULONG WINAPI source_reader_async_commands_callback_Release(IMFAsyncCallba
     return IMFSourceReader_Release(&reader->IMFSourceReader_iface);
 }
 
+static struct stream_response * media_stream_detach_response(struct source_reader *reader, struct stream_response *response)
+{
+    struct media_stream *stream;
+
+    list_remove(&response->entry);
+
+    if (response->stream_index < reader->stream_count)
+    {
+        stream = &reader->streams[response->stream_index];
+        if (stream->responses)
+            --stream->responses;
+    }
+
+    return response;
+}
+
 static struct stream_response *media_stream_pop_response(struct source_reader *reader, struct media_stream *stream)
 {
     struct stream_response *response;
@@ -841,20 +859,13 @@ static struct stream_response *media_stream_pop_response(struct source_reader *r
         LIST_FOR_EACH_ENTRY(response, &reader->responses, struct stream_response, entry)
         {
             if (response->stream_index == stream->index)
-            {
-                list_remove(&response->entry);
-                return response;
-            }
+                return media_stream_detach_response(reader, response);
         }
     }
     else
     {
         if ((head = list_head(&reader->responses)))
-        {
-            response = LIST_ENTRY(head, struct stream_response, entry);
-            list_remove(&response->entry);
-            return response;
-        }
+            return media_stream_detach_response(reader, LIST_ENTRY(head, struct stream_response, entry));
     }
 
     return NULL;
@@ -979,20 +990,35 @@ static BOOL source_reader_get_read_result(struct source_reader *reader, struct m
 static HRESULT source_reader_get_first_selected_stream(struct source_reader *reader, unsigned int flags,
         unsigned int *stream_index)
 {
-    unsigned int i;
-    BOOL selected;
+    unsigned int i, first_selected = ~0u;
+    BOOL selected, stream_drained;
 
     for (i = 0; i < reader->stream_count; ++i)
     {
-        source_reader_get_stream_selection(reader, i, &selected);
-        if (SUCCEEDED(source_reader_get_stream_selection(reader, i, &selected)) && selected &&
-                !(reader->streams[i].flags & flags))
+        stream_drained = reader->streams[i].state == STREAM_STATE_EOS && !reader->streams[i].responses;
+        selected = SUCCEEDED(source_reader_get_stream_selection(reader, i, &selected)) && selected;
+
+        if (selected && !(reader->streams[i].flags & flags))
         {
-            *stream_index = i;
-            break;
+            if (first_selected == ~0u)
+                first_selected = i;
+
+            if (!stream_drained)
+            {
+                *stream_index = i;
+                break;
+            }
         }
     }
 
+    /* If all selected streams reached EOS, use first selected. This fallback only applies after reader went through all
+       selected streams once. */
+    if (i == reader->stream_count && first_selected != ~0u && !flags)
+    {
+        *stream_index = first_selected;
+        i = first_selected;
+    }
+
     return i == reader->stream_count ? MF_E_MEDIA_SOURCE_NO_STREAMS_SELECTED : S_OK;
 }
 
@@ -1046,7 +1072,7 @@ static void source_reader_release_responses(struct source_reader *reader, struct
         {
             continue;
         }
-        list_remove(&ptr->entry);
+        media_stream_detach_response(reader, ptr);
         source_reader_release_response(ptr);
     }
 }




More information about the wine-cvs mailing list