[PATCH 1/1] winegstreamer: reintroduce flushing for wg_parser

zlice wine at gitlab.winehq.org
Fri May 20 15:32:14 CDT 2022


From: zlice <zlice555 at gmail.com>

Previous commit removed flushing but this causes issues in some games.

- add flushing back
- move variable creation after initial condition returns in wm_reader_get_stream_sample. This caused some slow down.
- Remove EOS sets. Some are not what flushing did before. Had some seg faults on exiting Fallout 3 with them in.
---
 dlls/winegstreamer/gst_private.h   |  3 ++
 dlls/winegstreamer/main.c          | 10 +++++++
 dlls/winegstreamer/media_source.c  | 13 +++++----
 dlls/winegstreamer/quartz_parser.c |  6 ++++
 dlls/winegstreamer/unixlib.h       |  3 ++
 dlls/winegstreamer/wg_parser.c     | 44 ++++++++++++++++++++++++++++--
 dlls/winegstreamer/wm_reader.c     | 21 +++++++++-----
 7 files changed, 85 insertions(+), 15 deletions(-)

diff --git a/dlls/winegstreamer/gst_private.h b/dlls/winegstreamer/gst_private.h
index 2a4b16079c1..8b4b0f39bd7 100644
--- a/dlls/winegstreamer/gst_private.h
+++ b/dlls/winegstreamer/gst_private.h
@@ -70,6 +70,9 @@ void wg_parser_destroy(struct wg_parser *parser);
 HRESULT wg_parser_connect(struct wg_parser *parser, uint64_t file_size);
 void wg_parser_disconnect(struct wg_parser *parser);
 
+void wg_parser_begin_flush(struct wg_parser *parser);
+void wg_parser_end_flush(struct wg_parser *parser);
+
 bool wg_parser_get_next_read_offset(struct wg_parser *parser, uint64_t *offset, uint32_t *size);
 void wg_parser_push_data(struct wg_parser *parser, const void *data, uint32_t size);
 
diff --git a/dlls/winegstreamer/main.c b/dlls/winegstreamer/main.c
index c3adbb82d61..0ae96dac250 100644
--- a/dlls/winegstreamer/main.c
+++ b/dlls/winegstreamer/main.c
@@ -107,6 +107,16 @@ void wg_parser_disconnect(struct wg_parser *parser)
     __wine_unix_call(unix_handle, unix_wg_parser_disconnect, parser);
 }
 
+void wg_parser_begin_flush(struct wg_parser *parser)
+{
+    __wine_unix_call(unix_handle, unix_wg_parser_begin_flush, parser);
+}
+
+void wg_parser_end_flush(struct wg_parser *parser)
+{
+    __wine_unix_call(unix_handle, unix_wg_parser_end_flush, parser);
+}
+
 bool wg_parser_get_next_read_offset(struct wg_parser *parser, uint64_t *offset, uint32_t *size)
 {
     struct wg_parser_get_next_read_offset_params params =
diff --git a/dlls/winegstreamer/media_source.c b/dlls/winegstreamer/media_source.c
index f07b83f413e..e1040df045c 100644
--- a/dlls/winegstreamer/media_source.c
+++ b/dlls/winegstreamer/media_source.c
@@ -392,6 +392,7 @@ static void start_pipeline(struct media_source *source, struct source_async_comm
     if (position->vt == VT_I8)
         wg_parser_stream_seek(source->streams[0]->wg_stream, 1.0, position->hVal.QuadPart, 0,
                 AM_SEEKING_AbsolutePositioning, AM_SEEKING_NoPositioning);
+    wg_parser_end_flush(source->wg_parser);
 
     for (i = 0; i < source->stream_count; i++)
         flush_token_queue(source->streams[i], position->vt == VT_EMPTY);
@@ -419,6 +420,8 @@ static void stop_pipeline(struct media_source *source)
 {
     unsigned int i;
 
+    wg_parser_begin_flush(source->wg_parser);
+
     for (i = 0; i < source->stream_count; i++)
     {
         struct media_stream *stream = source->streams[i];
@@ -537,12 +540,10 @@ static void wait_on_sample(struct media_stream *stream, IUnknown *token)
     {
         send_buffer(stream, &buffer, token);
     }
-    else
-    {
-        stream->eos = TRUE;
-        IMFMediaEventQueue_QueueEventParamVar(stream->event_queue, MEEndOfStream, &GUID_NULL, S_OK, &empty_var);
-        dispatch_end_of_presentation(stream->parent_source);
-    }
+    /*
+      There was code here always setting EOS but previous versions
+      would return. Assuming EOS is set in wg_parser_stream_get_buffer.
+    */
 }
 
 static HRESULT WINAPI source_async_commands_Invoke(IMFAsyncCallback *iface, IMFAsyncResult *result)
diff --git a/dlls/winegstreamer/quartz_parser.c b/dlls/winegstreamer/quartz_parser.c
index 34848c0b503..e54ebac5e7d 100644
--- a/dlls/winegstreamer/quartz_parser.c
+++ b/dlls/winegstreamer/quartz_parser.c
@@ -973,6 +973,7 @@ static HRESULT parser_init_stream(struct strmbase_filter *iface)
         return S_OK;
 
     filter->streaming = true;
+    wg_parser_end_flush(filter->wg_parser);
 
     for (i = 0; i < filter->source_count; ++i)
     {
@@ -1030,6 +1031,7 @@ static HRESULT parser_cleanup_stream(struct strmbase_filter *iface)
         return S_OK;
 
     filter->streaming = false;
+    wg_parser_begin_flush(filter->wg_parser);
 
     for (i = 0; i < filter->source_count; ++i)
     {
@@ -1354,6 +1356,8 @@ static HRESULT WINAPI GST_Seeking_SetPositions(IMediaSeeking *iface,
 
     if (!(current_flags & AM_SEEKING_NoFlush))
     {
+        wg_parser_begin_flush(filter->wg_parser);
+
         for (i = 0; i < filter->source_count; ++i)
         {
             if (filter->sources[i]->pin.pin.peer)
@@ -1381,6 +1385,8 @@ static HRESULT WINAPI GST_Seeking_SetPositions(IMediaSeeking *iface,
 
     if (!(current_flags & AM_SEEKING_NoFlush))
     {
+        wg_parser_end_flush(filter->wg_parser);
+
         for (i = 0; i < filter->source_count; ++i)
         {
             struct parser_source *flush_pin = filter->sources[i];
diff --git a/dlls/winegstreamer/unixlib.h b/dlls/winegstreamer/unixlib.h
index 5911278530d..a00180f2cde 100644
--- a/dlls/winegstreamer/unixlib.h
+++ b/dlls/winegstreamer/unixlib.h
@@ -268,6 +268,9 @@ enum unix_funcs
     unix_wg_parser_connect,
     unix_wg_parser_disconnect,
 
+    unix_wg_parser_begin_flush,
+    unix_wg_parser_end_flush,
+
     unix_wg_parser_get_next_read_offset,
     unix_wg_parser_push_data,
 
diff --git a/dlls/winegstreamer/wg_parser.c b/dlls/winegstreamer/wg_parser.c
index 48b88a4b11c..d21e7b3f358 100644
--- a/dlls/winegstreamer/wg_parser.c
+++ b/dlls/winegstreamer/wg_parser.c
@@ -87,7 +87,7 @@ struct wg_parser
         GstFlowReturn ret;
     } read_request;
 
-    bool sink_connected;
+    bool flushing, sink_connected;
 
     bool unlimited_buffering;
 };
@@ -126,6 +126,35 @@ static NTSTATUS wg_parser_get_stream(void *args)
     return S_OK;
 }
 
+static NTSTATUS wg_parser_begin_flush(void *args)
+{
+    struct wg_parser *parser = args;
+    unsigned int i;
+
+    pthread_mutex_lock(&parser->mutex);
+    parser->flushing = true;
+    pthread_mutex_unlock(&parser->mutex);
+
+    for (i = 0; i < parser->stream_count; ++i)
+    {
+        if (parser->streams[i]->enabled)
+            pthread_cond_signal(&parser->streams[i]->event_cond);
+    }
+
+    return S_OK;
+}
+
+static NTSTATUS wg_parser_end_flush(void *args)
+{
+    struct wg_parser *parser = args;
+
+    pthread_mutex_lock(&parser->mutex);
+    parser->flushing = false;
+    pthread_mutex_unlock(&parser->mutex);
+
+    return S_OK;
+}
+
 static NTSTATUS wg_parser_get_next_read_offset(void *args)
 {
     struct wg_parser_get_next_read_offset_params *params = args;
@@ -270,9 +299,16 @@ static NTSTATUS wg_parser_stream_get_buffer(void *args)
 
     pthread_mutex_lock(&parser->mutex);
 
-    while (!stream->eos && !stream->buffer)
+    while (!parser->flushing && !stream->eos && !stream->buffer)
         pthread_cond_wait(&stream->event_cond, &parser->mutex);
 
+    if (parser->flushing)
+    {
+        pthread_mutex_unlock(&parser->mutex);
+        GST_DEBUG("Filter is flushing.\n");
+        return VFW_E_WRONG_STATE;
+    }
+
     /* Note that we can both have a buffer and stream->eos, in which case we
      * must return the buffer. */
     if ((buffer = stream->buffer))
@@ -1563,6 +1599,7 @@ static NTSTATUS wg_parser_create(void *args)
     pthread_cond_init(&parser->init_cond, NULL);
     pthread_cond_init(&parser->read_cond, NULL);
     pthread_cond_init(&parser->read_done_cond, NULL);
+    parser->flushing = true;
     parser->init_gst = init_funcs[params->type];
     parser->unlimited_buffering = params->unlimited_buffering;
 
@@ -1599,6 +1636,9 @@ const unixlib_entry_t __wine_unix_call_funcs[] =
     X(wg_parser_connect),
     X(wg_parser_disconnect),
 
+    X(wg_parser_begin_flush),
+    X(wg_parser_end_flush),
+
     X(wg_parser_get_next_read_offset),
     X(wg_parser_push_data),
 
diff --git a/dlls/winegstreamer/wm_reader.c b/dlls/winegstreamer/wm_reader.c
index 03adea8a318..ae109c79be5 100644
--- a/dlls/winegstreamer/wm_reader.c
+++ b/dlls/winegstreamer/wm_reader.c
@@ -1512,6 +1512,7 @@ static HRESULT init_stream(struct wm_reader *reader, QWORD file_size)
         wg_parser_stream_enable(stream->wg_stream, &stream->format);
     }
 
+    wg_parser_end_flush(reader->wg_parser);
     /* We probably discarded events because streams weren't enabled yet.
      * Now that they're all enabled seek back to the start again. */
     wg_parser_stream_seek(reader->streams[0].wg_stream, 1.0, 0, 0,
@@ -1878,10 +1879,6 @@ HRESULT wm_reader_get_stream_sample(struct wm_reader *reader, WORD stream_number
     struct wg_parser_stream *wg_stream;
     struct wg_parser_buffer wg_buffer;
     struct wm_stream *stream;
-    DWORD size, capacity;
-    INSSBuffer *sample;
-    HRESULT hr;
-    BYTE *data;
 
     for (;;)
     {
@@ -1914,16 +1911,26 @@ HRESULT wm_reader_get_stream_sample(struct wm_reader *reader, WORD stream_number
             if (stream->eos)
                 return NS_E_NO_MORE_SAMPLES;
 
+            /*
+              There was code here always setting EOS but previous versions
+              would return. Assuming EOS is set in wg_parser_stream_get_buffer.
+              EOS was set at the end of this func before.
+              Could use has_duration below?
+            */
             if (!wg_parser_stream_get_buffer(wg_stream, &wg_buffer))
             {
-                stream->eos = true;
-                TRACE("End of stream.\n");
-                return NS_E_NO_MORE_SAMPLES;
+                FIXME("Stream is flushing.\n");
+                return E_NOTIMPL;
             }
         }
 
         TRACE("Got buffer for '%s' stream %p.\n", get_major_type_string(stream->format.major_type), stream);
 
+        DWORD size, capacity;
+        INSSBuffer *sample;
+        HRESULT hr;
+        BYTE *data;
+
         if (callback_advanced && stream->read_compressed && stream->allocate_stream)
         {
             if (FAILED(hr = IWMReaderCallbackAdvanced_AllocateForStream(callback_advanced,
-- 
GitLab

https://gitlab.winehq.org/wine/wine/-/merge_requests/105



More information about the wine-devel mailing list