mirror of
https://gitlab.winehq.org/wine/wine-staging.git
synced 2025-01-28 22:04:43 -08:00
Rebase against 23c6dd55b8c983ec88cada0a6d6c75ee9cd93976.
This commit is contained in:
parent
639755741e
commit
76a479203b
@ -1,2 +1,5 @@
|
||||
Fixes: [47699] Multiple games fail to connect to online services (missing BCryptSecretAgreement / BCryptDeriveKey implementation)
|
||||
|
||||
# Needs to be moved to the unix lib, but that's a nontrivial amount of work, and
|
||||
# using gcrypt is the wrong way forward (we should expose the missing APIs from
|
||||
# gnutls instead).
|
||||
Disabled: true
|
||||
|
@ -1,33 +0,0 @@
|
||||
From d037faddfa629e54b5ba13d57f2e4c185de2a555 Mon Sep 17 00:00:00 2001
|
||||
From: Christian Costa <titan.costa@gmail.com>
|
||||
Date: Tue, 4 Nov 2014 22:25:58 +0100
|
||||
Subject: d3dx9_36: No need to fail if we don't support vertices reordering in
|
||||
D3DXMESHOPT_ATTRSORT
|
||||
|
||||
A non optimized mesh does not prevent rendering as long as we return valid data to the application.
|
||||
In our case we provided an identity remapping array when no vertices reordering is done.
|
||||
|
||||
Avencast demo works perfectly well (using native effects functions).
|
||||
---
|
||||
dlls/d3dx9_36/mesh.c | 4 ----
|
||||
1 file changed, 4 deletions(-)
|
||||
|
||||
diff --git a/dlls/d3dx9_36/mesh.c b/dlls/d3dx9_36/mesh.c
|
||||
index 6f268f2..b15e033 100644
|
||||
--- a/dlls/d3dx9_36/mesh.c
|
||||
+++ b/dlls/d3dx9_36/mesh.c
|
||||
@@ -1700,11 +1700,7 @@ static HRESULT WINAPI d3dx9_mesh_OptimizeInplace(ID3DXMesh *iface, DWORD flags,
|
||||
if (FAILED(hr)) goto cleanup;
|
||||
} else if (flags & D3DXMESHOPT_ATTRSORT) {
|
||||
if (!(flags & D3DXMESHOPT_IGNOREVERTS))
|
||||
- {
|
||||
FIXME("D3DXMESHOPT_ATTRSORT vertex reordering not implemented.\n");
|
||||
- hr = E_NOTIMPL;
|
||||
- goto cleanup;
|
||||
- }
|
||||
|
||||
hr = iface->lpVtbl->LockAttributeBuffer(iface, 0, &attrib_buffer);
|
||||
if (FAILED(hr)) goto cleanup;
|
||||
--
|
||||
2.1.3
|
||||
|
@ -1 +0,0 @@
|
||||
Fixes: [48529] Avencast fails to launch
|
@ -1,394 +0,0 @@
|
||||
From 76ebf639f8c353cba828c0dfb26fdc0e01318098 Mon Sep 17 00:00:00 2001
|
||||
From: Derek Lesho <dlesho@codeweavers.com>
|
||||
Date: Mon, 30 Mar 2020 14:19:35 -0500
|
||||
Subject: [PATCH] winegstreamer: Add a GstPad wrapping the media source's
|
||||
bytestream.
|
||||
|
||||
Signed-off-by: Derek Lesho <dlesho@codeweavers.com>
|
||||
---
|
||||
dlls/winegstreamer/gst_cbs.c | 58 +++++++++
|
||||
dlls/winegstreamer/gst_cbs.h | 12 +-
|
||||
dlls/winegstreamer/main.c | 3 +
|
||||
dlls/winegstreamer/media_source.c | 189 +++++++++++++++++++++++++++++-
|
||||
4 files changed, 258 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/dlls/winegstreamer/gst_cbs.c b/dlls/winegstreamer/gst_cbs.c
|
||||
index bf7103b1606..12b53bc5d68 100644
|
||||
--- a/dlls/winegstreamer/gst_cbs.c
|
||||
+++ b/dlls/winegstreamer/gst_cbs.c
|
||||
@@ -49,6 +49,8 @@ static void CALLBACK perform_cb(TP_CALLBACK_INSTANCE *instance, void *user)
|
||||
|
||||
if (cbdata->type < GSTDEMUX_MAX)
|
||||
perform_cb_gstdemux(cbdata);
|
||||
+ else if (cbdata->type < MEDIA_SOURCE_MAX)
|
||||
+ perform_cb_media_source(cbdata);
|
||||
|
||||
pthread_mutex_lock(&cbdata->lock);
|
||||
cbdata->finished = 1;
|
||||
@@ -301,3 +303,59 @@ gboolean query_sink_wrapper(GstPad *pad, GstObject *parent, GstQuery *query)
|
||||
|
||||
return cbdata.u.query_sink_data.ret;
|
||||
}
|
||||
+
|
||||
+GstFlowReturn bytestream_wrapper_pull_wrapper(GstPad *pad, GstObject *parent, guint64 ofs, guint len,
|
||||
+ GstBuffer **buf)
|
||||
+{
|
||||
+ struct cb_data cbdata = { BYTESTREAM_WRAPPER_PULL };
|
||||
+
|
||||
+ cbdata.u.getrange_data.pad = pad;
|
||||
+ cbdata.u.getrange_data.parent = parent;
|
||||
+ cbdata.u.getrange_data.ofs = ofs;
|
||||
+ cbdata.u.getrange_data.len = len;
|
||||
+ cbdata.u.getrange_data.buf = buf;
|
||||
+
|
||||
+ call_cb(&cbdata);
|
||||
+
|
||||
+ return cbdata.u.getrange_data.ret;
|
||||
+}
|
||||
+
|
||||
+gboolean bytestream_query_wrapper(GstPad *pad, GstObject *parent, GstQuery *query)
|
||||
+{
|
||||
+ struct cb_data cbdata = { BYTESTREAM_QUERY };
|
||||
+
|
||||
+ cbdata.u.query_function_data.pad = pad;
|
||||
+ cbdata.u.query_function_data.parent = parent;
|
||||
+ cbdata.u.query_function_data.query = query;
|
||||
+
|
||||
+ call_cb(&cbdata);
|
||||
+
|
||||
+ return cbdata.u.query_function_data.ret;
|
||||
+}
|
||||
+
|
||||
+gboolean bytestream_pad_mode_activate_wrapper(GstPad *pad, GstObject *parent, GstPadMode mode, gboolean activate)
|
||||
+{
|
||||
+ struct cb_data cbdata = { BYTESTREAM_PAD_MODE_ACTIVATE };
|
||||
+
|
||||
+ cbdata.u.activate_mode_data.pad = pad;
|
||||
+ cbdata.u.activate_mode_data.parent = parent;
|
||||
+ cbdata.u.activate_mode_data.mode = mode;
|
||||
+ cbdata.u.activate_mode_data.activate = activate;
|
||||
+
|
||||
+ call_cb(&cbdata);
|
||||
+
|
||||
+ return cbdata.u.activate_mode_data.ret;
|
||||
+}
|
||||
+
|
||||
+gboolean bytestream_pad_event_process_wrapper(GstPad *pad, GstObject *parent, GstEvent *event)
|
||||
+{
|
||||
+ struct cb_data cbdata = { BYTESTREAM_PAD_EVENT_PROCESS };
|
||||
+
|
||||
+ cbdata.u.event_src_data.pad = pad;
|
||||
+ cbdata.u.event_src_data.parent = parent;
|
||||
+ cbdata.u.event_src_data.event = event;
|
||||
+
|
||||
+ call_cb(&cbdata);
|
||||
+
|
||||
+ return cbdata.u.event_src_data.ret;
|
||||
+}
|
||||
diff --git a/dlls/winegstreamer/gst_cbs.h b/dlls/winegstreamer/gst_cbs.h
|
||||
index 4725f23ad1a..3459a9ef8ee 100644
|
||||
--- a/dlls/winegstreamer/gst_cbs.h
|
||||
+++ b/dlls/winegstreamer/gst_cbs.h
|
||||
@@ -43,7 +43,12 @@ enum CB_TYPE {
|
||||
AUTOPLUG_BLACKLIST,
|
||||
UNKNOWN_TYPE,
|
||||
QUERY_SINK,
|
||||
- GSTDEMUX_MAX
|
||||
+ GSTDEMUX_MAX,
|
||||
+ BYTESTREAM_WRAPPER_PULL,
|
||||
+ BYTESTREAM_QUERY,
|
||||
+ BYTESTREAM_PAD_MODE_ACTIVATE,
|
||||
+ BYTESTREAM_PAD_EVENT_PROCESS,
|
||||
+ MEDIA_SOURCE_MAX,
|
||||
};
|
||||
|
||||
struct cb_data {
|
||||
@@ -138,6 +143,7 @@ struct cb_data {
|
||||
|
||||
void mark_wine_thread(void) DECLSPEC_HIDDEN;
|
||||
void perform_cb_gstdemux(struct cb_data *data) DECLSPEC_HIDDEN;
|
||||
+void perform_cb_media_source(struct cb_data *data) DECLSPEC_HIDDEN;
|
||||
|
||||
GstBusSyncReply watch_bus_wrapper(GstBus *bus, GstMessage *msg, gpointer user) DECLSPEC_HIDDEN;
|
||||
void existing_new_pad_wrapper(GstElement *bin, GstPad *pad, gpointer user) DECLSPEC_HIDDEN;
|
||||
@@ -154,5 +160,9 @@ GstAutoplugSelectResult autoplug_blacklist_wrapper(GstElement *bin, GstPad *pad,
|
||||
void unknown_type_wrapper(GstElement *bin, GstPad *pad, GstCaps *caps, gpointer user) DECLSPEC_HIDDEN;
|
||||
void Gstreamer_transform_pad_added_wrapper(GstElement *filter, GstPad *pad, gpointer user) DECLSPEC_HIDDEN;
|
||||
gboolean query_sink_wrapper(GstPad *pad, GstObject *parent, GstQuery *query) DECLSPEC_HIDDEN;
|
||||
+GstFlowReturn bytestream_wrapper_pull_wrapper(GstPad *pad, GstObject *parent, guint64 ofs, guint len, GstBuffer **buf) DECLSPEC_HIDDEN;
|
||||
+gboolean bytestream_query_wrapper(GstPad *pad, GstObject *parent, GstQuery *query) DECLSPEC_HIDDEN;
|
||||
+gboolean bytestream_pad_mode_activate_wrapper(GstPad *pad, GstObject *parent, GstPadMode mode, gboolean activate) DECLSPEC_HIDDEN;
|
||||
+gboolean bytestream_pad_event_process_wrapper(GstPad *pad, GstObject *parent, GstEvent *event) DECLSPEC_HIDDEN;
|
||||
|
||||
#endif
|
||||
diff --git a/dlls/winegstreamer/main.c b/dlls/winegstreamer/main.c
|
||||
index 2872710b3e2..4ca371d58bd 100644
|
||||
--- a/dlls/winegstreamer/main.c
|
||||
+++ b/dlls/winegstreamer/main.c
|
||||
@@ -146,6 +146,9 @@ HRESULT WINAPI DllGetClassObject(REFCLSID clsid, REFIID iid, void **out)
|
||||
|
||||
TRACE("clsid %s, iid %s, out %p.\n", debugstr_guid(clsid), debugstr_guid(iid), out);
|
||||
|
||||
+ if (!init_gstreamer())
|
||||
+ return CLASS_E_CLASSNOTAVAILABLE;
|
||||
+
|
||||
if (SUCCEEDED(hr = mfplat_get_class_object(clsid, iid, out)))
|
||||
return hr;
|
||||
|
||||
diff --git a/dlls/winegstreamer/media_source.c b/dlls/winegstreamer/media_source.c
|
||||
index f365c8a1827..1accf55c6a2 100644
|
||||
--- a/dlls/winegstreamer/media_source.c
|
||||
+++ b/dlls/winegstreamer/media_source.c
|
||||
@@ -17,9 +17,15 @@
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
+#include "config.h"
|
||||
+
|
||||
+#include <gst/gst.h>
|
||||
+
|
||||
#include "gst_private.h"
|
||||
+#include "gst_cbs.h"
|
||||
|
||||
#include <stdarg.h>
|
||||
+#include <assert.h>
|
||||
|
||||
#define COBJMACROS
|
||||
#define NONAMELESSUNION
|
||||
@@ -27,6 +33,7 @@
|
||||
#include "mfapi.h"
|
||||
#include "mferror.h"
|
||||
#include "mfidl.h"
|
||||
+#include "mfobjects.h"
|
||||
|
||||
#include "wine/debug.h"
|
||||
#include "wine/heap.h"
|
||||
@@ -39,6 +46,8 @@ struct media_source
|
||||
IMFMediaSource IMFMediaSource_iface;
|
||||
LONG ref;
|
||||
IMFMediaEventQueue *event_queue;
|
||||
+ IMFByteStream *byte_stream;
|
||||
+ GstPad *my_src;
|
||||
enum
|
||||
{
|
||||
SOURCE_OPENING,
|
||||
@@ -52,6 +61,127 @@ static inline struct media_source *impl_from_IMFMediaSource(IMFMediaSource *ifac
|
||||
return CONTAINING_RECORD(iface, struct media_source, IMFMediaSource_iface);
|
||||
}
|
||||
|
||||
+static GstFlowReturn bytestream_wrapper_pull(GstPad *pad, GstObject *parent, guint64 ofs, guint len,
|
||||
+ GstBuffer **buf)
|
||||
+{
|
||||
+ struct media_source *source = gst_pad_get_element_private(pad);
|
||||
+ IMFByteStream *byte_stream = source->byte_stream;
|
||||
+ ULONG bytes_read;
|
||||
+ GstMapInfo info;
|
||||
+ BOOL is_eof;
|
||||
+ HRESULT hr;
|
||||
+
|
||||
+ TRACE("requesting %u bytes at %s from source %p into buffer %p\n", len, wine_dbgstr_longlong(ofs), source, *buf);
|
||||
+
|
||||
+ if (ofs != GST_BUFFER_OFFSET_NONE)
|
||||
+ {
|
||||
+ if (FAILED(IMFByteStream_SetCurrentPosition(byte_stream, ofs)))
|
||||
+ return GST_FLOW_ERROR;
|
||||
+ }
|
||||
+
|
||||
+ if (FAILED(IMFByteStream_IsEndOfStream(byte_stream, &is_eof)))
|
||||
+ return GST_FLOW_ERROR;
|
||||
+ if (is_eof)
|
||||
+ return GST_FLOW_EOS;
|
||||
+
|
||||
+ if (!(*buf))
|
||||
+ *buf = gst_buffer_new_and_alloc(len);
|
||||
+ gst_buffer_map(*buf, &info, GST_MAP_WRITE);
|
||||
+ hr = IMFByteStream_Read(byte_stream, info.data, len, &bytes_read);
|
||||
+ gst_buffer_unmap(*buf, &info);
|
||||
+
|
||||
+ gst_buffer_set_size(*buf, bytes_read);
|
||||
+
|
||||
+ if (FAILED(hr))
|
||||
+ return GST_FLOW_ERROR;
|
||||
+ return GST_FLOW_OK;
|
||||
+}
|
||||
+
|
||||
+static gboolean bytestream_query(GstPad *pad, GstObject *parent, GstQuery *query)
|
||||
+{
|
||||
+ struct media_source *source = gst_pad_get_element_private(pad);
|
||||
+ GstFormat format;
|
||||
+ QWORD bytestream_len;
|
||||
+
|
||||
+ TRACE("GStreamer queries source %p for %s\n", source, GST_QUERY_TYPE_NAME(query));
|
||||
+
|
||||
+ if (FAILED(IMFByteStream_GetLength(source->byte_stream, &bytestream_len)))
|
||||
+ return FALSE;
|
||||
+
|
||||
+ switch (GST_QUERY_TYPE(query))
|
||||
+ {
|
||||
+ 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)
|
||||
+ {
|
||||
+ QWORD length;
|
||||
+ IMFByteStream_GetLength(source->byte_stream, &length);
|
||||
+ gst_query_set_duration(query, GST_FORMAT_BYTES, length);
|
||||
+ return TRUE;
|
||||
+ }
|
||||
+ return FALSE;
|
||||
+ }
|
||||
+ case GST_QUERY_SEEKING:
|
||||
+ {
|
||||
+ gst_query_parse_seeking (query, &format, NULL, NULL, NULL);
|
||||
+ if (format != GST_FORMAT_BYTES)
|
||||
+ {
|
||||
+ WARN("Cannot seek using format \"%s\".\n", gst_format_get_name(format));
|
||||
+ return FALSE;
|
||||
+ }
|
||||
+ gst_query_set_seeking(query, GST_FORMAT_BYTES, 1, 0, bytestream_len);
|
||||
+ 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_PULL);
|
||||
+ return TRUE;
|
||||
+ }
|
||||
+ default:
|
||||
+ {
|
||||
+ WARN("Unhandled query type %s\n", GST_QUERY_TYPE_NAME(query));
|
||||
+ return FALSE;
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static gboolean bytestream_pad_mode_activate(GstPad *pad, GstObject *parent, GstPadMode mode, gboolean activate)
|
||||
+{
|
||||
+ struct media_source *source = gst_pad_get_element_private(pad);
|
||||
+
|
||||
+ TRACE("%s source pad for mediasource %p in %s mode.\n",
|
||||
+ activate ? "Activating" : "Deactivating", source, gst_pad_mode_get_name(mode));
|
||||
+
|
||||
+ return mode == GST_PAD_MODE_PULL;
|
||||
+}
|
||||
+
|
||||
+static gboolean bytestream_pad_event_process(GstPad *pad, GstObject *parent, GstEvent *event)
|
||||
+{
|
||||
+ struct media_source *source = gst_pad_get_element_private(pad);
|
||||
+
|
||||
+ TRACE("source %p, type \"%s\".\n", source, GST_EVENT_TYPE_NAME(event));
|
||||
+
|
||||
+ switch (event->type) {
|
||||
+ /* the seek event should fail in pull mode */
|
||||
+ case GST_EVENT_SEEK:
|
||||
+ return FALSE;
|
||||
+ default:
|
||||
+ WARN("Ignoring \"%s\" event.\n", GST_EVENT_TYPE_NAME(event));
|
||||
+ case GST_EVENT_TAG:
|
||||
+ case GST_EVENT_QOS:
|
||||
+ case GST_EVENT_RECONFIGURE:
|
||||
+ return gst_pad_event_default(pad, parent, event);
|
||||
+ }
|
||||
+ return TRUE;
|
||||
+}
|
||||
+
|
||||
static HRESULT WINAPI media_source_QueryInterface(IMFMediaSource *iface, REFIID riid, void **out)
|
||||
{
|
||||
struct media_source *source = impl_from_IMFMediaSource(iface);
|
||||
@@ -211,8 +341,12 @@ static HRESULT WINAPI media_source_Shutdown(IMFMediaSource *iface)
|
||||
|
||||
source->state = SOURCE_SHUTDOWN;
|
||||
|
||||
+ if (source->my_src)
|
||||
+ gst_object_unref(GST_OBJECT(source->my_src));
|
||||
if (source->event_queue)
|
||||
IMFMediaEventQueue_Shutdown(source->event_queue);
|
||||
+ if (source->byte_stream)
|
||||
+ IMFByteStream_Release(source->byte_stream);
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
@@ -236,19 +370,31 @@ static const IMFMediaSourceVtbl IMFMediaSource_vtbl =
|
||||
|
||||
static HRESULT media_source_constructor(IMFByteStream *bytestream, struct media_source **out_media_source)
|
||||
{
|
||||
+ GstStaticPadTemplate src_template =
|
||||
+ GST_STATIC_PAD_TEMPLATE("mf_src", GST_PAD_SRC, GST_PAD_ALWAYS, GST_STATIC_CAPS_ANY);
|
||||
+
|
||||
struct media_source *object = heap_alloc_zero(sizeof(*object));
|
||||
HRESULT hr;
|
||||
|
||||
if (!object)
|
||||
return E_OUTOFMEMORY;
|
||||
|
||||
+ object->IMFMediaSource_iface.lpVtbl = &IMFMediaSource_vtbl;
|
||||
+ object->ref = 1;
|
||||
+ object->byte_stream = bytestream;
|
||||
+ IMFByteStream_AddRef(bytestream);
|
||||
+
|
||||
if (FAILED(hr = MFCreateEventQueue(&object->event_queue)))
|
||||
goto fail;
|
||||
|
||||
- object->state = SOURCE_STOPPED;
|
||||
+ object->my_src = gst_pad_new_from_static_template(&src_template, "mf-src");
|
||||
+ gst_pad_set_element_private(object->my_src, object);
|
||||
+ gst_pad_set_getrange_function(object->my_src, bytestream_wrapper_pull_wrapper);
|
||||
+ gst_pad_set_query_function(object->my_src, bytestream_query_wrapper);
|
||||
+ gst_pad_set_activatemode_function(object->my_src, bytestream_pad_mode_activate_wrapper);
|
||||
+ gst_pad_set_event_function(object->my_src, bytestream_pad_event_process_wrapper);
|
||||
|
||||
- object->IMFMediaSource_iface.lpVtbl = &IMFMediaSource_vtbl;
|
||||
- object->ref = 1;
|
||||
+ object->state = SOURCE_STOPPED;
|
||||
|
||||
*out_media_source = object;
|
||||
return S_OK;
|
||||
@@ -716,3 +862,40 @@ HRESULT winegstreamer_stream_handler_create(REFIID riid, void **obj)
|
||||
|
||||
return hr;
|
||||
}
|
||||
+
|
||||
+/* helper for callback forwarding */
|
||||
+void perform_cb_media_source(struct cb_data *cbdata)
|
||||
+{
|
||||
+ switch(cbdata->type)
|
||||
+ {
|
||||
+ case BYTESTREAM_WRAPPER_PULL:
|
||||
+ {
|
||||
+ struct getrange_data *data = &cbdata->u.getrange_data;
|
||||
+ cbdata->u.getrange_data.ret = bytestream_wrapper_pull(data->pad, data->parent,
|
||||
+ data->ofs, data->len, data->buf);
|
||||
+ break;
|
||||
+ }
|
||||
+ case BYTESTREAM_QUERY:
|
||||
+ {
|
||||
+ struct query_function_data *data = &cbdata->u.query_function_data;
|
||||
+ cbdata->u.query_function_data.ret = bytestream_query(data->pad, data->parent, data->query);
|
||||
+ break;
|
||||
+ }
|
||||
+ case BYTESTREAM_PAD_MODE_ACTIVATE:
|
||||
+ {
|
||||
+ struct activate_mode_data *data = &cbdata->u.activate_mode_data;
|
||||
+ cbdata->u.activate_mode_data.ret = bytestream_pad_mode_activate(data->pad, data->parent, data->mode, data->activate);
|
||||
+ break;
|
||||
+ }
|
||||
+ case BYTESTREAM_PAD_EVENT_PROCESS:
|
||||
+ {
|
||||
+ struct event_src_data *data = &cbdata->u.event_src_data;
|
||||
+ cbdata->u.event_src_data.ret = bytestream_pad_event_process(data->pad, data->parent, data->event);
|
||||
+ break;
|
||||
+ }
|
||||
+ default:
|
||||
+ {
|
||||
+ assert(0);
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
--
|
||||
2.28.0
|
||||
|
@ -1,597 +0,0 @@
|
||||
From 49b2e0568ffe3e5e2ea7e9c3572ec09ef2cf8ad7 Mon Sep 17 00:00:00 2001
|
||||
From: Derek Lesho <dlesho@codeweavers.com>
|
||||
Date: Tue, 31 Mar 2020 13:34:57 -0500
|
||||
Subject: [PATCH] winegstreamer: Use decodebin to initialize media streams.
|
||||
|
||||
Signed-off-by: Derek Lesho <dlesho@codeweavers.com>
|
||||
---
|
||||
dlls/winegstreamer/gst_cbs.c | 45 ++++
|
||||
dlls/winegstreamer/gst_cbs.h | 8 +
|
||||
dlls/winegstreamer/media_source.c | 405 +++++++++++++++++++++++++++++-
|
||||
3 files changed, 457 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/dlls/winegstreamer/gst_cbs.c b/dlls/winegstreamer/gst_cbs.c
|
||||
index 12b53bc5d68..51aaefa911d 100644
|
||||
--- a/dlls/winegstreamer/gst_cbs.c
|
||||
+++ b/dlls/winegstreamer/gst_cbs.c
|
||||
@@ -359,3 +359,48 @@ gboolean bytestream_pad_event_process_wrapper(GstPad *pad, GstObject *parent, Gs
|
||||
|
||||
return cbdata.u.event_src_data.ret;
|
||||
}
|
||||
+
|
||||
+GstBusSyncReply mf_src_bus_watch_wrapper(GstBus *bus, GstMessage *message, gpointer user)
|
||||
+{
|
||||
+ struct cb_data cbdata = { MF_SRC_BUS_WATCH };
|
||||
+
|
||||
+ cbdata.u.watch_bus_data.bus = bus;
|
||||
+ cbdata.u.watch_bus_data.msg = message;
|
||||
+ cbdata.u.watch_bus_data.user = user;
|
||||
+
|
||||
+ call_cb(&cbdata);
|
||||
+
|
||||
+ return cbdata.u.watch_bus_data.ret;
|
||||
+}
|
||||
+
|
||||
+void mf_src_stream_added_wrapper(GstElement *bin, GstPad *pad, gpointer user)
|
||||
+{
|
||||
+ struct cb_data cbdata = { MF_SRC_STREAM_ADDED };
|
||||
+
|
||||
+ cbdata.u.pad_added_data.element = bin;
|
||||
+ cbdata.u.pad_added_data.pad = pad;
|
||||
+ cbdata.u.pad_added_data.user = user;
|
||||
+
|
||||
+ call_cb(&cbdata);
|
||||
+}
|
||||
+
|
||||
+void mf_src_stream_removed_wrapper(GstElement *element, GstPad *pad, gpointer user)
|
||||
+{
|
||||
+ struct cb_data cbdata = { MF_SRC_STREAM_REMOVED };
|
||||
+
|
||||
+ cbdata.u.pad_removed_data.element = element;
|
||||
+ cbdata.u.pad_removed_data.pad = pad;
|
||||
+ cbdata.u.pad_removed_data.user = user;
|
||||
+
|
||||
+ call_cb(&cbdata);
|
||||
+}
|
||||
+
|
||||
+void mf_src_no_more_pads_wrapper(GstElement *element, gpointer user)
|
||||
+{
|
||||
+ struct cb_data cbdata = { MF_SRC_NO_MORE_PADS };
|
||||
+
|
||||
+ cbdata.u.no_more_pads_data.element = element;
|
||||
+ cbdata.u.no_more_pads_data.user = user;
|
||||
+
|
||||
+ call_cb(&cbdata);
|
||||
+}
|
||||
diff --git a/dlls/winegstreamer/gst_cbs.h b/dlls/winegstreamer/gst_cbs.h
|
||||
index 3459a9ef8ee..a48999bbf71 100644
|
||||
--- a/dlls/winegstreamer/gst_cbs.h
|
||||
+++ b/dlls/winegstreamer/gst_cbs.h
|
||||
@@ -48,6 +48,10 @@ enum CB_TYPE {
|
||||
BYTESTREAM_QUERY,
|
||||
BYTESTREAM_PAD_MODE_ACTIVATE,
|
||||
BYTESTREAM_PAD_EVENT_PROCESS,
|
||||
+ MF_SRC_BUS_WATCH,
|
||||
+ MF_SRC_STREAM_ADDED,
|
||||
+ MF_SRC_STREAM_REMOVED,
|
||||
+ MF_SRC_NO_MORE_PADS,
|
||||
MEDIA_SOURCE_MAX,
|
||||
};
|
||||
|
||||
@@ -164,5 +168,9 @@ GstFlowReturn bytestream_wrapper_pull_wrapper(GstPad *pad, GstObject *parent, gu
|
||||
gboolean bytestream_query_wrapper(GstPad *pad, GstObject *parent, GstQuery *query) DECLSPEC_HIDDEN;
|
||||
gboolean bytestream_pad_mode_activate_wrapper(GstPad *pad, GstObject *parent, GstPadMode mode, gboolean activate) DECLSPEC_HIDDEN;
|
||||
gboolean bytestream_pad_event_process_wrapper(GstPad *pad, GstObject *parent, GstEvent *event) DECLSPEC_HIDDEN;
|
||||
+GstBusSyncReply mf_src_bus_watch_wrapper(GstBus *bus, GstMessage *message, gpointer user) DECLSPEC_HIDDEN;
|
||||
+void mf_src_stream_added_wrapper(GstElement *bin, GstPad *pad, gpointer user) DECLSPEC_HIDDEN;
|
||||
+void mf_src_stream_removed_wrapper(GstElement *element, GstPad *pad, gpointer user) DECLSPEC_HIDDEN;
|
||||
+void mf_src_no_more_pads_wrapper(GstElement *element, gpointer user) DECLSPEC_HIDDEN;
|
||||
|
||||
#endif
|
||||
diff --git a/dlls/winegstreamer/media_source.c b/dlls/winegstreamer/media_source.c
|
||||
index 1accf55c6a2..f61f84359d5 100644
|
||||
--- a/dlls/winegstreamer/media_source.c
|
||||
+++ b/dlls/winegstreamer/media_source.c
|
||||
@@ -24,6 +24,7 @@
|
||||
#include "gst_private.h"
|
||||
#include "gst_cbs.h"
|
||||
|
||||
+#include <assert.h>
|
||||
#include <stdarg.h>
|
||||
#include <assert.h>
|
||||
|
||||
@@ -41,21 +42,47 @@
|
||||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(mfplat);
|
||||
|
||||
+struct media_stream
|
||||
+{
|
||||
+ IMFMediaStream IMFMediaStream_iface;
|
||||
+ LONG ref;
|
||||
+ struct media_source *parent_source;
|
||||
+ IMFMediaEventQueue *event_queue;
|
||||
+ GstElement *appsink;
|
||||
+ GstPad *their_src, *my_sink;
|
||||
+ enum
|
||||
+ {
|
||||
+ STREAM_STUB,
|
||||
+ STREAM_SHUTDOWN,
|
||||
+ } state;
|
||||
+};
|
||||
+
|
||||
struct media_source
|
||||
{
|
||||
IMFMediaSource IMFMediaSource_iface;
|
||||
LONG ref;
|
||||
IMFMediaEventQueue *event_queue;
|
||||
IMFByteStream *byte_stream;
|
||||
- GstPad *my_src;
|
||||
+ struct media_stream **streams;
|
||||
+ ULONG stream_count;
|
||||
+ GstBus *bus;
|
||||
+ GstElement *container;
|
||||
+ GstElement *decodebin;
|
||||
+ GstPad *my_src, *their_sink;
|
||||
enum
|
||||
{
|
||||
SOURCE_OPENING,
|
||||
SOURCE_STOPPED,
|
||||
SOURCE_SHUTDOWN,
|
||||
} state;
|
||||
+ HANDLE all_streams_event;
|
||||
};
|
||||
|
||||
+static inline struct media_stream *impl_from_IMFMediaStream(IMFMediaStream *iface)
|
||||
+{
|
||||
+ return CONTAINING_RECORD(iface, struct media_stream, IMFMediaStream_iface);
|
||||
+}
|
||||
+
|
||||
static inline struct media_source *impl_from_IMFMediaSource(IMFMediaSource *iface)
|
||||
{
|
||||
return CONTAINING_RECORD(iface, struct media_source, IMFMediaSource_iface);
|
||||
@@ -182,6 +209,242 @@ static gboolean bytestream_pad_event_process(GstPad *pad, GstObject *parent, Gst
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
+GstBusSyncReply bus_watch(GstBus *bus, GstMessage *message, gpointer user)
|
||||
+{
|
||||
+ struct media_source *source = user;
|
||||
+ gchar *dbg_info = NULL;
|
||||
+ GError *err = NULL;
|
||||
+
|
||||
+ TRACE("source %p message type %s\n", source, GST_MESSAGE_TYPE_NAME(message));
|
||||
+
|
||||
+ switch (message->type)
|
||||
+ {
|
||||
+ case GST_MESSAGE_ERROR:
|
||||
+ gst_message_parse_error(message, &err, &dbg_info);
|
||||
+ ERR("%s: %s\n", GST_OBJECT_NAME(message->src), err->message);
|
||||
+ ERR("%s\n", dbg_info);
|
||||
+ g_error_free(err);
|
||||
+ g_free(dbg_info);
|
||||
+ break;
|
||||
+ case GST_MESSAGE_WARNING:
|
||||
+ gst_message_parse_warning(message, &err, &dbg_info);
|
||||
+ WARN("%s: %s\n", GST_OBJECT_NAME(message->src), err->message);
|
||||
+ WARN("%s\n", dbg_info);
|
||||
+ g_error_free(err);
|
||||
+ g_free(dbg_info);
|
||||
+ break;
|
||||
+ default:
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ gst_message_unref(message);
|
||||
+ return GST_BUS_DROP;
|
||||
+}
|
||||
+
|
||||
+static HRESULT WINAPI media_stream_QueryInterface(IMFMediaStream *iface, REFIID riid, void **out)
|
||||
+{
|
||||
+ struct media_stream *stream = impl_from_IMFMediaStream(iface);
|
||||
+
|
||||
+ TRACE("(%p)->(%s %p)\n", stream, debugstr_guid(riid), out);
|
||||
+
|
||||
+ if (IsEqualIID(riid, &IID_IMFMediaStream) ||
|
||||
+ IsEqualIID(riid, &IID_IMFMediaEventGenerator) ||
|
||||
+ IsEqualIID(riid, &IID_IUnknown))
|
||||
+ {
|
||||
+ *out = &stream->IMFMediaStream_iface;
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ FIXME("(%s, %p)\n", debugstr_guid(riid), out);
|
||||
+ *out = NULL;
|
||||
+ return E_NOINTERFACE;
|
||||
+ }
|
||||
+
|
||||
+ IUnknown_AddRef((IUnknown*)*out);
|
||||
+ return S_OK;
|
||||
+}
|
||||
+
|
||||
+static ULONG WINAPI media_stream_AddRef(IMFMediaStream *iface)
|
||||
+{
|
||||
+ struct media_stream *stream = impl_from_IMFMediaStream(iface);
|
||||
+ ULONG ref = InterlockedIncrement(&stream->ref);
|
||||
+
|
||||
+ TRACE("(%p) ref=%u\n", stream, ref);
|
||||
+
|
||||
+ return ref;
|
||||
+}
|
||||
+
|
||||
+static ULONG WINAPI media_stream_Release(IMFMediaStream *iface)
|
||||
+{
|
||||
+ struct media_stream *stream = impl_from_IMFMediaStream(iface);
|
||||
+
|
||||
+ ULONG ref = InterlockedDecrement(&stream->ref);
|
||||
+
|
||||
+ TRACE("(%p) ref=%u\n", stream, ref);
|
||||
+
|
||||
+ if (!ref)
|
||||
+ {
|
||||
+ if (stream->my_sink)
|
||||
+ gst_object_unref(GST_OBJECT(stream->my_sink));
|
||||
+ if (stream->event_queue)
|
||||
+ IMFMediaEventQueue_Release(stream->event_queue);
|
||||
+ if (stream->parent_source)
|
||||
+ IMFMediaSource_Release(&stream->parent_source->IMFMediaSource_iface);
|
||||
+
|
||||
+ heap_free(stream);
|
||||
+ }
|
||||
+
|
||||
+ return ref;
|
||||
+}
|
||||
+
|
||||
+static HRESULT WINAPI media_stream_GetEvent(IMFMediaStream *iface, DWORD flags, IMFMediaEvent **event)
|
||||
+{
|
||||
+ struct media_stream *stream = impl_from_IMFMediaStream(iface);
|
||||
+
|
||||
+ TRACE("(%p)->(%#x, %p)\n", stream, flags, event);
|
||||
+
|
||||
+ if (stream->state == STREAM_SHUTDOWN)
|
||||
+ return MF_E_SHUTDOWN;
|
||||
+
|
||||
+ return IMFMediaEventQueue_GetEvent(stream->event_queue, flags, event);
|
||||
+}
|
||||
+
|
||||
+static HRESULT WINAPI media_stream_BeginGetEvent(IMFMediaStream *iface, IMFAsyncCallback *callback, IUnknown *state)
|
||||
+{
|
||||
+ struct media_stream *stream = impl_from_IMFMediaStream(iface);
|
||||
+
|
||||
+ TRACE("(%p)->(%p, %p)\n", stream, callback, state);
|
||||
+
|
||||
+ if (stream->state == STREAM_SHUTDOWN)
|
||||
+ return MF_E_SHUTDOWN;
|
||||
+
|
||||
+ return IMFMediaEventQueue_BeginGetEvent(stream->event_queue, callback, state);
|
||||
+}
|
||||
+
|
||||
+static HRESULT WINAPI media_stream_EndGetEvent(IMFMediaStream *iface, IMFAsyncResult *result, IMFMediaEvent **event)
|
||||
+{
|
||||
+ struct media_stream *stream = impl_from_IMFMediaStream(iface);
|
||||
+
|
||||
+ TRACE("(%p)->(%p, %p)\n", stream, result, event);
|
||||
+
|
||||
+ if (stream->state == STREAM_SHUTDOWN)
|
||||
+ return MF_E_SHUTDOWN;
|
||||
+
|
||||
+ return IMFMediaEventQueue_EndGetEvent(stream->event_queue, result, event);
|
||||
+}
|
||||
+
|
||||
+static HRESULT WINAPI media_stream_QueueEvent(IMFMediaStream *iface, MediaEventType event_type, REFGUID ext_type,
|
||||
+ HRESULT hr, const PROPVARIANT *value)
|
||||
+{
|
||||
+ struct media_stream *stream = impl_from_IMFMediaStream(iface);
|
||||
+
|
||||
+ TRACE("(%p)->(%d, %s, %#x, %p)\n", stream, event_type, debugstr_guid(ext_type), hr, value);
|
||||
+
|
||||
+ if (stream->state == STREAM_SHUTDOWN)
|
||||
+ return MF_E_SHUTDOWN;
|
||||
+
|
||||
+ return IMFMediaEventQueue_QueueEventParamVar(stream->event_queue, event_type, ext_type, hr, value);
|
||||
+}
|
||||
+
|
||||
+static HRESULT WINAPI media_stream_GetMediaSource(IMFMediaStream *iface, IMFMediaSource **source)
|
||||
+{
|
||||
+ struct media_stream *stream = impl_from_IMFMediaStream(iface);
|
||||
+
|
||||
+ FIXME("stub (%p)->(%p)\n", stream, source);
|
||||
+
|
||||
+ if (stream->state == STREAM_SHUTDOWN)
|
||||
+ return MF_E_SHUTDOWN;
|
||||
+
|
||||
+ return E_NOTIMPL;
|
||||
+}
|
||||
+
|
||||
+static HRESULT WINAPI media_stream_GetStreamDescriptor(IMFMediaStream* iface, IMFStreamDescriptor **descriptor)
|
||||
+{
|
||||
+ struct media_stream *stream = impl_from_IMFMediaStream(iface);
|
||||
+
|
||||
+ TRACE("(%p)->(%p)\n", stream, descriptor);
|
||||
+
|
||||
+ if (stream->state == STREAM_SHUTDOWN)
|
||||
+ return MF_E_SHUTDOWN;
|
||||
+
|
||||
+ return E_NOTIMPL;
|
||||
+}
|
||||
+
|
||||
+static HRESULT WINAPI media_stream_RequestSample(IMFMediaStream *iface, IUnknown *token)
|
||||
+{
|
||||
+ struct media_stream *stream = impl_from_IMFMediaStream(iface);
|
||||
+
|
||||
+ TRACE("(%p)->(%p)\n", iface, token);
|
||||
+
|
||||
+ if (stream->state == STREAM_SHUTDOWN)
|
||||
+ return MF_E_SHUTDOWN;
|
||||
+
|
||||
+ return E_NOTIMPL;
|
||||
+}
|
||||
+
|
||||
+static const IMFMediaStreamVtbl media_stream_vtbl =
|
||||
+{
|
||||
+ media_stream_QueryInterface,
|
||||
+ media_stream_AddRef,
|
||||
+ media_stream_Release,
|
||||
+ media_stream_GetEvent,
|
||||
+ media_stream_BeginGetEvent,
|
||||
+ media_stream_EndGetEvent,
|
||||
+ media_stream_QueueEvent,
|
||||
+ media_stream_GetMediaSource,
|
||||
+ media_stream_GetStreamDescriptor,
|
||||
+ media_stream_RequestSample
|
||||
+};
|
||||
+
|
||||
+/* creates a stub stream */
|
||||
+static HRESULT new_media_stream(struct media_source *source, GstPad *pad, struct media_stream **out_stream)
|
||||
+{
|
||||
+ struct media_stream *object = heap_alloc_zero(sizeof(*object));
|
||||
+ HRESULT hr;
|
||||
+
|
||||
+ TRACE("(%p %p)->(%p)\n", source, pad, out_stream);
|
||||
+
|
||||
+ object->IMFMediaStream_iface.lpVtbl = &media_stream_vtbl;
|
||||
+ object->ref = 1;
|
||||
+
|
||||
+ IMFMediaSource_AddRef(&source->IMFMediaSource_iface);
|
||||
+ object->parent_source = source;
|
||||
+ object->their_src = pad;
|
||||
+
|
||||
+ object->state = STREAM_STUB;
|
||||
+
|
||||
+ if (FAILED(hr = MFCreateEventQueue(&object->event_queue)))
|
||||
+ goto fail;
|
||||
+
|
||||
+ if (!(object->appsink = gst_element_factory_make("appsink", NULL)))
|
||||
+ {
|
||||
+ hr = E_OUTOFMEMORY;
|
||||
+ goto fail;
|
||||
+ }
|
||||
+ gst_bin_add(GST_BIN(object->parent_source->container), object->appsink);
|
||||
+
|
||||
+ g_object_set(object->appsink, "sync", FALSE, NULL);
|
||||
+ g_object_set(object->appsink, "max-buffers", 5, NULL);
|
||||
+
|
||||
+ object->my_sink = gst_element_get_static_pad(object->appsink, "sink");
|
||||
+ gst_pad_set_element_private(object->my_sink, object);
|
||||
+
|
||||
+ gst_pad_link(object->their_src, object->my_sink);
|
||||
+
|
||||
+ gst_element_sync_state_with_parent(object->appsink);
|
||||
+
|
||||
+ TRACE("->(%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 WINAPI media_source_QueryInterface(IMFMediaSource *iface, REFIID riid, void **out)
|
||||
{
|
||||
struct media_source *source = impl_from_IMFMediaSource(iface);
|
||||
@@ -333,6 +596,7 @@ static HRESULT WINAPI media_source_Pause(IMFMediaSource *iface)
|
||||
static HRESULT WINAPI media_source_Shutdown(IMFMediaSource *iface)
|
||||
{
|
||||
struct media_source *source = impl_from_IMFMediaSource(iface);
|
||||
+ unsigned int i;
|
||||
|
||||
TRACE("(%p)\n", source);
|
||||
|
||||
@@ -341,13 +605,34 @@ static HRESULT WINAPI media_source_Shutdown(IMFMediaSource *iface)
|
||||
|
||||
source->state = SOURCE_SHUTDOWN;
|
||||
|
||||
+ if (source->container)
|
||||
+ {
|
||||
+ gst_element_set_state(source->container, GST_STATE_NULL);
|
||||
+ gst_object_unref(GST_OBJECT(source->container));
|
||||
+ }
|
||||
+
|
||||
if (source->my_src)
|
||||
gst_object_unref(GST_OBJECT(source->my_src));
|
||||
+ if (source->their_sink)
|
||||
+ gst_object_unref(GST_OBJECT(source->their_sink));
|
||||
+
|
||||
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++)
|
||||
+ {
|
||||
+ source->streams[i]->state = STREAM_SHUTDOWN;
|
||||
+ IMFMediaStream_Release(&source->streams[i]->IMFMediaStream_iface);
|
||||
+ }
|
||||
+
|
||||
+ if (source->stream_count)
|
||||
+ heap_free(source->streams);
|
||||
+
|
||||
+ if (source->all_streams_event)
|
||||
+ CloseHandle(source->all_streams_event);
|
||||
+
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
@@ -368,6 +653,50 @@ static const IMFMediaSourceVtbl IMFMediaSource_vtbl =
|
||||
media_source_Shutdown,
|
||||
};
|
||||
|
||||
+static void stream_added(GstElement *element, GstPad *pad, gpointer user)
|
||||
+{
|
||||
+ struct media_source *source = user;
|
||||
+ struct media_stream **new_stream_array;
|
||||
+ struct media_stream *stream;
|
||||
+
|
||||
+ if (gst_pad_get_direction(pad) != GST_PAD_SRC)
|
||||
+ return;
|
||||
+
|
||||
+ if (FAILED(new_media_stream(source, pad, &stream)))
|
||||
+ return;
|
||||
+
|
||||
+ if (!(new_stream_array = heap_realloc(source->streams, (source->stream_count + 1) * (sizeof(*new_stream_array)))))
|
||||
+ {
|
||||
+ ERR("Failed to add stream to source\n");
|
||||
+ IMFMediaStream_Release(&stream->IMFMediaStream_iface);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ source->streams = new_stream_array;
|
||||
+ source->streams[source->stream_count++] = stream;
|
||||
+}
|
||||
+
|
||||
+static void stream_removed(GstElement *element, GstPad *pad, gpointer user)
|
||||
+{
|
||||
+ struct media_source *source = user;
|
||||
+ unsigned int i;
|
||||
+
|
||||
+ for (i = 0; i < source->stream_count; i++)
|
||||
+ {
|
||||
+ struct media_stream *stream = source->streams[i];
|
||||
+ if (stream->their_src != pad)
|
||||
+ continue;
|
||||
+ stream->their_src = NULL;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static void no_more_pads(GstElement *element, gpointer user)
|
||||
+{
|
||||
+ struct media_source *source = user;
|
||||
+
|
||||
+ SetEvent(source->all_streams_event);
|
||||
+}
|
||||
+
|
||||
static HRESULT media_source_constructor(IMFByteStream *bytestream, struct media_source **out_media_source)
|
||||
{
|
||||
GstStaticPadTemplate src_template =
|
||||
@@ -375,6 +704,7 @@ static HRESULT media_source_constructor(IMFByteStream *bytestream, struct media_
|
||||
|
||||
struct media_source *object = heap_alloc_zero(sizeof(*object));
|
||||
HRESULT hr;
|
||||
+ int ret;
|
||||
|
||||
if (!object)
|
||||
return E_OUTOFMEMORY;
|
||||
@@ -383,10 +713,16 @@ static HRESULT media_source_constructor(IMFByteStream *bytestream, struct media_
|
||||
object->ref = 1;
|
||||
object->byte_stream = bytestream;
|
||||
IMFByteStream_AddRef(bytestream);
|
||||
+ object->all_streams_event = CreateEventA(NULL, FALSE, FALSE, NULL);
|
||||
|
||||
if (FAILED(hr = MFCreateEventQueue(&object->event_queue)))
|
||||
goto fail;
|
||||
|
||||
+ object->container = gst_bin_new(NULL);
|
||||
+ object->bus = gst_bus_new();
|
||||
+ gst_bus_set_sync_handler(object->bus, mf_src_bus_watch_wrapper, object, NULL);
|
||||
+ gst_element_set_bus(object->container, object->bus);
|
||||
+
|
||||
object->my_src = gst_pad_new_from_static_template(&src_template, "mf-src");
|
||||
gst_pad_set_element_private(object->my_src, object);
|
||||
gst_pad_set_getrange_function(object->my_src, bytestream_wrapper_pull_wrapper);
|
||||
@@ -394,6 +730,49 @@ static HRESULT media_source_constructor(IMFByteStream *bytestream, struct media_
|
||||
gst_pad_set_activatemode_function(object->my_src, bytestream_pad_mode_activate_wrapper);
|
||||
gst_pad_set_event_function(object->my_src, bytestream_pad_event_process_wrapper);
|
||||
|
||||
+ if (!(object->decodebin = gst_element_factory_make("decodebin", NULL)))
|
||||
+ {
|
||||
+ WARN("Failed to create decodebin for source\n");
|
||||
+ hr = E_OUTOFMEMORY;
|
||||
+ goto fail;
|
||||
+ }
|
||||
+
|
||||
+ /* In Media Foundation, sources will infinitely leak buffers, when a subset of the selected
|
||||
+ streams are read from. This behavior is relied upon in the Unity3D engine game, Trailmakers,
|
||||
+ where Unity selects both the video and audio streams, yet only reads from the video stream.
|
||||
+ Removing these buffering limits reflects that behavior. */
|
||||
+ g_object_set(object->decodebin, "max-size-buffers", 0, NULL);
|
||||
+ g_object_set(object->decodebin, "max-size-time", G_GUINT64_CONSTANT(0), NULL);
|
||||
+ g_object_set(object->decodebin, "max-size-bytes", 0, NULL);
|
||||
+
|
||||
+ gst_bin_add(GST_BIN(object->container), object->decodebin);
|
||||
+
|
||||
+ g_signal_connect(object->decodebin, "pad-added", G_CALLBACK(mf_src_stream_added_wrapper), object);
|
||||
+ g_signal_connect(object->decodebin, "pad-removed", G_CALLBACK(mf_src_stream_removed_wrapper), object);
|
||||
+ g_signal_connect(object->decodebin, "no-more-pads", G_CALLBACK(mf_src_no_more_pads_wrapper), object);
|
||||
+
|
||||
+ object->their_sink = gst_element_get_static_pad(object->decodebin, "sink");
|
||||
+
|
||||
+ if ((ret = gst_pad_link(object->my_src, object->their_sink)) < 0)
|
||||
+ {
|
||||
+ WARN("Failed to link our bytestream pad to the demuxer input\n");
|
||||
+ hr = E_OUTOFMEMORY;
|
||||
+ goto fail;
|
||||
+ }
|
||||
+
|
||||
+ object->state = SOURCE_OPENING;
|
||||
+
|
||||
+ gst_element_set_state(object->container, GST_STATE_PAUSED);
|
||||
+ ret = gst_element_get_state(object->container, NULL, NULL, -1);
|
||||
+ if (ret == GST_STATE_CHANGE_FAILURE)
|
||||
+ {
|
||||
+ ERR("Failed to play source.\n");
|
||||
+ hr = E_OUTOFMEMORY;
|
||||
+ goto fail;
|
||||
+ }
|
||||
+
|
||||
+ WaitForSingleObject(object->all_streams_event, INFINITE);
|
||||
+
|
||||
object->state = SOURCE_STOPPED;
|
||||
|
||||
*out_media_source = object;
|
||||
@@ -893,6 +1272,30 @@ void perform_cb_media_source(struct cb_data *cbdata)
|
||||
cbdata->u.event_src_data.ret = bytestream_pad_event_process(data->pad, data->parent, data->event);
|
||||
break;
|
||||
}
|
||||
+ case MF_SRC_BUS_WATCH:
|
||||
+ {
|
||||
+ struct watch_bus_data *data = &cbdata->u.watch_bus_data;
|
||||
+ cbdata->u.watch_bus_data.ret = bus_watch(data->bus, data->msg, data->user);
|
||||
+ break;
|
||||
+ }
|
||||
+ case MF_SRC_STREAM_ADDED:
|
||||
+ {
|
||||
+ struct pad_added_data *data = &cbdata->u.pad_added_data;
|
||||
+ stream_added(data->element, data->pad, data->user);
|
||||
+ break;
|
||||
+ }
|
||||
+ case MF_SRC_STREAM_REMOVED:
|
||||
+ {
|
||||
+ struct pad_removed_data *data = &cbdata->u.pad_removed_data;
|
||||
+ stream_removed(data->element, data->pad, data->user);
|
||||
+ break;
|
||||
+ }
|
||||
+ case MF_SRC_NO_MORE_PADS:
|
||||
+ {
|
||||
+ struct no_more_pads_data *data = &cbdata->u.no_more_pads_data;
|
||||
+ no_more_pads(data->element, data->user);
|
||||
+ break;
|
||||
+ }
|
||||
default:
|
||||
{
|
||||
assert(0);
|
||||
--
|
||||
2.28.0
|
||||
|
@ -1,381 +0,0 @@
|
||||
From 5119cb0704635fb1b4e30f4b67f86826b28e6015 Mon Sep 17 00:00:00 2001
|
||||
From: Derek Lesho <dlesho@codeweavers.com>
|
||||
Date: Fri, 11 Sep 2020 13:51:20 -0500
|
||||
Subject: [PATCH] winegstreamer: Implement IMFMediaStream::GetStreamDescriptor.
|
||||
|
||||
Signed-off-by: Derek Lesho <dlesho@codeweavers.com>
|
||||
---
|
||||
dlls/winegstreamer/gst_private.h | 4 +
|
||||
dlls/winegstreamer/media_source.c | 75 +++++++++++++-
|
||||
dlls/winegstreamer/mfplat.c | 166 ++++++++++++++++++++++++++++++
|
||||
3 files changed, 240 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/dlls/winegstreamer/gst_private.h b/dlls/winegstreamer/gst_private.h
|
||||
index ef07d3591e7..60b38a48f5a 100644
|
||||
--- a/dlls/winegstreamer/gst_private.h
|
||||
+++ b/dlls/winegstreamer/gst_private.h
|
||||
@@ -36,6 +36,7 @@
|
||||
#include "winuser.h"
|
||||
#include "dshow.h"
|
||||
#include "strmif.h"
|
||||
+#include "mfobjects.h"
|
||||
#include "wine/heap.h"
|
||||
#include "wine/strmbase.h"
|
||||
|
||||
@@ -54,6 +55,9 @@ void start_dispatch_thread(void) DECLSPEC_HIDDEN;
|
||||
|
||||
extern HRESULT mfplat_get_class_object(REFCLSID rclsid, REFIID riid, void **obj) DECLSPEC_HIDDEN;
|
||||
|
||||
+HRESULT winegstreamer_stream_handler_create(REFIID riid, void **obj) DECLSPEC_HIDDEN;
|
||||
+IMFMediaType *mf_media_type_from_caps(const GstCaps *caps) DECLSPEC_HIDDEN;
|
||||
+
|
||||
HRESULT winegstreamer_stream_handler_create(REFIID riid, void **obj) DECLSPEC_HIDDEN;
|
||||
|
||||
#endif /* __GST_PRIVATE_INCLUDED__ */
|
||||
diff --git a/dlls/winegstreamer/media_source.c b/dlls/winegstreamer/media_source.c
|
||||
index f61f84359d5..723f052c10d 100644
|
||||
--- a/dlls/winegstreamer/media_source.c
|
||||
+++ b/dlls/winegstreamer/media_source.c
|
||||
@@ -48,13 +48,17 @@ struct media_stream
|
||||
LONG ref;
|
||||
struct media_source *parent_source;
|
||||
IMFMediaEventQueue *event_queue;
|
||||
+ IMFStreamDescriptor *descriptor;
|
||||
GstElement *appsink;
|
||||
GstPad *their_src, *my_sink;
|
||||
enum
|
||||
{
|
||||
STREAM_STUB,
|
||||
+ STREAM_INACTIVE,
|
||||
STREAM_SHUTDOWN,
|
||||
} state;
|
||||
+ /* used when in STUB state: */
|
||||
+ DWORD stream_id;
|
||||
};
|
||||
|
||||
struct media_source
|
||||
@@ -286,6 +290,8 @@ static ULONG WINAPI media_stream_Release(IMFMediaStream *iface)
|
||||
{
|
||||
if (stream->my_sink)
|
||||
gst_object_unref(GST_OBJECT(stream->my_sink));
|
||||
+ if (stream->descriptor)
|
||||
+ IMFStreamDescriptor_Release(stream->descriptor);
|
||||
if (stream->event_queue)
|
||||
IMFMediaEventQueue_Release(stream->event_queue);
|
||||
if (stream->parent_source)
|
||||
@@ -367,7 +373,10 @@ static HRESULT WINAPI media_stream_GetStreamDescriptor(IMFMediaStream* iface, IM
|
||||
if (stream->state == STREAM_SHUTDOWN)
|
||||
return MF_E_SHUTDOWN;
|
||||
|
||||
- return E_NOTIMPL;
|
||||
+ IMFStreamDescriptor_AddRef(stream->descriptor);
|
||||
+ *descriptor = stream->descriptor;
|
||||
+
|
||||
+ return S_OK;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI media_stream_RequestSample(IMFMediaStream *iface, IUnknown *token)
|
||||
@@ -397,7 +406,7 @@ static const IMFMediaStreamVtbl media_stream_vtbl =
|
||||
};
|
||||
|
||||
/* creates a stub stream */
|
||||
-static HRESULT new_media_stream(struct media_source *source, GstPad *pad, struct media_stream **out_stream)
|
||||
+static HRESULT new_media_stream(struct media_source *source, GstPad *pad, DWORD stream_id, struct media_stream **out_stream)
|
||||
{
|
||||
struct media_stream *object = heap_alloc_zero(sizeof(*object));
|
||||
HRESULT hr;
|
||||
@@ -410,6 +419,7 @@ static HRESULT new_media_stream(struct media_source *source, GstPad *pad, struct
|
||||
IMFMediaSource_AddRef(&source->IMFMediaSource_iface);
|
||||
object->parent_source = source;
|
||||
object->their_src = pad;
|
||||
+ object->stream_id = stream_id;
|
||||
|
||||
object->state = STREAM_STUB;
|
||||
|
||||
@@ -427,8 +437,6 @@ static HRESULT new_media_stream(struct media_source *source, GstPad *pad, struct
|
||||
g_object_set(object->appsink, "max-buffers", 5, NULL);
|
||||
|
||||
object->my_sink = gst_element_get_static_pad(object->appsink, "sink");
|
||||
- gst_pad_set_element_private(object->my_sink, object);
|
||||
-
|
||||
gst_pad_link(object->their_src, object->my_sink);
|
||||
|
||||
gst_element_sync_state_with_parent(object->appsink);
|
||||
@@ -445,6 +453,47 @@ fail:
|
||||
return hr;
|
||||
}
|
||||
|
||||
+static HRESULT media_stream_init_desc(struct media_stream *stream)
|
||||
+{
|
||||
+ GstCaps *current_caps = gst_pad_get_current_caps(stream->their_src);
|
||||
+ IMFMediaTypeHandler *type_handler;
|
||||
+ IMFMediaType *stream_type = NULL;
|
||||
+ HRESULT hr;
|
||||
+
|
||||
+ if (!current_caps)
|
||||
+ {
|
||||
+ hr = E_FAIL;
|
||||
+ goto fail;
|
||||
+ }
|
||||
+
|
||||
+ stream_type = mf_media_type_from_caps(current_caps);
|
||||
+ gst_caps_unref(current_caps);
|
||||
+ if (!stream_type)
|
||||
+ {
|
||||
+ hr = E_FAIL;
|
||||
+ goto fail;
|
||||
+ }
|
||||
+
|
||||
+ if (FAILED(hr = MFCreateStreamDescriptor(stream->stream_id, 1, &stream_type, &stream->descriptor)))
|
||||
+ goto fail;
|
||||
+
|
||||
+ if (FAILED(hr = IMFStreamDescriptor_GetMediaTypeHandler(stream->descriptor, &type_handler)))
|
||||
+ goto fail;
|
||||
+
|
||||
+ if (FAILED(hr = IMFMediaTypeHandler_SetCurrentMediaType(type_handler, stream_type)))
|
||||
+ goto fail;
|
||||
+
|
||||
+ IMFMediaTypeHandler_Release(type_handler);
|
||||
+
|
||||
+ stream->state = STREAM_INACTIVE;
|
||||
+
|
||||
+ return S_OK;
|
||||
+ fail:
|
||||
+ if (type_handler)
|
||||
+ IMFMediaTypeHandler_Release(type_handler);
|
||||
+ return hr;
|
||||
+}
|
||||
+
|
||||
static HRESULT WINAPI media_source_QueryInterface(IMFMediaSource *iface, REFIID riid, void **out)
|
||||
{
|
||||
struct media_source *source = impl_from_IMFMediaSource(iface);
|
||||
@@ -662,7 +711,7 @@ static void stream_added(GstElement *element, GstPad *pad, gpointer user)
|
||||
if (gst_pad_get_direction(pad) != GST_PAD_SRC)
|
||||
return;
|
||||
|
||||
- if (FAILED(new_media_stream(source, pad, &stream)))
|
||||
+ if (FAILED(new_media_stream(source, pad, source->stream_count, &stream)))
|
||||
return;
|
||||
|
||||
if (!(new_stream_array = heap_realloc(source->streams, (source->stream_count + 1) * (sizeof(*new_stream_array)))))
|
||||
@@ -687,6 +736,8 @@ static void stream_removed(GstElement *element, GstPad *pad, gpointer user)
|
||||
if (stream->their_src != pad)
|
||||
continue;
|
||||
stream->their_src = NULL;
|
||||
+ if (stream->state != STREAM_INACTIVE)
|
||||
+ stream->state = STREAM_INACTIVE;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -703,6 +754,7 @@ static HRESULT media_source_constructor(IMFByteStream *bytestream, struct media_
|
||||
GST_STATIC_PAD_TEMPLATE("mf_src", GST_PAD_SRC, GST_PAD_ALWAYS, GST_STATIC_CAPS_ANY);
|
||||
|
||||
struct media_source *object = heap_alloc_zero(sizeof(*object));
|
||||
+ unsigned int i;
|
||||
HRESULT hr;
|
||||
int ret;
|
||||
|
||||
@@ -772,6 +824,19 @@ static HRESULT media_source_constructor(IMFByteStream *bytestream, struct media_
|
||||
}
|
||||
|
||||
WaitForSingleObject(object->all_streams_event, INFINITE);
|
||||
+ for (i = 0; i < object->stream_count; i++)
|
||||
+ {
|
||||
+ GstSample *preroll;
|
||||
+ g_signal_emit_by_name(object->streams[i]->appsink, "pull-preroll", &preroll);
|
||||
+ hr = E_FAIL;
|
||||
+ if (!preroll || 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);
|
||||
+ IMFMediaStream_Release(&object->streams[i]->IMFMediaStream_iface);
|
||||
+ goto fail;
|
||||
+ }
|
||||
+ gst_sample_unref(preroll);
|
||||
+ }
|
||||
|
||||
object->state = SOURCE_STOPPED;
|
||||
|
||||
diff --git a/dlls/winegstreamer/mfplat.c b/dlls/winegstreamer/mfplat.c
|
||||
index c996f06211e..2c2216f94b6 100644
|
||||
--- a/dlls/winegstreamer/mfplat.c
|
||||
+++ b/dlls/winegstreamer/mfplat.c
|
||||
@@ -16,6 +16,11 @@
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
+#include "config.h"
|
||||
+#include <gst/gst.h>
|
||||
+
|
||||
+#include "gst_private.h"
|
||||
+
|
||||
#include <stdarg.h>
|
||||
|
||||
#include "gst_private.h"
|
||||
@@ -436,3 +441,164 @@ HRESULT mfplat_get_class_object(REFCLSID rclsid, REFIID riid, void **obj)
|
||||
|
||||
return CLASS_E_CLASSNOTAVAILABLE;
|
||||
}
|
||||
+
|
||||
+static const struct
|
||||
+{
|
||||
+ const GUID *subtype;
|
||||
+ GstVideoFormat format;
|
||||
+}
|
||||
+uncompressed_video_formats[] =
|
||||
+{
|
||||
+ {&MFVideoFormat_ARGB32, GST_VIDEO_FORMAT_BGRA},
|
||||
+ {&MFVideoFormat_RGB32, GST_VIDEO_FORMAT_BGRx},
|
||||
+ {&MFVideoFormat_RGB24, GST_VIDEO_FORMAT_BGR},
|
||||
+ {&MFVideoFormat_RGB565, GST_VIDEO_FORMAT_BGR16},
|
||||
+ {&MFVideoFormat_RGB555, GST_VIDEO_FORMAT_BGR15},
|
||||
+};
|
||||
+
|
||||
+/* returns NULL if doesn't match exactly */
|
||||
+IMFMediaType *mf_media_type_from_caps(const GstCaps *caps)
|
||||
+{
|
||||
+ IMFMediaType *media_type;
|
||||
+ GstStructure *info;
|
||||
+ const char *mime_type;
|
||||
+
|
||||
+ if (TRACE_ON(mfplat))
|
||||
+ {
|
||||
+ gchar *human_readable = gst_caps_to_string(caps);
|
||||
+ TRACE("caps = %s\n", debugstr_a(human_readable));
|
||||
+ g_free(human_readable);
|
||||
+ }
|
||||
+
|
||||
+ if (FAILED(MFCreateMediaType(&media_type)))
|
||||
+ return NULL;
|
||||
+
|
||||
+ info = gst_caps_get_structure(caps, 0);
|
||||
+ mime_type = gst_structure_get_name(info);
|
||||
+
|
||||
+ if (!strncmp(mime_type, "video", 5))
|
||||
+ {
|
||||
+ GstVideoInfo video_info;
|
||||
+
|
||||
+ if (!gst_video_info_from_caps(&video_info, caps))
|
||||
+ {
|
||||
+ return NULL;
|
||||
+ }
|
||||
+
|
||||
+ IMFMediaType_SetGUID(media_type, &MF_MT_MAJOR_TYPE, &MFMediaType_Video);
|
||||
+
|
||||
+ IMFMediaType_SetUINT64(media_type, &MF_MT_FRAME_SIZE, ((UINT64)video_info.width << 32) | video_info.height);
|
||||
+
|
||||
+ IMFMediaType_SetUINT64(media_type, &MF_MT_FRAME_RATE, ((UINT64)video_info.fps_n << 32) | video_info.fps_d);
|
||||
+
|
||||
+ if (!strcmp(mime_type, "video/x-raw"))
|
||||
+ {
|
||||
+ GUID fourcc_subtype = MFVideoFormat_Base;
|
||||
+ unsigned int i;
|
||||
+
|
||||
+ IMFMediaType_SetUINT32(media_type, &MF_MT_COMPRESSED, FALSE);
|
||||
+
|
||||
+ /* First try FOURCC */
|
||||
+ if ((fourcc_subtype.Data1 = gst_video_format_to_fourcc(video_info.finfo->format)))
|
||||
+ {
|
||||
+ IMFMediaType_SetGUID(media_type, &MF_MT_SUBTYPE, &fourcc_subtype);
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ for (i = 0; i < ARRAY_SIZE(uncompressed_video_formats); i++)
|
||||
+ {
|
||||
+ if (uncompressed_video_formats[i].format == video_info.finfo->format)
|
||||
+ {
|
||||
+ IMFMediaType_SetGUID(media_type, &MF_MT_SUBTYPE, uncompressed_video_formats[i].subtype);
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+ if (i == ARRAY_SIZE(uncompressed_video_formats))
|
||||
+ {
|
||||
+ FIXME("Unrecognized uncompressed video format %x\n", video_info.finfo->format);
|
||||
+ IMFMediaType_Release(media_type);
|
||||
+ return NULL;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ FIXME("Unrecognized video format %s\n", mime_type);
|
||||
+ return NULL;
|
||||
+ }
|
||||
+ }
|
||||
+ else if (!strncmp(mime_type, "audio", 5))
|
||||
+ {
|
||||
+ gint rate, channels, bitrate;
|
||||
+ guint64 channel_mask;
|
||||
+ IMFMediaType_SetGUID(media_type, &MF_MT_MAJOR_TYPE, &MFMediaType_Audio);
|
||||
+
|
||||
+ if (gst_structure_get_int(info, "rate", &rate))
|
||||
+ IMFMediaType_SetUINT32(media_type, &MF_MT_AUDIO_SAMPLES_PER_SECOND, rate);
|
||||
+
|
||||
+ if (gst_structure_get_int(info, "channels", &channels))
|
||||
+ IMFMediaType_SetUINT32(media_type, &MF_MT_AUDIO_NUM_CHANNELS, channels);
|
||||
+
|
||||
+ if (gst_structure_get(info, "channel-mask", GST_TYPE_BITMASK, &channel_mask, NULL))
|
||||
+ IMFMediaType_SetUINT32(media_type, &MF_MT_AUDIO_CHANNEL_MASK, channel_mask);
|
||||
+
|
||||
+ if (gst_structure_get_int(info, "bitrate", &bitrate))
|
||||
+ IMFMediaType_SetUINT32(media_type, &MF_MT_AVG_BITRATE, bitrate);
|
||||
+
|
||||
+ if (!strcmp(mime_type, "audio/x-raw"))
|
||||
+ {
|
||||
+ GstAudioInfo audio_info;
|
||||
+
|
||||
+ if (gst_audio_info_from_caps(&audio_info, caps))
|
||||
+ {
|
||||
+ DWORD depth = GST_AUDIO_INFO_DEPTH(&audio_info);
|
||||
+
|
||||
+ /* validation */
|
||||
+ if ((audio_info.finfo->flags & GST_AUDIO_FORMAT_FLAG_INTEGER && depth > 8) ||
|
||||
+ (audio_info.finfo->flags & GST_AUDIO_FORMAT_FLAG_SIGNED && depth <= 8) ||
|
||||
+ (audio_info.finfo->endianness != G_LITTLE_ENDIAN && depth > 8))
|
||||
+ {
|
||||
+ IMFMediaType_Release(media_type);
|
||||
+ return NULL;
|
||||
+ }
|
||||
+
|
||||
+ /* conversion */
|
||||
+ switch (audio_info.finfo->flags)
|
||||
+ {
|
||||
+ case GST_AUDIO_FORMAT_FLAG_FLOAT:
|
||||
+ IMFMediaType_SetGUID(media_type, &MF_MT_SUBTYPE, &MFAudioFormat_Float);
|
||||
+ break;
|
||||
+ case GST_AUDIO_FORMAT_FLAG_INTEGER:
|
||||
+ case GST_AUDIO_FORMAT_FLAG_SIGNED:
|
||||
+ IMFMediaType_SetGUID(media_type, &MF_MT_SUBTYPE, &MFAudioFormat_PCM);
|
||||
+ break;
|
||||
+ default:
|
||||
+ FIXME("Unrecognized audio format %x\n", audio_info.finfo->format);
|
||||
+ IMFMediaType_Release(media_type);
|
||||
+ return NULL;
|
||||
+ }
|
||||
+
|
||||
+ IMFMediaType_SetUINT32(media_type, &MF_MT_AUDIO_BITS_PER_SAMPLE, depth);
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ ERR("Failed to get caps audio info\n");
|
||||
+ IMFMediaType_Release(media_type);
|
||||
+ return NULL;
|
||||
+ }
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ FIXME("Unrecognized audio format %s\n", mime_type);
|
||||
+ IMFMediaType_Release(media_type);
|
||||
+ return NULL;
|
||||
+ }
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ IMFMediaType_Release(media_type);
|
||||
+ return NULL;
|
||||
+ }
|
||||
+
|
||||
+ return media_type;
|
||||
+}
|
||||
--
|
||||
2.28.0
|
||||
|
@ -1 +1,2 @@
|
||||
Fixes: [49692] mfplat: Improved support for multiple video formats.
|
||||
Disabled: true
|
||||
|
@ -51,7 +51,7 @@ usage()
|
||||
# Get the upstream commit sha
|
||||
upstream_commit()
|
||||
{
|
||||
echo "2ee75bf9ade3e90f10ffe4236c8c95d817402392"
|
||||
echo "23c6dd55b8c983ec88cada0a6d6c75ee9cd93976"
|
||||
}
|
||||
|
||||
# Show version information
|
||||
@ -88,7 +88,6 @@ patch_enable_all ()
|
||||
enable_advapi32_LsaLookupPrivilegeName="$1"
|
||||
enable_api_ms_win_Stub_DLLs="$1"
|
||||
enable_atl_AtlAxDialogBox="$1"
|
||||
enable_bcrypt_ECDHSecretAgreement="$1"
|
||||
enable_cmd_launch_association="$1"
|
||||
enable_color_sRGB_profile="$1"
|
||||
enable_comctl32_Listview_DrawItem="$1"
|
||||
@ -107,7 +106,6 @@ patch_enable_all ()
|
||||
enable_d3dx9_36_D3DXStubs="$1"
|
||||
enable_d3dx9_36_DDS="$1"
|
||||
enable_d3dx9_36_Filter_Warnings="$1"
|
||||
enable_d3dx9_36_Optimize_Inplace="$1"
|
||||
enable_d3dx9_36_UpdateSkinnedMesh="$1"
|
||||
enable_dbghelp_Debug_Symbols="$1"
|
||||
enable_ddraw_Device_Caps="$1"
|
||||
@ -146,7 +144,6 @@ patch_enable_all ()
|
||||
enable_krnl386_exe16_GDT_LDT_Emulation="$1"
|
||||
enable_krnl386_exe16_Invalid_Console_Handles="$1"
|
||||
enable_loader_KeyboardLayouts="$1"
|
||||
enable_mfplat_streaming_support="$1"
|
||||
enable_mmsystem_dll16_MIDIHDR_Refcount="$1"
|
||||
enable_mountmgr_DosDevices="$1"
|
||||
enable_mscoree_CorValidateImage="$1"
|
||||
@ -358,9 +355,6 @@ patch_enable ()
|
||||
atl-AtlAxDialogBox)
|
||||
enable_atl_AtlAxDialogBox="$2"
|
||||
;;
|
||||
bcrypt-ECDHSecretAgreement)
|
||||
enable_bcrypt_ECDHSecretAgreement="$2"
|
||||
;;
|
||||
cmd-launch-association)
|
||||
enable_cmd_launch_association="$2"
|
||||
;;
|
||||
@ -415,9 +409,6 @@ patch_enable ()
|
||||
d3dx9_36-Filter_Warnings)
|
||||
enable_d3dx9_36_Filter_Warnings="$2"
|
||||
;;
|
||||
d3dx9_36-Optimize_Inplace)
|
||||
enable_d3dx9_36_Optimize_Inplace="$2"
|
||||
;;
|
||||
d3dx9_36-UpdateSkinnedMesh)
|
||||
enable_d3dx9_36_UpdateSkinnedMesh="$2"
|
||||
;;
|
||||
@ -532,9 +523,6 @@ patch_enable ()
|
||||
loader-KeyboardLayouts)
|
||||
enable_loader_KeyboardLayouts="$2"
|
||||
;;
|
||||
mfplat-streaming-support)
|
||||
enable_mfplat_streaming_support="$2"
|
||||
;;
|
||||
mmsystem.dll16-MIDIHDR_Refcount)
|
||||
enable_mmsystem_dll16_MIDIHDR_Refcount="$2"
|
||||
;;
|
||||
@ -1840,21 +1828,6 @@ if test "$enable_atl_AtlAxDialogBox" -eq 1; then
|
||||
patch_apply atl-AtlAxDialogBox/0001-atl-Implement-AtlAxDialogBox-A-W.patch
|
||||
fi
|
||||
|
||||
# Patchset bcrypt-ECDHSecretAgreement
|
||||
# |
|
||||
# | This patchset fixes the following Wine bugs:
|
||||
# | * [#47699] Multiple games fail to connect to online services (missing BCryptSecretAgreement / BCryptDeriveKey
|
||||
# | implementation)
|
||||
# |
|
||||
# | Modified files:
|
||||
# | * configure.ac, dlls/bcrypt/Makefile.in, dlls/bcrypt/bcrypt_internal.h, dlls/bcrypt/bcrypt_main.c, dlls/bcrypt/gcrypt.c,
|
||||
# | dlls/bcrypt/gnutls.c, dlls/bcrypt/macos.c, dlls/bcrypt/tests/bcrypt.c
|
||||
# |
|
||||
if test "$enable_bcrypt_ECDHSecretAgreement" -eq 1; then
|
||||
patch_apply bcrypt-ECDHSecretAgreement/0001-bcrypt-Implement-BCryptSecretAgreement-with-libgcryp.patch
|
||||
patch_apply bcrypt-ECDHSecretAgreement/0002-bcrypt-Implement-BCRYPT_KDF_HASH.patch
|
||||
fi
|
||||
|
||||
# Patchset cmd-launch-association
|
||||
# |
|
||||
# | This patchset fixes the following Wine bugs:
|
||||
@ -2196,18 +2169,6 @@ if test "$enable_d3dx9_36_Filter_Warnings" -eq 1; then
|
||||
patch_apply d3dx9_36-Filter_Warnings/0001-d3dx9_36-Filter-out-D3DCompile-warning-messages-that.patch
|
||||
fi
|
||||
|
||||
# Patchset d3dx9_36-Optimize_Inplace
|
||||
# |
|
||||
# | This patchset fixes the following Wine bugs:
|
||||
# | * [#48529] Avencast fails to launch
|
||||
# |
|
||||
# | Modified files:
|
||||
# | * dlls/d3dx9_36/mesh.c
|
||||
# |
|
||||
if test "$enable_d3dx9_36_Optimize_Inplace" -eq 1; then
|
||||
patch_apply d3dx9_36-Optimize_Inplace/0001-d3dx9_36-No-need-to-fail-if-we-don-t-support-vertice.patch
|
||||
fi
|
||||
|
||||
# Patchset d3dx9_36-UpdateSkinnedMesh
|
||||
# |
|
||||
# | This patchset fixes the following Wine bugs:
|
||||
@ -2718,78 +2679,6 @@ if test "$enable_loader_KeyboardLayouts" -eq 1; then
|
||||
patch_apply loader-KeyboardLayouts/0002-user32-Improve-GetKeyboardLayoutList.patch
|
||||
fi
|
||||
|
||||
# Patchset mfplat-streaming-support
|
||||
# |
|
||||
# | This patchset fixes the following Wine bugs:
|
||||
# | * [#49692] mfplat: Improved support for multiple video formats.
|
||||
# |
|
||||
# | Modified files:
|
||||
# | * configure.ac, dlls/mf/Makefile.in, dlls/mf/handler.c, dlls/mf/handler.h, dlls/mf/main.c, dlls/mf/sar.c,
|
||||
# | dlls/mf/session.c, dlls/mf/tests/mf.c, dlls/mf/topology.c, dlls/mfplat/mediatype.c, dlls/mfplat/tests/mfplat.c,
|
||||
# | dlls/mfplat/tests/test.mp4, dlls/mfreadwrite/reader.c, dlls/mfreadwrite/tests/mfplat.c,
|
||||
# | dlls/mfreadwrite/tests/resource.rc, dlls/mfreadwrite/tests/test.mp4, dlls/winegstreamer/Makefile.in,
|
||||
# | dlls/winegstreamer/audioconvert.c, dlls/winegstreamer/colorconvert.c, dlls/winegstreamer/gst_cbs.c,
|
||||
# | dlls/winegstreamer/gst_cbs.h, dlls/winegstreamer/gst_private.h, dlls/winegstreamer/main.c,
|
||||
# | dlls/winegstreamer/media_source.c, dlls/winegstreamer/mf_decode.c, dlls/winegstreamer/mfplat.c,
|
||||
# | dlls/winegstreamer/winegstreamer_classes.idl, include/mfidl.idl, tools/make_makefiles, tools/makedep.c
|
||||
# |
|
||||
if test "$enable_mfplat_streaming_support" -eq 1; then
|
||||
patch_apply mfplat-streaming-support/0001-winegstreamer-Add-a-GstPad-wrapping-the-media-source.patch
|
||||
patch_apply mfplat-streaming-support/0002-winegstreamer-Use-decodebin-to-initialize-media-stre.patch
|
||||
patch_apply mfplat-streaming-support/0003-winegstreamer-Implement-IMFMediaStream-GetStreamDesc.patch
|
||||
patch_apply mfplat-streaming-support/0004-winegstreamer-Insert-parser-into-pipeline-to-rectify.patch
|
||||
patch_apply mfplat-streaming-support/0005-winegstreamer-Insert-videoconvert-into-decoded-video.patch
|
||||
patch_apply mfplat-streaming-support/0006-winegstreamer-Insert-audioconvert-into-decoded-audio.patch
|
||||
patch_apply mfplat-streaming-support/0007-winegstreamer-Translate-H.264-caps-to-attributes.patch
|
||||
patch_apply mfplat-streaming-support/0008-winegstreamer-Translate-WMV-caps-to-attributes.patch
|
||||
patch_apply mfplat-streaming-support/0009-winegstreamer-Translate-AAC-caps-to-attributes.patch
|
||||
patch_apply mfplat-streaming-support/0010-winegstreamer-Translate-MPEG-4-Section-2-caps-to-att.patch
|
||||
patch_apply mfplat-streaming-support/0011-winegstreamer-Translate-WMA-caps-to-attributes.patch
|
||||
patch_apply mfplat-streaming-support/0012-winegstreamer-Implement-IMFMediaSource-CreatePresent.patch
|
||||
patch_apply mfplat-streaming-support/0013-winegstreamer-Introduce-IMFMediaType-GstCaps-convert.patch
|
||||
patch_apply mfplat-streaming-support/0014-winegstreamer-Translate-H.264-attributes-to-caps.patch
|
||||
patch_apply mfplat-streaming-support/0015-winegstreamer-Translate-WMV-attributes-to-caps.patch
|
||||
patch_apply mfplat-streaming-support/0016-winegstreamer-Translate-AAC-attributes-to-caps.patch
|
||||
patch_apply mfplat-streaming-support/0017-winegstreamer-Translate-MPEG-4-Section-2-attributes-.patch
|
||||
patch_apply mfplat-streaming-support/0018-winegstreamer-Translate-WMA-attributes-to-caps.patch
|
||||
patch_apply mfplat-streaming-support/0019-winegstreamer-Implement-IMFMediaSource-Start.patch
|
||||
patch_apply mfplat-streaming-support/0020-winegstreamer-Implement-IMFMediaStream-RequestSample.patch
|
||||
patch_apply mfplat-streaming-support/0021-winegstreamer-Implement-IMFMediaSource-GetCharacteri.patch
|
||||
patch_apply mfplat-streaming-support/0022-winegstreamer-Calculate-the-MF_PD_DURATION-of-the-me.patch
|
||||
patch_apply mfplat-streaming-support/0023-tools-Add-support-for-multiple-parent-directories.patch
|
||||
patch_apply mfplat-streaming-support/0024-mf-Introduce-handler-helper.patch
|
||||
patch_apply mfplat-streaming-support/0025-Introduce-IMFSample-GstBuffer-converter.patch
|
||||
patch_apply mfplat-streaming-support/0026-winegstreamer-Implement-decoder-MFT-on-gstreamer.patch
|
||||
patch_apply mfplat-streaming-support/0027-mfreadwrite-Select-all-streams-when-creating-a-sourc.patch
|
||||
patch_apply mfplat-streaming-support/0028-Miscellaneous.patch
|
||||
patch_apply mfplat-streaming-support/0029-WMV.patch
|
||||
patch_apply mfplat-streaming-support/0030-mf-Ask-for-more-samples-from-upstream-node-when-upon.patch
|
||||
patch_apply mfplat-streaming-support/0031-winegstreamer-Implement-IMFMedisStream-GetMediaSourc.patch
|
||||
patch_apply mfplat-streaming-support/0032-Expose-PCM-output-type-on-AAC-decoder.patch
|
||||
patch_apply mfplat-streaming-support/0033-mfplat-Add-I420-format-information.patch
|
||||
patch_apply mfplat-streaming-support/0034-winegstreamer-Implement-Color-Converter-MFT.patch
|
||||
patch_apply mfplat-streaming-support/0035-HACK-Set-BPS-to-16-for-output-template.patch
|
||||
patch_apply mfplat-streaming-support/0036-Improve-tests.patch
|
||||
patch_apply mfplat-streaming-support/0037-Revert-Improve-tests.patch
|
||||
patch_apply mfplat-streaming-support/0038-Report-streams-backwards-and-only-select-one-of-each.patch
|
||||
patch_apply mfplat-streaming-support/0039-winegstreamer-Implement-IMFMediaSource-Stop.patch
|
||||
patch_apply mfplat-streaming-support/0040-winegstreamer-Introduce-MPEG-4-Section-2-video-decod.patch
|
||||
patch_apply mfplat-streaming-support/0041-HACK-Switch-between-all-selection-streams-on-MF_SOUR.patch
|
||||
patch_apply mfplat-streaming-support/0042-winegstreamer-Introduce-WMA-audio-decoder.patch
|
||||
patch_apply mfplat-streaming-support/0043-Support-stereo-down-folding.patch
|
||||
patch_apply mfplat-streaming-support/0044-winegstreamer-Implement-MF_SD_LANGUAGE.patch
|
||||
patch_apply mfplat-streaming-support/0045-Revert-mf-topoloader-Add-a-structure-for-iterative-b.patch
|
||||
patch_apply mfplat-streaming-support/0046-Revert-mf-topoloader-Clone-source-nodes-as-a-first-l.patch
|
||||
patch_apply mfplat-streaming-support/0047-Revert-mf-topoloader-Switch-to-public-interface-for-.patch
|
||||
patch_apply mfplat-streaming-support/0048-mf-Partially-implement-the-topology-loader.patch
|
||||
patch_apply mfplat-streaming-support/0049-mf-Miscelaneous-fixes-to-topology-resolution.patch
|
||||
patch_apply mfplat-streaming-support/0050-Rewrite-branch-resolver.patch
|
||||
patch_apply mfplat-streaming-support/0051-mf-sar-Compare-against-native-media-type-in-IsMediaT.patch
|
||||
patch_apply mfplat-streaming-support/0052-winegstreamer-Implement-audio-conversion-MFT.patch
|
||||
patch_apply mfplat-streaming-support/0053-winegstreamer-Support-eAVEncH264VProfile_Constrained.patch
|
||||
patch_apply mfplat-streaming-support/0054-winegstreamer-Support-older-versions.patch
|
||||
fi
|
||||
|
||||
# Patchset mmsystem.dll16-MIDIHDR_Refcount
|
||||
# |
|
||||
# | This patchset fixes the following Wine bugs:
|
||||
|
@ -1 +1 @@
|
||||
2ee75bf9ade3e90f10ffe4236c8c95d817402392
|
||||
23c6dd55b8c983ec88cada0a6d6c75ee9cd93976
|
||||
|
Loading…
x
Reference in New Issue
Block a user