Re-enable mfplat-streaming-support

We had reverted the current upstream winegreamer commits to allow
mfplat-streaming-support to be used within staging.  Hopefully the
patchset in question will be upstream shortly.
This commit is contained in:
Alistair Leslie-Hughes 2021-09-19 13:13:15 +10:00
parent fdcc8bec48
commit fc40539f6d
9 changed files with 1476 additions and 1 deletions

View File

@ -0,0 +1,29 @@
From 28339597a00da381c079c9d4f46b67780511c267 Mon Sep 17 00:00:00 2001
From: Alistair Leslie-Hughes <leslie_alistair@hotmail.com>
Date: Sun, 19 Sep 2021 13:07:56 +1000
Subject: [PATCH 1/6] Revert "winegstreamer: Fix return code in init_gst
failure case."
This reverts commit b9a7e961cdd39203866be38e90b1d901595d54ba.
---
dlls/winegstreamer/quartz_parser.c | 3 ---
1 file changed, 3 deletions(-)
diff --git a/dlls/winegstreamer/quartz_parser.c b/dlls/winegstreamer/quartz_parser.c
index a8e7e3d979f..5299f4dc2ed 100644
--- a/dlls/winegstreamer/quartz_parser.c
+++ b/dlls/winegstreamer/quartz_parser.c
@@ -982,10 +982,7 @@ static HRESULT parser_sink_connect(struct strmbase_sink *iface, IPin *peer, cons
goto err;
if (!filter->init_gst(filter))
- {
- hr = E_FAIL;
goto err;
- }
for (i = 0; i < filter->source_count; ++i)
{
--
2.33.0

View File

@ -0,0 +1,614 @@
From 1106d6f409e0876e72c73d71982519f5e6d7e1c5 Mon Sep 17 00:00:00 2001
From: Alistair Leslie-Hughes <leslie_alistair@hotmail.com>
Date: Sun, 19 Sep 2021 13:08:01 +1000
Subject: [PATCH 2/6] Revert "winegstreamer: Replace source pad interface with
GstAppSrc."
This reverts commit 1aa359a100bae859b278007e8bf90673eebd7db0.
---
dlls/winegstreamer/wg_parser.c | 425 ++++++++++++++++++++++++---------
1 file changed, 308 insertions(+), 117 deletions(-)
diff --git a/dlls/winegstreamer/wg_parser.c b/dlls/winegstreamer/wg_parser.c
index 6b6b033b879..f0815e37689 100644
--- a/dlls/winegstreamer/wg_parser.c
+++ b/dlls/winegstreamer/wg_parser.c
@@ -33,7 +33,6 @@
#include <gst/gst.h>
#include <gst/video/video.h>
#include <gst/audio/audio.h>
-#include <gst/app/gstappsrc.h>
/* GStreamer callbacks may be called on threads not created by Wine, and
* therefore cannot access the Wine TEB. This means that we must use GStreamer
@@ -50,20 +49,28 @@ struct wg_parser
struct wg_parser_stream **streams;
unsigned int stream_count;
- GstElement *container, *appsrc, *decodebin;
+ GstElement *container, *decodebin;
GstBus *bus;
+ GstPad *my_src, *their_sink;
+
+ guint64 file_size, start_offset, next_offset, stop_offset;
+ guint64 next_pull_offset;
+
+ pthread_t push_thread;
pthread_mutex_t mutex;
pthread_cond_t init_cond;
bool no_more_pads, has_duration, error;
- pthread_cond_t read_cond;
+ pthread_cond_t read_cond, read_done_cond;
struct
{
+ void *data;
uint64_t offset;
uint32_t size;
- bool pending;
+ bool done;
+ bool ret;
} read_request;
bool flushing, sink_connected;
@@ -515,7 +522,7 @@ static bool CDECL wg_parser_get_next_read_offset(struct wg_parser *parser,
{
pthread_mutex_lock(&parser->mutex);
- while (parser->sink_connected && !parser->read_request.pending)
+ while (parser->sink_connected && !parser->read_request.data)
pthread_cond_wait(&parser->read_cond, &parser->mutex);
if (!parser->sink_connected)
@@ -534,69 +541,15 @@ static bool CDECL wg_parser_get_next_read_offset(struct wg_parser *parser,
static void CDECL wg_parser_push_data(struct wg_parser *parser,
const void *data, uint32_t size)
{
- GstMessage *message;
- GstFlowReturn ret;
- GstBuffer *buffer;
- GError *error;
-
- if (!data)
- {
- pthread_mutex_lock(&parser->mutex);
-
- if (parser->sink_connected)
- {
- error = g_error_new(G_FILE_ERROR, G_FILE_ERROR_FAILED, "WG-Parser client failed to read data at offset %" G_GUINT64_FORMAT, parser->read_request.offset);
- message = gst_message_new_error(NULL, error, "");
- gst_bus_post(parser->bus, message);
- parser->read_request.pending = false;
- }
-
- pthread_mutex_unlock(&parser->mutex);
- return;
- }
-
- if (!size)
- {
- pthread_mutex_lock(&parser->mutex);
-
- if (parser->sink_connected)
- g_signal_emit_by_name(G_OBJECT(parser->appsrc), "end-of-stream", &ret);
- parser->read_request.pending = false;
-
- pthread_mutex_unlock(&parser->mutex);
- return;
- }
-
- /* We will always perform an extra blit here. We can avoid this in some
- * cases by wrapping a client-allocated buffer using
- * gst_buffer_new_wrapped(). However, releasing the memory is non-trivial,
- * since GStreamer will hold onto a reference for an arbitrarily long
- * period of time. Until there's evidence to suggest that the blit causes a
- * performance problem, leave it alone. */
- buffer = gst_buffer_new_and_alloc(size);
- gst_buffer_fill(buffer, 0, data, size);
-
pthread_mutex_lock(&parser->mutex);
-
- if (!parser->sink_connected)
- {
- pthread_mutex_unlock(&parser->mutex);
- gst_buffer_unref(buffer);
- return;
- }
-
- assert(parser->read_request.pending);
-
- GST_BUFFER_OFFSET(buffer) = parser->read_request.offset;
- g_signal_emit_by_name(G_OBJECT(parser->appsrc), "push-buffer", buffer, &ret);
-
- /* In random-access mode, GST_FLOW_EOS shouldn't be returned. */
- assert(ret == GST_FLOW_OK || ret == GST_FLOW_FLUSHING);
- if (ret == GST_FLOW_OK)
- parser->read_request.offset += size;
-
- parser->read_request.pending = false;
+ parser->read_request.size = size;
+ parser->read_request.done = true;
+ parser->read_request.ret = !!data;
+ if (data)
+ memcpy(parser->read_request.data, data, size);
+ parser->read_request.data = NULL;
pthread_mutex_unlock(&parser->mutex);
+ pthread_cond_signal(&parser->read_done_cond);
}
static void CDECL wg_parser_set_unlimited_buffering(struct wg_parser *parser)
@@ -1251,56 +1204,196 @@ static void pad_removed_cb(GstElement *element, GstPad *pad, gpointer user)
g_free(name);
}
-static void src_need_data(GstElement *appsrc, guint length, gpointer user)
+static GstFlowReturn src_getrange_cb(GstPad *pad, GstObject *parent,
+ guint64 offset, guint size, GstBuffer **buffer)
{
- struct wg_parser *parser = user;
- guint64 queued_bytes;
+ struct wg_parser *parser = gst_pad_get_element_private(pad);
+ GstBuffer *new_buffer = NULL;
+ GstMapInfo map_info;
+ bool ret;
+
+ GST_LOG("pad %p, offset %" G_GINT64_MODIFIER "u, length %u, buffer %p.", pad, offset, size, *buffer);
+
+ if (offset == GST_BUFFER_OFFSET_NONE)
+ offset = parser->next_pull_offset;
+ parser->next_pull_offset = offset + size;
+
+ if (!*buffer)
+ *buffer = new_buffer = gst_buffer_new_and_alloc(size);
+
+ gst_buffer_map(*buffer, &map_info, GST_MAP_WRITE);
pthread_mutex_lock(&parser->mutex);
- /* As of GStreamer 1.18, appsrc suffers from a race condition. When in
- * random access mode (and when underlyingly in pull mode), appsrc may
- * spuriously send multiple requests for the same offset and length. If it
- * receives the same buffer twice (or consecutive buffers), it will blindly
- * queue them and satisfy subsequent getrange requests from downstream
- * elements with the wrong buffers.
- *
- * Internally, this function is called inside of a loop, which also pops
- * buffers from the internal queue. Accordingly we can safely treat this
- * request as spurious by checking if we have already sent data; since the
- * data is consumed by this thread it will not have been consumed yet.
- *
- * The bug is documented in greater detail here:
- *
- * https://gitlab.freedesktop.org/gstreamer/gst-plugins-base/-/issues/937
- */
- g_object_get(G_OBJECT(appsrc), "current-level-bytes", &queued_bytes, NULL);
- if (queued_bytes)
+ assert(!parser->read_request.data);
+ parser->read_request.data = map_info.data;
+ parser->read_request.offset = offset;
+ parser->read_request.size = size;
+ parser->read_request.done = false;
+ pthread_cond_signal(&parser->read_cond);
+
+ /* Note that we don't unblock this wait on GST_EVENT_FLUSH_START. We expect
+ * the upstream pin to flush if necessary. We should never be blocked on
+ * read_thread() not running. */
+
+ while (!parser->read_request.done)
+ pthread_cond_wait(&parser->read_done_cond, &parser->mutex);
+
+ ret = parser->read_request.ret;
+ gst_buffer_set_size(*buffer, parser->read_request.size);
+
+ pthread_mutex_unlock(&parser->mutex);
+
+ gst_buffer_unmap(*buffer, &map_info);
+
+ GST_LOG("Request returned %d.", ret);
+
+ if ((!ret || !size) && new_buffer)
+ gst_buffer_unref(new_buffer);
+
+ if (ret)
+ return size ? GST_FLOW_OK : GST_FLOW_EOS;
+ return GST_FLOW_ERROR;
+}
+
+static gboolean src_query_cb(GstPad *pad, GstObject *parent, GstQuery *query)
+{
+ struct wg_parser *parser = gst_pad_get_element_private(pad);
+ GstFormat format;
+
+ GST_LOG("parser %p, type %s.", parser, GST_QUERY_TYPE_NAME(query));
+
+ switch (GST_QUERY_TYPE(query))
{
- pthread_mutex_unlock(&parser->mutex);
- return;
+ case GST_QUERY_DURATION:
+ gst_query_parse_duration(query, &format, NULL);
+ if (format == GST_FORMAT_PERCENT)
+ {
+ gst_query_set_duration(query, GST_FORMAT_PERCENT, GST_FORMAT_PERCENT_MAX);
+ return TRUE;
+ }
+ else if (format == GST_FORMAT_BYTES)
+ {
+ gst_query_set_duration(query, GST_FORMAT_BYTES, parser->file_size);
+ return TRUE;
+ }
+ return FALSE;
+
+ case GST_QUERY_SEEKING:
+ gst_query_parse_seeking (query, &format, NULL, NULL, NULL);
+ if (format != GST_FORMAT_BYTES)
+ {
+ GST_WARNING("Cannot seek using format \"%s\".", gst_format_get_name(format));
+ return FALSE;
+ }
+ gst_query_set_seeking(query, GST_FORMAT_BYTES, 1, 0, parser->file_size);
+ return TRUE;
+
+ case GST_QUERY_SCHEDULING:
+ gst_query_set_scheduling(query, GST_SCHEDULING_FLAG_SEEKABLE, 1, -1, 0);
+ gst_query_add_scheduling_mode(query, GST_PAD_MODE_PUSH);
+ gst_query_add_scheduling_mode(query, GST_PAD_MODE_PULL);
+ return TRUE;
+
+ default:
+ GST_WARNING("Unhandled query type %s.", GST_QUERY_TYPE_NAME(query));
+ return FALSE;
}
+}
- parser->read_request.pending = true;
- parser->read_request.size = length;
+static void *push_data(void *arg)
+{
+ struct wg_parser *parser = arg;
+ GstBuffer *buffer;
+ guint max_size;
- pthread_cond_signal(&parser->read_cond);
+ GST_DEBUG("Starting push thread.");
- pthread_mutex_unlock(&parser->mutex);
+ if (!(buffer = gst_buffer_new_allocate(NULL, 16384, NULL)))
+ {
+ GST_ERROR("Failed to allocate memory.");
+ return NULL;
+ }
+
+ max_size = parser->stop_offset ? parser->stop_offset : parser->file_size;
+
+ for (;;)
+ {
+ ULONG size;
+ int ret;
+
+ if (parser->next_offset >= max_size)
+ break;
+ size = min(16384, max_size - parser->next_offset);
+
+ if ((ret = src_getrange_cb(parser->my_src, NULL, parser->next_offset, size, &buffer)) < 0)
+ {
+ GST_ERROR("Failed to read data, ret %s.", gst_flow_get_name(ret));
+ break;
+ }
+
+ parser->next_offset += size;
+
+ buffer->duration = buffer->pts = -1;
+ if ((ret = gst_pad_push(parser->my_src, buffer)) < 0)
+ {
+ GST_ERROR("Failed to push data, ret %s.", gst_flow_get_name(ret));
+ break;
+ }
+ }
+
+ gst_buffer_unref(buffer);
+
+ gst_pad_push_event(parser->my_src, gst_event_new_eos());
+
+ GST_DEBUG("Stopping push thread.");
+
+ return NULL;
}
-static gboolean src_seek_data(GstElement *appsrc, guint64 offset, gpointer user)
+static gboolean activate_push(GstPad *pad, gboolean activate)
{
- struct wg_parser *parser = user;
+ struct wg_parser *parser = gst_pad_get_element_private(pad);
- pthread_mutex_lock(&parser->mutex);
+ if (!activate)
+ {
+ if (parser->push_thread)
+ {
+ pthread_join(parser->push_thread, NULL);
+ parser->push_thread = 0;
+ }
+ }
+ else if (!parser->push_thread)
+ {
+ int ret;
- assert(!parser->read_request.pending);
- parser->read_request.offset = offset;
+ if ((ret = pthread_create(&parser->push_thread, NULL, push_data, parser)))
+ {
+ GST_ERROR("Failed to create push thread: %s", strerror(errno));
+ parser->push_thread = 0;
+ return FALSE;
+ }
+ }
+ return TRUE;
+}
- pthread_mutex_unlock(&parser->mutex);
+static gboolean src_activate_mode_cb(GstPad *pad, GstObject *parent, GstPadMode mode, gboolean activate)
+{
+ struct wg_parser *parser = gst_pad_get_element_private(pad);
- return true;
+ GST_DEBUG("%s source pad for parser %p in %s mode.",
+ activate ? "Activating" : "Deactivating", parser, gst_pad_mode_get_name(mode));
+
+ switch (mode)
+ {
+ case GST_PAD_MODE_PULL:
+ return TRUE;
+ case GST_PAD_MODE_PUSH:
+ return activate_push(pad, activate);
+ case GST_PAD_MODE_NONE:
+ break;
+ }
+ return FALSE;
}
static GstBusSyncReply bus_handler_cb(GstBus *bus, GstMessage *msg, gpointer user)
@@ -1347,11 +1440,89 @@ static GstBusSyncReply bus_handler_cb(GstBus *bus, GstMessage *msg, gpointer use
return GST_BUS_DROP;
}
+static gboolean src_perform_seek(struct wg_parser *parser, GstEvent *event)
+{
+ BOOL thread = !!parser->push_thread;
+ GstSeekType cur_type, stop_type;
+ GstFormat seek_format;
+ GstEvent *flush_event;
+ GstSeekFlags flags;
+ gint64 cur, stop;
+ guint32 seqnum;
+ gdouble rate;
+
+ gst_event_parse_seek(event, &rate, &seek_format, &flags,
+ &cur_type, &cur, &stop_type, &stop);
+
+ if (seek_format != GST_FORMAT_BYTES)
+ {
+ GST_FIXME("Unhandled format \"%s\".", gst_format_get_name(seek_format));
+ return FALSE;
+ }
+
+ seqnum = gst_event_get_seqnum(event);
+
+ /* send flush start */
+ if (flags & GST_SEEK_FLAG_FLUSH)
+ {
+ flush_event = gst_event_new_flush_start();
+ gst_event_set_seqnum(flush_event, seqnum);
+ gst_pad_push_event(parser->my_src, flush_event);
+ if (thread)
+ gst_pad_set_active(parser->my_src, 1);
+ }
+
+ parser->next_offset = parser->start_offset = cur;
+
+ /* and prepare to continue streaming */
+ if (flags & GST_SEEK_FLAG_FLUSH)
+ {
+ flush_event = gst_event_new_flush_stop(TRUE);
+ gst_event_set_seqnum(flush_event, seqnum);
+ gst_pad_push_event(parser->my_src, flush_event);
+ if (thread)
+ gst_pad_set_active(parser->my_src, 1);
+ }
+
+ return TRUE;
+}
+
+static gboolean src_event_cb(GstPad *pad, GstObject *parent, GstEvent *event)
+{
+ struct wg_parser *parser = gst_pad_get_element_private(pad);
+ gboolean ret = TRUE;
+
+ GST_LOG("parser %p, type \"%s\".", parser, GST_EVENT_TYPE_NAME(event));
+
+ switch (event->type)
+ {
+ case GST_EVENT_SEEK:
+ ret = src_perform_seek(parser, event);
+ break;
+
+ case GST_EVENT_FLUSH_START:
+ case GST_EVENT_FLUSH_STOP:
+ case GST_EVENT_QOS:
+ case GST_EVENT_RECONFIGURE:
+ break;
+
+ default:
+ GST_WARNING("Ignoring \"%s\" event.", GST_EVENT_TYPE_NAME(event));
+ ret = FALSE;
+ break;
+ }
+ gst_event_unref(event);
+ return ret;
+}
+
static HRESULT CDECL wg_parser_connect(struct wg_parser *parser, uint64_t file_size)
{
+ GstStaticPadTemplate src_template = GST_STATIC_PAD_TEMPLATE("quartz_src",
+ GST_PAD_SRC, GST_PAD_ALWAYS, GST_STATIC_CAPS_ANY);
unsigned int i;
int ret;
+ parser->file_size = file_size;
parser->sink_connected = true;
if (!parser->bus)
@@ -1363,16 +1534,15 @@ static HRESULT CDECL wg_parser_connect(struct wg_parser *parser, uint64_t file_s
parser->container = gst_bin_new(NULL);
gst_element_set_bus(parser->container, parser->bus);
- if (!(parser->appsrc = create_element("appsrc", "base")))
- return E_FAIL;
- gst_bin_add(GST_BIN(parser->container), parser->appsrc);
+ parser->my_src = gst_pad_new_from_static_template(&src_template, "quartz-src");
+ gst_pad_set_getrange_function(parser->my_src, src_getrange_cb);
+ gst_pad_set_query_function(parser->my_src, src_query_cb);
+ gst_pad_set_activatemode_function(parser->my_src, src_activate_mode_cb);
+ gst_pad_set_event_function(parser->my_src, src_event_cb);
+ gst_pad_set_element_private(parser->my_src, parser);
- g_object_set(parser->appsrc, "stream-type", GST_APP_STREAM_TYPE_RANDOM_ACCESS, NULL);
- g_object_set(parser->appsrc, "size", file_size, NULL);
- g_signal_connect(parser->appsrc, "need-data", G_CALLBACK(src_need_data), parser);
- g_signal_connect(parser->appsrc, "seek-data", G_CALLBACK(src_seek_data), parser);
-
- parser->read_request.offset = 0;
+ parser->start_offset = parser->next_offset = parser->stop_offset = 0;
+ parser->next_pull_offset = 0;
parser->error = false;
if (!parser->init_gst(parser))
@@ -1468,11 +1638,18 @@ static HRESULT CDECL wg_parser_connect(struct wg_parser *parser, uint64_t file_s
pthread_mutex_unlock(&parser->mutex);
+ parser->next_offset = 0;
return S_OK;
out:
if (parser->container)
gst_element_set_state(parser->container, GST_STATE_NULL);
+ if (parser->their_sink)
+ {
+ gst_pad_unlink(parser->my_src, parser->their_sink);
+ gst_object_unref(parser->their_sink);
+ parser->my_src = parser->their_sink = NULL;
+ }
for (i = 0; i < parser->stream_count; ++i)
free_stream(parser->streams[i]);
@@ -1509,6 +1686,10 @@ static void CDECL wg_parser_disconnect(struct wg_parser *parser)
pthread_mutex_unlock(&parser->mutex);
gst_element_set_state(parser->container, GST_STATE_NULL);
+ gst_pad_unlink(parser->my_src, parser->their_sink);
+ gst_object_unref(parser->my_src);
+ gst_object_unref(parser->their_sink);
+ parser->my_src = parser->their_sink = NULL;
pthread_mutex_lock(&parser->mutex);
parser->sink_connected = false;
@@ -1530,6 +1711,7 @@ static void CDECL wg_parser_disconnect(struct wg_parser *parser)
static BOOL decodebin_parser_init_gst(struct wg_parser *parser)
{
GstElement *element;
+ int ret;
if (!(element = create_element("decodebin", "base")))
return FALSE;
@@ -1542,13 +1724,15 @@ static BOOL decodebin_parser_init_gst(struct wg_parser *parser)
g_signal_connect(element, "autoplug-select", G_CALLBACK(autoplug_select_cb), parser);
g_signal_connect(element, "no-more-pads", G_CALLBACK(no_more_pads_cb), parser);
+ parser->their_sink = gst_element_get_static_pad(element, "sink");
+
pthread_mutex_lock(&parser->mutex);
parser->no_more_pads = false;
pthread_mutex_unlock(&parser->mutex);
- if (!gst_element_link(parser->appsrc, parser->decodebin))
+ if ((ret = gst_pad_link(parser->my_src, parser->their_sink)) < 0)
{
- GST_ERROR("Failed to link appsrc.\n");
+ GST_ERROR("Failed to link pads, error %d.\n", ret);
return FALSE;
}
@@ -1558,6 +1742,7 @@ static BOOL decodebin_parser_init_gst(struct wg_parser *parser)
static BOOL avi_parser_init_gst(struct wg_parser *parser)
{
GstElement *element;
+ int ret;
if (!(element = create_element("avidemux", "good")))
return FALSE;
@@ -1568,13 +1753,15 @@ static BOOL avi_parser_init_gst(struct wg_parser *parser)
g_signal_connect(element, "pad-removed", G_CALLBACK(pad_removed_cb), parser);
g_signal_connect(element, "no-more-pads", G_CALLBACK(no_more_pads_cb), parser);
+ parser->their_sink = gst_element_get_static_pad(element, "sink");
+
pthread_mutex_lock(&parser->mutex);
parser->no_more_pads = false;
pthread_mutex_unlock(&parser->mutex);
- if (!gst_element_link(parser->appsrc, element))
+ if ((ret = gst_pad_link(parser->my_src, parser->their_sink)) < 0)
{
- GST_ERROR("Failed to link appsrc.\n");
+ GST_ERROR("Failed to link pads, error %d.\n", ret);
return FALSE;
}
@@ -1592,9 +1779,10 @@ static BOOL mpeg_audio_parser_init_gst(struct wg_parser *parser)
gst_bin_add(GST_BIN(parser->container), element);
- if (!gst_element_link(parser->appsrc, element))
+ parser->their_sink = gst_element_get_static_pad(element, "sink");
+ if ((ret = gst_pad_link(parser->my_src, parser->their_sink)) < 0)
{
- GST_ERROR("Failed to link appsrc.\n");
+ GST_ERROR("Failed to link sink pads, error %d.\n", ret);
return FALSE;
}
@@ -1625,9 +1813,10 @@ static BOOL wave_parser_init_gst(struct wg_parser *parser)
gst_bin_add(GST_BIN(parser->container), element);
- if (!gst_element_link(parser->appsrc, element))
+ parser->their_sink = gst_element_get_static_pad(element, "sink");
+ if ((ret = gst_pad_link(parser->my_src, parser->their_sink)) < 0)
{
- GST_ERROR("Failed to link appsrc.\n");
+ GST_ERROR("Failed to link sink pads, error %d.\n", ret);
return FALSE;
}
@@ -1658,6 +1847,7 @@ static struct wg_parser *wg_parser_create(void)
pthread_mutex_init(&parser->mutex, NULL);
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;
GST_DEBUG("Created winegstreamer parser %p.\n", parser);
@@ -1711,6 +1901,7 @@ static void CDECL wg_parser_destroy(struct wg_parser *parser)
pthread_mutex_destroy(&parser->mutex);
pthread_cond_destroy(&parser->init_cond);
pthread_cond_destroy(&parser->read_cond);
+ pthread_cond_destroy(&parser->read_done_cond);
free(parser);
}
--
2.33.0

View File

@ -0,0 +1,224 @@
From 2e341e32dd761e40c9045648b0edfabd9b49fc4e Mon Sep 17 00:00:00 2001
From: Alistair Leslie-Hughes <leslie_alistair@hotmail.com>
Date: Sun, 19 Sep 2021 13:08:02 +1000
Subject: [PATCH 3/6] Revert "winegstreamer: Allocate source media buffers in
the PE components."
This reverts commit 8b7390f80d866435f06f2571a93bcd67c0947673.
---
dlls/winegstreamer/gst_private.h | 7 +++----
dlls/winegstreamer/media_source.c | 28 ++++------------------------
dlls/winegstreamer/quartz_parser.c | 26 +++-----------------------
dlls/winegstreamer/wg_parser.c | 28 +++++++++++++---------------
4 files changed, 23 insertions(+), 66 deletions(-)
diff --git a/dlls/winegstreamer/gst_private.h b/dlls/winegstreamer/gst_private.h
index 49e06b31369..c29fc4a2437 100644
--- a/dlls/winegstreamer/gst_private.h
+++ b/dlls/winegstreamer/gst_private.h
@@ -170,10 +170,9 @@ struct unix_funcs
void (CDECL *wg_parser_begin_flush)(struct wg_parser *parser);
void (CDECL *wg_parser_end_flush)(struct wg_parser *parser);
- bool (CDECL *wg_parser_get_next_read_offset)(struct wg_parser *parser,
- uint64_t *offset, uint32_t *size);
- void (CDECL *wg_parser_push_data)(struct wg_parser *parser,
- const void *data, uint32_t size);
+ bool (CDECL *wg_parser_get_read_request)(struct wg_parser *parser,
+ void **data, uint64_t *offset, uint32_t *size);
+ void (CDECL *wg_parser_complete_read_request)(struct wg_parser *parser, bool ret);
void (CDECL *wg_parser_set_unlimited_buffering)(struct wg_parser *parser);
diff --git a/dlls/winegstreamer/media_source.c b/dlls/winegstreamer/media_source.c
index 825bad8da27..95bdb9b488e 100644
--- a/dlls/winegstreamer/media_source.c
+++ b/dlls/winegstreamer/media_source.c
@@ -530,11 +530,6 @@ static DWORD CALLBACK read_thread(void *arg)
{
struct media_source *source = arg;
IMFByteStream *byte_stream = source->byte_stream;
- uint32_t buffer_size = 0;
- uint64_t file_size;
- void *data = NULL;
-
- IMFByteStream_GetLength(byte_stream, &file_size);
TRACE("Starting read thread for media source %p.\n", source);
@@ -544,33 +539,18 @@ static DWORD CALLBACK read_thread(void *arg)
ULONG ret_size;
uint32_t size;
HRESULT hr;
+ void *data;
- if (!unix_funcs->wg_parser_get_next_read_offset(source->wg_parser, &offset, &size))
+ if (!unix_funcs->wg_parser_get_read_request(source->wg_parser, &data, &offset, &size))
continue;
- if (offset >= file_size)
- size = 0;
- else if (offset + size >= file_size)
- size = file_size - offset;
-
- if (size > buffer_size)
- {
- buffer_size = size;
- data = realloc(data, size);
- }
-
- ret_size = 0;
-
if (SUCCEEDED(hr = IMFByteStream_SetCurrentPosition(byte_stream, offset)))
hr = IMFByteStream_Read(byte_stream, data, size, &ret_size);
- if (FAILED(hr))
- ERR("Failed to read %u bytes at offset %I64u, hr %#x.\n", size, offset, hr);
- else if (ret_size != size)
+ if (SUCCEEDED(hr) && ret_size != size)
ERR("Unexpected short read: requested %u bytes, got %u.\n", size, ret_size);
- unix_funcs->wg_parser_push_data(source->wg_parser, SUCCEEDED(hr) ? data : NULL, ret_size);
+ unix_funcs->wg_parser_complete_read_request(source->wg_parser, SUCCEEDED(hr));
}
- free(data);
TRACE("Media source is shutting down; exiting.\n");
return 0;
}
diff --git a/dlls/winegstreamer/quartz_parser.c b/dlls/winegstreamer/quartz_parser.c
index 5299f4dc2ed..09a916d7f5c 100644
--- a/dlls/winegstreamer/quartz_parser.c
+++ b/dlls/winegstreamer/quartz_parser.c
@@ -785,11 +785,6 @@ static DWORD CALLBACK stream_thread(void *arg)
static DWORD CALLBACK read_thread(void *arg)
{
struct parser *filter = arg;
- LONGLONG file_size, unused;
- uint32_t buffer_size = 0;
- void *data = NULL;
-
- IAsyncReader_Length(filter->reader, &file_size, &unused);
TRACE("Starting read thread for filter %p.\n", filter);
@@ -798,29 +793,14 @@ static DWORD CALLBACK read_thread(void *arg)
uint64_t offset;
uint32_t size;
HRESULT hr;
+ void *data;
- if (!unix_funcs->wg_parser_get_next_read_offset(filter->wg_parser, &offset, &size))
+ if (!unix_funcs->wg_parser_get_read_request(filter->wg_parser, &data, &offset, &size))
continue;
-
- if (offset >= file_size)
- size = 0;
- else if (offset + size >= file_size)
- size = file_size - offset;
-
- if (size > buffer_size)
- {
- buffer_size = size;
- data = realloc(data, size);
- }
-
hr = IAsyncReader_SyncRead(filter->reader, offset, size, data);
- if (FAILED(hr))
- ERR("Failed to read %u bytes at offset %I64u, hr %#x.\n", size, offset, hr);
-
- unix_funcs->wg_parser_push_data(filter->wg_parser, SUCCEEDED(hr) ? data : NULL, size);
+ unix_funcs->wg_parser_complete_read_request(filter->wg_parser, SUCCEEDED(hr));
}
- free(data);
TRACE("Streaming stopped; exiting.\n");
return 0;
}
diff --git a/dlls/winegstreamer/wg_parser.c b/dlls/winegstreamer/wg_parser.c
index f0815e37689..119cbffbd88 100644
--- a/dlls/winegstreamer/wg_parser.c
+++ b/dlls/winegstreamer/wg_parser.c
@@ -517,8 +517,8 @@ static void CDECL wg_parser_end_flush(struct wg_parser *parser)
pthread_mutex_unlock(&parser->mutex);
}
-static bool CDECL wg_parser_get_next_read_offset(struct wg_parser *parser,
- uint64_t *offset, uint32_t *size)
+static bool CDECL wg_parser_get_read_request(struct wg_parser *parser,
+ void **data, uint64_t *offset, uint32_t *size)
{
pthread_mutex_lock(&parser->mutex);
@@ -531,6 +531,7 @@ static bool CDECL wg_parser_get_next_read_offset(struct wg_parser *parser,
return false;
}
+ *data = parser->read_request.data;
*offset = parser->read_request.offset;
*size = parser->read_request.size;
@@ -538,15 +539,11 @@ static bool CDECL wg_parser_get_next_read_offset(struct wg_parser *parser,
return true;
}
-static void CDECL wg_parser_push_data(struct wg_parser *parser,
- const void *data, uint32_t size)
+static void CDECL wg_parser_complete_read_request(struct wg_parser *parser, bool ret)
{
pthread_mutex_lock(&parser->mutex);
- parser->read_request.size = size;
parser->read_request.done = true;
- parser->read_request.ret = !!data;
- if (data)
- memcpy(parser->read_request.data, data, size);
+ parser->read_request.ret = ret;
parser->read_request.data = NULL;
pthread_mutex_unlock(&parser->mutex);
pthread_cond_signal(&parser->read_done_cond);
@@ -1217,6 +1214,10 @@ static GstFlowReturn src_getrange_cb(GstPad *pad, GstObject *parent,
if (offset == GST_BUFFER_OFFSET_NONE)
offset = parser->next_pull_offset;
parser->next_pull_offset = offset + size;
+ if (offset >= parser->file_size)
+ return GST_FLOW_EOS;
+ if (offset + size >= parser->file_size)
+ size = parser->file_size - offset;
if (!*buffer)
*buffer = new_buffer = gst_buffer_new_and_alloc(size);
@@ -1240,7 +1241,6 @@ static GstFlowReturn src_getrange_cb(GstPad *pad, GstObject *parent,
pthread_cond_wait(&parser->read_done_cond, &parser->mutex);
ret = parser->read_request.ret;
- gst_buffer_set_size(*buffer, parser->read_request.size);
pthread_mutex_unlock(&parser->mutex);
@@ -1248,12 +1248,10 @@ static GstFlowReturn src_getrange_cb(GstPad *pad, GstObject *parent,
GST_LOG("Request returned %d.", ret);
- if ((!ret || !size) && new_buffer)
+ if (!ret && new_buffer)
gst_buffer_unref(new_buffer);
- if (ret)
- return size ? GST_FLOW_OK : GST_FLOW_EOS;
- return GST_FLOW_ERROR;
+ return ret ? GST_FLOW_OK : GST_FLOW_ERROR;
}
static gboolean src_query_cb(GstPad *pad, GstObject *parent, GstQuery *query)
@@ -1920,8 +1918,8 @@ static const struct unix_funcs funcs =
wg_parser_begin_flush,
wg_parser_end_flush,
- wg_parser_get_next_read_offset,
- wg_parser_push_data,
+ wg_parser_get_read_request,
+ wg_parser_complete_read_request,
wg_parser_set_unlimited_buffering,
--
2.33.0

View File

@ -0,0 +1,221 @@
From ca25389c3980c848dc6094f84160079a4cf805f7 Mon Sep 17 00:00:00 2001
From: Alistair Leslie-Hughes <leslie_alistair@hotmail.com>
Date: Sun, 19 Sep 2021 13:08:03 +1000
Subject: [PATCH 4/6] Revert "winegstreamer: Duplicate source shutdown path
into constructor with leak fixes."
This reverts commit 67734bfce31d6032cee1a8980a9022665e9e18fa.
---
dlls/winegstreamer/gst_private.h | 1 -
dlls/winegstreamer/media_source.c | 102 +++++++++++-------------------
2 files changed, 37 insertions(+), 66 deletions(-)
diff --git a/dlls/winegstreamer/gst_private.h b/dlls/winegstreamer/gst_private.h
index c29fc4a2437..c6c99b1dd55 100644
--- a/dlls/winegstreamer/gst_private.h
+++ b/dlls/winegstreamer/gst_private.h
@@ -22,7 +22,6 @@
#define __GST_PRIVATE_INCLUDED__
#include <assert.h>
-#include <limits.h>
#include <stdarg.h>
#include <stdbool.h>
#include <stdint.h>
diff --git a/dlls/winegstreamer/media_source.c b/dlls/winegstreamer/media_source.c
index 95bdb9b488e..01ab626254a 100644
--- a/dlls/winegstreamer/media_source.c
+++ b/dlls/winegstreamer/media_source.c
@@ -733,12 +733,6 @@ static HRESULT new_media_stream(struct media_source *source,
object->IMFMediaStream_iface.lpVtbl = &media_stream_vtbl;
object->ref = 1;
- if (FAILED(hr = MFCreateEventQueue(&object->event_queue)))
- {
- free(object);
- return hr;
- }
-
IMFMediaSource_AddRef(&source->IMFMediaSource_iface);
object->parent_source = source;
object->stream_id = stream_id;
@@ -747,11 +741,20 @@ static HRESULT new_media_stream(struct media_source *source,
object->eos = FALSE;
object->wg_stream = wg_stream;
+ if (FAILED(hr = MFCreateEventQueue(&object->event_queue)))
+ goto fail;
+
TRACE("Created stream object %p.\n", object);
*out_stream = object;
return S_OK;
+
+fail:
+ WARN("Failed to construct media stream, hr %#x.\n", hr);
+
+ IMFMediaStream_Release(&object->IMFMediaStream_iface);
+ return hr;
}
static HRESULT media_stream_init_desc(struct media_stream *stream)
@@ -844,16 +847,10 @@ static HRESULT media_stream_init_desc(struct media_stream *stream)
goto done;
if (FAILED(hr = IMFStreamDescriptor_GetMediaTypeHandler(stream->descriptor, &type_handler)))
- {
- IMFStreamDescriptor_Release(stream->descriptor);
goto done;
- }
if (FAILED(hr = IMFMediaTypeHandler_SetCurrentMediaType(type_handler, stream_types[0])))
- {
- IMFStreamDescriptor_Release(stream->descriptor);
goto done;
- }
done:
if (type_handler)
@@ -1216,13 +1213,19 @@ static HRESULT WINAPI media_source_Shutdown(IMFMediaSource *iface)
unix_funcs->wg_parser_disconnect(source->wg_parser);
- source->read_thread_shutdown = true;
- WaitForSingleObject(source->read_thread, INFINITE);
- CloseHandle(source->read_thread);
+ if (source->read_thread)
+ {
+ source->read_thread_shutdown = true;
+ WaitForSingleObject(source->read_thread, INFINITE);
+ CloseHandle(source->read_thread);
+ }
- IMFPresentationDescriptor_Release(source->pres_desc);
- IMFMediaEventQueue_Shutdown(source->event_queue);
- IMFByteStream_Release(source->byte_stream);
+ if (source->pres_desc)
+ IMFPresentationDescriptor_Release(source->pres_desc);
+ if (source->event_queue)
+ IMFMediaEventQueue_Shutdown(source->event_queue);
+ if (source->byte_stream)
+ IMFByteStream_Release(source->byte_stream);
for (i = 0; i < source->stream_count; i++)
{
@@ -1230,18 +1233,23 @@ static HRESULT WINAPI media_source_Shutdown(IMFMediaSource *iface)
stream->state = STREAM_SHUTDOWN;
- IMFMediaEventQueue_Shutdown(stream->event_queue);
- IMFStreamDescriptor_Release(stream->descriptor);
- IMFMediaSource_Release(&stream->parent_source->IMFMediaSource_iface);
+ if (stream->event_queue)
+ IMFMediaEventQueue_Shutdown(stream->event_queue);
+ if (stream->descriptor)
+ IMFStreamDescriptor_Release(stream->descriptor);
+ if (stream->parent_source)
+ IMFMediaSource_Release(&stream->parent_source->IMFMediaSource_iface);
IMFMediaStream_Release(&stream->IMFMediaStream_iface);
}
unix_funcs->wg_parser_destroy(source->wg_parser);
- free(source->streams);
+ if (source->stream_count)
+ free(source->streams);
- MFUnlockWorkQueue(source->async_commands_queue);
+ if (source->async_commands_queue)
+ MFUnlockWorkQueue(source->async_commands_queue);
return S_OK;
}
@@ -1266,7 +1274,6 @@ static const IMFMediaSourceVtbl IMFMediaSource_vtbl =
static HRESULT media_source_constructor(IMFByteStream *bytestream, struct media_source **out_media_source)
{
IMFStreamDescriptor **descriptors = NULL;
- unsigned int stream_count = UINT_MAX;
struct media_source *object;
UINT64 total_pres_time = 0;
struct wg_parser *parser;
@@ -1330,15 +1337,15 @@ static HRESULT media_source_constructor(IMFByteStream *bytestream, struct media_
* leak occurs with native. */
unix_funcs->wg_parser_set_unlimited_buffering(parser);
- stream_count = unix_funcs->wg_parser_get_stream_count(parser);
+ object->stream_count = unix_funcs->wg_parser_get_stream_count(parser);
- if (!(object->streams = calloc(stream_count, sizeof(*object->streams))))
+ if (!(object->streams = calloc(object->stream_count, sizeof(*object->streams))))
{
hr = E_OUTOFMEMORY;
goto fail;
}
- for (i = 0; i < stream_count; ++i)
+ for (i = 0; i < object->stream_count; ++i)
{
if (FAILED(hr = new_media_stream(object, unix_funcs->wg_parser_get_stream(parser, i), i, &object->streams[i])))
goto fail;
@@ -1346,13 +1353,9 @@ static HRESULT media_source_constructor(IMFByteStream *bytestream, struct media_
if (FAILED(hr = media_stream_init_desc(object->streams[i])))
{
ERR("Failed to finish initialization of media stream %p, hr %x.\n", object->streams[i], hr);
- IMFMediaSource_Release(&object->streams[i]->parent_source->IMFMediaSource_iface);
- IMFMediaEventQueue_Release(object->streams[i]->event_queue);
- free(object->streams[i]);
+ IMFMediaStream_Release(&object->streams[i]->IMFMediaStream_iface);
goto fail;
}
-
- object->stream_count++;
}
/* init presentation descriptor */
@@ -1389,39 +1392,8 @@ static HRESULT media_source_constructor(IMFByteStream *bytestream, struct media_
fail:
WARN("Failed to construct MFMediaSource, hr %#x.\n", hr);
- if (descriptors)
- {
- for (i = 0; i < object->stream_count; i++)
- IMFStreamDescriptor_Release(descriptors[i]);
- free(descriptors);
- }
- for (i = 0; i < object->stream_count; i++)
- {
- struct media_stream *stream = object->streams[i];
-
- IMFMediaEventQueue_Release(stream->event_queue);
- IMFStreamDescriptor_Release(stream->descriptor);
- IMFMediaSource_Release(&stream->parent_source->IMFMediaSource_iface);
-
- free(stream);
- }
- free(object->streams);
- if (stream_count != UINT_MAX)
- unix_funcs->wg_parser_disconnect(object->wg_parser);
- if (object->read_thread)
- {
- object->read_thread_shutdown = true;
- WaitForSingleObject(object->read_thread, INFINITE);
- CloseHandle(object->read_thread);
- }
- if (object->wg_parser)
- unix_funcs->wg_parser_destroy(object->wg_parser);
- if (object->async_commands_queue)
- MFUnlockWorkQueue(object->async_commands_queue);
- if (object->event_queue)
- IMFMediaEventQueue_Release(object->event_queue);
- IMFByteStream_Release(object->byte_stream);
- free(object);
+ free(descriptors);
+ IMFMediaSource_Release(&object->IMFMediaSource_iface);
return hr;
}
--
2.33.0

View File

@ -0,0 +1,140 @@
From e648d762c2609321822334a9a8db8a2f5905b51d Mon Sep 17 00:00:00 2001
From: Alistair Leslie-Hughes <leslie_alistair@hotmail.com>
Date: Sun, 19 Sep 2021 13:08:04 +1000
Subject: [PATCH 5/6] Revert "winegstreamer: Properly clean up from failure in
wg_parser_connect()."
This reverts commit 721b1eb2ebe5c3eaab8ac3fb1e4f4648cbee5b4d.
---
dlls/winegstreamer/wg_parser.c | 76 ++++++++++------------------------
1 file changed, 23 insertions(+), 53 deletions(-)
diff --git a/dlls/winegstreamer/wg_parser.c b/dlls/winegstreamer/wg_parser.c
index 119cbffbd88..bf5a51aeaf4 100644
--- a/dlls/winegstreamer/wg_parser.c
+++ b/dlls/winegstreamer/wg_parser.c
@@ -1034,30 +1034,6 @@ static struct wg_parser_stream *create_stream(struct wg_parser *parser)
return stream;
}
-static void free_stream(struct wg_parser_stream *stream)
-{
- if (stream->their_src)
- {
- if (stream->post_sink)
- {
- gst_pad_unlink(stream->their_src, stream->post_sink);
- gst_pad_unlink(stream->post_src, stream->my_sink);
- gst_object_unref(stream->post_src);
- gst_object_unref(stream->post_sink);
- stream->post_src = stream->post_sink = NULL;
- }
- else
- gst_pad_unlink(stream->their_src, stream->my_sink);
- gst_object_unref(stream->their_src);
- }
- gst_object_unref(stream->my_sink);
-
- pthread_cond_destroy(&stream->event_cond);
- pthread_cond_destroy(&stream->event_empty_cond);
-
- free(stream);
-}
-
static void pad_added_cb(GstElement *element, GstPad *pad, gpointer user)
{
struct wg_parser *parser = user;
@@ -1544,14 +1520,14 @@ static HRESULT CDECL wg_parser_connect(struct wg_parser *parser, uint64_t file_s
parser->error = false;
if (!parser->init_gst(parser))
- goto out;
+ return E_FAIL;
gst_element_set_state(parser->container, GST_STATE_PAUSED);
ret = gst_element_get_state(parser->container, NULL, NULL, -1);
if (ret == GST_STATE_CHANGE_FAILURE)
{
GST_ERROR("Failed to play stream.\n");
- goto out;
+ return E_FAIL;
}
pthread_mutex_lock(&parser->mutex);
@@ -1561,7 +1537,7 @@ static HRESULT CDECL wg_parser_connect(struct wg_parser *parser, uint64_t file_s
if (parser->error)
{
pthread_mutex_unlock(&parser->mutex);
- goto out;
+ return E_FAIL;
}
for (i = 0; i < parser->stream_count; ++i)
@@ -1601,7 +1577,7 @@ static HRESULT CDECL wg_parser_connect(struct wg_parser *parser, uint64_t file_s
if (parser->error)
{
pthread_mutex_unlock(&parser->mutex);
- goto out;
+ return E_FAIL;
}
if (gst_pad_query_duration(stream->their_src, GST_FORMAT_TIME, &duration))
{
@@ -1638,36 +1614,30 @@ static HRESULT CDECL wg_parser_connect(struct wg_parser *parser, uint64_t file_s
parser->next_offset = 0;
return S_OK;
+}
-out:
- if (parser->container)
- gst_element_set_state(parser->container, GST_STATE_NULL);
- if (parser->their_sink)
- {
- gst_pad_unlink(parser->my_src, parser->their_sink);
- gst_object_unref(parser->their_sink);
- parser->my_src = parser->their_sink = NULL;
- }
-
- for (i = 0; i < parser->stream_count; ++i)
- free_stream(parser->streams[i]);
- parser->stream_count = 0;
- free(parser->streams);
- parser->streams = NULL;
-
- if (parser->container)
+static void free_stream(struct wg_parser_stream *stream)
+{
+ if (stream->their_src)
{
- gst_element_set_bus(parser->container, NULL);
- gst_object_unref(parser->container);
- parser->container = NULL;
+ if (stream->post_sink)
+ {
+ gst_pad_unlink(stream->their_src, stream->post_sink);
+ gst_pad_unlink(stream->post_src, stream->my_sink);
+ gst_object_unref(stream->post_src);
+ gst_object_unref(stream->post_sink);
+ stream->post_src = stream->post_sink = NULL;
+ }
+ else
+ gst_pad_unlink(stream->their_src, stream->my_sink);
+ gst_object_unref(stream->their_src);
}
+ gst_object_unref(stream->my_sink);
- pthread_mutex_lock(&parser->mutex);
- parser->sink_connected = false;
- pthread_mutex_unlock(&parser->mutex);
- pthread_cond_signal(&parser->read_cond);
+ pthread_cond_destroy(&stream->event_cond);
+ pthread_cond_destroy(&stream->event_empty_cond);
- return E_FAIL;
+ free(stream);
}
static void CDECL wg_parser_disconnect(struct wg_parser *parser)
--
2.33.0

View File

@ -0,0 +1,160 @@
From 6d496c2655531790cdfdb5869fd37b64ae405b8a Mon Sep 17 00:00:00 2001
From: Alistair Leslie-Hughes <leslie_alistair@hotmail.com>
Date: Sun, 19 Sep 2021 13:08:05 +1000
Subject: [PATCH 6/6] Revert "winegstreamer: Factor out more of the init_gst
callback into wg_parser_connect()."
This reverts commit 830efe873a967dbbb0c9a65be6a66b124a5fa826.
---
dlls/winegstreamer/wg_parser.c | 78 +++++++++++++++++++++++-----------
1 file changed, 54 insertions(+), 24 deletions(-)
diff --git a/dlls/winegstreamer/wg_parser.c b/dlls/winegstreamer/wg_parser.c
index bf5a51aeaf4..cd12a23d0c8 100644
--- a/dlls/winegstreamer/wg_parser.c
+++ b/dlls/winegstreamer/wg_parser.c
@@ -1494,7 +1494,6 @@ static HRESULT CDECL wg_parser_connect(struct wg_parser *parser, uint64_t file_s
GstStaticPadTemplate src_template = GST_STATIC_PAD_TEMPLATE("quartz_src",
GST_PAD_SRC, GST_PAD_ALWAYS, GST_STATIC_CAPS_ANY);
unsigned int i;
- int ret;
parser->file_size = file_size;
parser->sink_connected = true;
@@ -1517,29 +1516,12 @@ static HRESULT CDECL wg_parser_connect(struct wg_parser *parser, uint64_t file_s
parser->start_offset = parser->next_offset = parser->stop_offset = 0;
parser->next_pull_offset = 0;
- parser->error = false;
if (!parser->init_gst(parser))
return E_FAIL;
- gst_element_set_state(parser->container, GST_STATE_PAUSED);
- ret = gst_element_get_state(parser->container, NULL, NULL, -1);
- if (ret == GST_STATE_CHANGE_FAILURE)
- {
- GST_ERROR("Failed to play stream.\n");
- return E_FAIL;
- }
-
pthread_mutex_lock(&parser->mutex);
- while (!parser->no_more_pads && !parser->error)
- pthread_cond_wait(&parser->init_cond, &parser->mutex);
- if (parser->error)
- {
- pthread_mutex_unlock(&parser->mutex);
- return E_FAIL;
- }
-
for (i = 0; i < parser->stream_count; ++i)
{
struct wg_parser_stream *stream = parser->streams[i];
@@ -1695,7 +1677,7 @@ static BOOL decodebin_parser_init_gst(struct wg_parser *parser)
parser->their_sink = gst_element_get_static_pad(element, "sink");
pthread_mutex_lock(&parser->mutex);
- parser->no_more_pads = false;
+ parser->no_more_pads = parser->error = false;
pthread_mutex_unlock(&parser->mutex);
if ((ret = gst_pad_link(parser->my_src, parser->their_sink)) < 0)
@@ -1704,6 +1686,24 @@ static BOOL decodebin_parser_init_gst(struct wg_parser *parser)
return FALSE;
}
+ gst_element_set_state(parser->container, GST_STATE_PAUSED);
+ ret = gst_element_get_state(parser->container, NULL, NULL, -1);
+ if (ret == GST_STATE_CHANGE_FAILURE)
+ {
+ GST_ERROR("Failed to play stream.\n");
+ return FALSE;
+ }
+
+ pthread_mutex_lock(&parser->mutex);
+ while (!parser->no_more_pads && !parser->error)
+ pthread_cond_wait(&parser->init_cond, &parser->mutex);
+ if (parser->error)
+ {
+ pthread_mutex_unlock(&parser->mutex);
+ return FALSE;
+ }
+ pthread_mutex_unlock(&parser->mutex);
+
return TRUE;
}
@@ -1724,7 +1724,7 @@ static BOOL avi_parser_init_gst(struct wg_parser *parser)
parser->their_sink = gst_element_get_static_pad(element, "sink");
pthread_mutex_lock(&parser->mutex);
- parser->no_more_pads = false;
+ parser->no_more_pads = parser->error = false;
pthread_mutex_unlock(&parser->mutex);
if ((ret = gst_pad_link(parser->my_src, parser->their_sink)) < 0)
@@ -1733,6 +1733,24 @@ static BOOL avi_parser_init_gst(struct wg_parser *parser)
return FALSE;
}
+ gst_element_set_state(parser->container, GST_STATE_PAUSED);
+ ret = gst_element_get_state(parser->container, NULL, NULL, -1);
+ if (ret == GST_STATE_CHANGE_FAILURE)
+ {
+ GST_ERROR("Failed to play stream.\n");
+ return FALSE;
+ }
+
+ pthread_mutex_lock(&parser->mutex);
+ while (!parser->no_more_pads && !parser->error)
+ pthread_cond_wait(&parser->init_cond, &parser->mutex);
+ if (parser->error)
+ {
+ pthread_mutex_unlock(&parser->mutex);
+ return FALSE;
+ }
+ pthread_mutex_unlock(&parser->mutex);
+
return TRUE;
}
@@ -1763,9 +1781,15 @@ static BOOL mpeg_audio_parser_init_gst(struct wg_parser *parser)
GST_ERROR("Failed to link source pads, error %d.\n", ret);
return FALSE;
}
- gst_pad_set_active(stream->my_sink, 1);
- parser->no_more_pads = true;
+ gst_pad_set_active(stream->my_sink, 1);
+ gst_element_set_state(parser->container, GST_STATE_PAUSED);
+ ret = gst_element_get_state(parser->container, NULL, NULL, -1);
+ if (ret == GST_STATE_CHANGE_FAILURE)
+ {
+ GST_ERROR("Failed to play stream.\n");
+ return FALSE;
+ }
return TRUE;
}
@@ -1798,9 +1822,15 @@ static BOOL wave_parser_init_gst(struct wg_parser *parser)
GST_ERROR("Failed to link source pads, error %d.\n", ret);
return FALSE;
}
- gst_pad_set_active(stream->my_sink, 1);
- parser->no_more_pads = true;
+ gst_pad_set_active(stream->my_sink, 1);
+ gst_element_set_state(parser->container, GST_STATE_PAUSED);
+ ret = gst_element_get_state(parser->container, NULL, NULL, -1);
+ if (ret == GST_STATE_CHANGE_FAILURE)
+ {
+ GST_ERROR("Failed to play stream.\n");
+ return FALSE;
+ }
return TRUE;
}
--
2.33.0

View File

@ -0,0 +1,2 @@
# This is just a revert of update mfplat patches until it's new versions
# of the mfplat have been merged upstream.

View File

@ -1,2 +1,2 @@
Fixes: [49692] Multiple applications need a Media Foundation media source implementation
Disabled: True
Depends: mfplat-reverts

View File

@ -138,6 +138,8 @@ patch_enable_all ()
enable_krnl386_exe16_Invalid_Console_Handles="$1"
enable_libs_Unicode_Collation="$1"
enable_loader_KeyboardLayouts="$1"
enable_mfplat_reverts="$1"
enable_mfplat_streaming_support="$1"
enable_mmsystem_dll16_MIDIHDR_Refcount="$1"
enable_mountmgr_DosDevices="$1"
enable_mscoree_CorValidateImage="$1"
@ -454,6 +456,12 @@ patch_enable ()
loader-KeyboardLayouts)
enable_loader_KeyboardLayouts="$2"
;;
mfplat-reverts)
enable_mfplat_reverts="$2"
;;
mfplat-streaming-support)
enable_mfplat_streaming_support="$2"
;;
mmsystem.dll16-MIDIHDR_Refcount)
enable_mmsystem_dll16_MIDIHDR_Refcount="$2"
;;
@ -1340,6 +1348,13 @@ if test "$enable_ntdll_WRITECOPY" -eq 1; then
enable_ntdll_ForceBottomUpAlloc=1
fi
if test "$enable_mfplat_streaming_support" -eq 1; then
if test "$enable_mfplat_reverts" -gt 1; then
abort "Patchset mfplat-reverts disabled, but mfplat-streaming-support depends on that."
fi
enable_mfplat_reverts=1
fi
if test "$enable_imm32_com_initialization" -eq 1; then
if test "$enable_winex11__NET_ACTIVE_WINDOW" -gt 1; then
abort "Patchset winex11-_NET_ACTIVE_WINDOW disabled, but imm32-com-initialization depends on that."
@ -2439,6 +2454,76 @@ if test "$enable_loader_KeyboardLayouts" -eq 1; then
patch_apply loader-KeyboardLayouts/0002-user32-Improve-GetKeyboardLayoutList.patch
fi
# Patchset mfplat-reverts
# |
# | Modified files:
# | * dlls/winegstreamer/gst_private.h, dlls/winegstreamer/media_source.c, dlls/winegstreamer/quartz_parser.c,
# | dlls/winegstreamer/wg_parser.c
# |
if test "$enable_mfplat_reverts" -eq 1; then
patch_apply mfplat-reverts/0001-Revert-winegstreamer-Fix-return-code-in-init_gst-fai.patch
patch_apply mfplat-reverts/0002-Revert-winegstreamer-Replace-source-pad-interface-wi.patch
patch_apply mfplat-reverts/0003-Revert-winegstreamer-Allocate-source-media-buffers-i.patch
patch_apply mfplat-reverts/0004-Revert-winegstreamer-Duplicate-source-shutdown-path-.patch
patch_apply mfplat-reverts/0005-Revert-winegstreamer-Properly-clean-up-from-failure-.patch
patch_apply mfplat-reverts/0006-Revert-winegstreamer-Factor-out-more-of-the-init_gst.patch
fi
# Patchset mfplat-streaming-support
# |
# | This patchset has the following (direct or indirect) dependencies:
# | * mfplat-reverts
# |
# | This patchset fixes the following Wine bugs:
# | * [#49692] Multiple applications need a Media Foundation media source implementation
# |
# | Modified files:
# | * dlls/mf/topology.c, dlls/mfplat/main.c, dlls/winegstreamer/Makefile.in, dlls/winegstreamer/audioconvert.c,
# | dlls/winegstreamer/colorconvert.c, dlls/winegstreamer/decode_transform.c, dlls/winegstreamer/gst_private.h,
# | dlls/winegstreamer/media_source.c, dlls/winegstreamer/mfplat.c, dlls/winegstreamer/quartz_parser.c,
# | dlls/winegstreamer/wg_parser.c, dlls/winegstreamer/winegstreamer_classes.idl, include/mfidl.idl, include/wmcodecdsp.idl
# |
if test "$enable_mfplat_streaming_support" -eq 1; then
patch_apply mfplat-streaming-support/0001-winegstreamer-Activate-source-pad-in-push-mode-if-it.patch
patch_apply mfplat-streaming-support/0002-winegstreamer-Push-stream-start-and-segment-events-i.patch
patch_apply mfplat-streaming-support/0003-winegstreamer-Introduce-H.264-decoder-transform.patch
patch_apply mfplat-streaming-support/0004-winegstreamer-Implement-GetInputAvailableType-for-de.patch
patch_apply mfplat-streaming-support/0005-winegstreamer-Implement-GetOutputAvailableType-for-d.patch
patch_apply mfplat-streaming-support/0006-winegstreamer-Implement-SetInputType-for-decode-tran.patch
patch_apply mfplat-streaming-support/0007-winegstreamer-Implement-SetOutputType-for-decode-tra.patch
patch_apply mfplat-streaming-support/0008-winegstreamer-Implement-Get-Input-Output-StreamInfo-.patch
patch_apply mfplat-streaming-support/0009-winegstreamer-Add-push-mode-path-for-wg_parser.patch
patch_apply mfplat-streaming-support/0010-winegstreamer-Implement-Process-Input-Output-for-dec.patch
patch_apply mfplat-streaming-support/0011-winestreamer-Implement-ProcessMessage-for-decoder-tr.patch
patch_apply mfplat-streaming-support/0012-winegstreamer-Semi-stub-GetAttributes-for-decoder-tr.patch
patch_apply mfplat-streaming-support/0013-winegstreamer-Register-the-H.264-decoder-transform.patch
patch_apply mfplat-streaming-support/0014-winegstreamer-Introduce-AAC-decoder-transform.patch
patch_apply mfplat-streaming-support/0015-winegstreamer-Register-the-AAC-decoder-transform.patch
patch_apply mfplat-streaming-support/0016-winegstreamer-Rename-GStreamer-objects-to-be-more-ge.patch
patch_apply mfplat-streaming-support/0017-winegstreamer-Report-streams-backwards-in-media-sour.patch
patch_apply mfplat-streaming-support/0018-winegstreamer-Implement-Process-Input-Output-for-aud.patch
patch_apply mfplat-streaming-support/0019-winegstreamer-Implement-Get-Input-Output-StreamInfo-.patch
patch_apply mfplat-streaming-support/0020-winegstreamer-Semi-stub-Get-Attributes-functions-for.patch
patch_apply mfplat-streaming-support/0021-winegstreamer-Introduce-color-conversion-transform.patch
patch_apply mfplat-streaming-support/0022-winegstreamer-Register-the-color-conversion-transfor.patch
patch_apply mfplat-streaming-support/0023-winegstreamer-Implement-GetInputAvailableType-for-co.patch
patch_apply mfplat-streaming-support/0024-winegstreamer-Implement-SetInputType-for-color-conve.patch
patch_apply mfplat-streaming-support/0025-winegstreamer-Implement-GetOutputAvailableType-for-c.patch
patch_apply mfplat-streaming-support/0026-winegstreamer-Implement-SetOutputType-for-color-conv.patch
patch_apply mfplat-streaming-support/0027-winegstreamer-Implement-Process-Input-Output-for-col.patch
patch_apply mfplat-streaming-support/0028-winegstreamer-Implement-ProcessMessage-for-color-con.patch
patch_apply mfplat-streaming-support/0029-winegstreamer-Implement-Get-Input-Output-StreamInfo-.patch
patch_apply mfplat-streaming-support/0030-mf-topology-Forward-failure-from-SetOutputType-when-.patch
patch_apply mfplat-streaming-support/0031-winegstreamer-Handle-flush-command-in-audio-converst.patch
patch_apply mfplat-streaming-support/0032-winegstreamer-In-the-default-configuration-select-on.patch
patch_apply mfplat-streaming-support/0033-winegstreamer-Implement-MF_SD_LANGUAGE.patch
patch_apply mfplat-streaming-support/0034-winegstreamer-Only-require-videobox-element-for-pars.patch
patch_apply mfplat-streaming-support/0035-winegstreamer-Don-t-rely-on-max_size-in-unseekable-p.patch
patch_apply mfplat-streaming-support/0036-winegstreamer-Implement-MFT_MESSAGE_COMMAND_FLUSH-fo.patch
patch_apply mfplat-streaming-support/0037-winegstreamer-Default-Frame-size-if-one-isn-t-availa.patch
patch_apply mfplat-streaming-support/0038-mfplat-Stub-out-MFCreateDXGIDeviceManager-to-avoid-t.patch
fi
# Patchset mmsystem.dll16-MIDIHDR_Refcount
# |
# | This patchset fixes the following Wine bugs: