[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