mirror of
https://gitlab.winehq.org/wine/wine-staging.git
synced 2024-11-21 16:46:54 -08:00
Updated mfplat-streaming-support patchset
This commit is contained in:
parent
d79463a8b3
commit
9a9401026f
@ -1,18 +1,19 @@
|
||||
From 34ca87dde0bd4e3cab92aaf674903791de20bdc0 Mon Sep 17 00:00:00 2001
|
||||
From 139b483754aee0188f68109dc593df6eb9e083c4 Mon Sep 17 00:00:00 2001
|
||||
From: Derek Lesho <dlesho@codeweavers.com>
|
||||
Date: Mon, 30 Mar 2020 14:19:35 -0500
|
||||
Subject: [PATCH 09/54] winegstreamer: Add a GstPad wrapping the media source's
|
||||
Subject: [PATCH 01/52] 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/media_source.c | 237 +++++++++++++++++++++++++++++-
|
||||
3 files changed, 302 insertions(+), 5 deletions(-)
|
||||
dlls/winegstreamer/main.c | 3 +
|
||||
dlls/winegstreamer/media_source.c | 219 +++++++++++++++++++++++++++++-
|
||||
4 files changed, 288 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/dlls/winegstreamer/gst_cbs.c b/dlls/winegstreamer/gst_cbs.c
|
||||
index bf7103b160..dfe33dd627 100644
|
||||
index bf7103b1606..8f48368c96a 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)
|
||||
@ -84,9 +85,8 @@ index bf7103b160..dfe33dd627 100644
|
||||
+
|
||||
+ return cbdata.u.event_src_data.ret;
|
||||
+}
|
||||
\ No newline at end of file
|
||||
diff --git a/dlls/winegstreamer/gst_cbs.h b/dlls/winegstreamer/gst_cbs.h
|
||||
index 4725f23ad1..10e999feea 100644
|
||||
index 4725f23ad1a..10e999feea7 100644
|
||||
--- a/dlls/winegstreamer/gst_cbs.h
|
||||
+++ b/dlls/winegstreamer/gst_cbs.h
|
||||
@@ -43,7 +43,12 @@ enum CB_TYPE {
|
||||
@ -121,11 +121,28 @@ index 4725f23ad1..10e999feea 100644
|
||||
+gboolean process_bytestream_pad_event_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 09a40a0620..48119e4a89 100644
|
||||
index 84ecf305d4c..6b3bd4a7869 100644
|
||||
--- a/dlls/winegstreamer/media_source.c
|
||||
+++ b/dlls/winegstreamer/media_source.c
|
||||
@@ -1,4 +1,9 @@
|
||||
@@ -17,7 +17,12 @@
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
+#include "config.h"
|
||||
+
|
||||
+#include <gst/gst.h>
|
||||
@ -135,7 +152,7 @@ index 09a40a0620..48119e4a89 100644
|
||||
|
||||
#include <stdarg.h>
|
||||
|
||||
@@ -8,6 +13,7 @@
|
||||
@@ -27,6 +32,7 @@
|
||||
#include "mfapi.h"
|
||||
#include "mferror.h"
|
||||
#include "mfidl.h"
|
||||
@ -143,32 +160,16 @@ index 09a40a0620..48119e4a89 100644
|
||||
|
||||
#include "wine/debug.h"
|
||||
#include "wine/heap.h"
|
||||
@@ -15,11 +21,24 @@
|
||||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(mfplat);
|
||||
|
||||
+static struct source_desc
|
||||
+{
|
||||
+ GstStaticCaps bytestream_caps;
|
||||
+} source_descs[] =
|
||||
+{
|
||||
+ {/*SOURCE_TYPE_MPEG_4*/
|
||||
+ GST_STATIC_CAPS("video/quicktime"),
|
||||
+ }
|
||||
+};
|
||||
+
|
||||
struct media_source
|
||||
{
|
||||
@@ -39,6 +45,8 @@ struct media_source
|
||||
IMFMediaSource IMFMediaSource_iface;
|
||||
LONG ref;
|
||||
+ enum source_type type;
|
||||
IMFMediaEventQueue *event_queue;
|
||||
+ IMFByteStream *byte_stream;
|
||||
+ GstPad *my_src;
|
||||
enum
|
||||
{
|
||||
SOURCE_OPENING,
|
||||
@@ -35,6 +54,154 @@ static inline struct media_source *impl_from_IMFMediaSource(IMFMediaSource *ifac
|
||||
@@ -52,6 +60,154 @@ static inline struct media_source *impl_from_IMFMediaSource(IMFMediaSource *ifac
|
||||
return CONTAINING_RECORD(iface, struct media_source, IMFMediaSource_iface);
|
||||
}
|
||||
|
||||
@ -259,12 +260,12 @@ index 09a40a0620..48119e4a89 100644
|
||||
+ }
|
||||
+ case GST_QUERY_CAPS:
|
||||
+ {
|
||||
+ GstStaticCaps any = GST_STATIC_CAPS_ANY;
|
||||
+ GstCaps *caps, *filter;
|
||||
+
|
||||
+ caps = gst_static_caps_get(&any);
|
||||
+ gst_query_parse_caps(query, &filter);
|
||||
+
|
||||
+ caps = gst_static_caps_get(&source_descs[source->type].bytestream_caps);
|
||||
+
|
||||
+ if (filter) {
|
||||
+ GstCaps* filtered;
|
||||
+ filtered = gst_caps_intersect_full(
|
||||
@ -323,36 +324,28 @@ index 09a40a0620..48119e4a89 100644
|
||||
static HRESULT WINAPI media_source_QueryInterface(IMFMediaSource *iface, REFIID riid, void **out)
|
||||
{
|
||||
struct media_source *source = impl_from_IMFMediaSource(iface);
|
||||
@@ -187,13 +354,20 @@ static HRESULT WINAPI media_source_Pause(IMFMediaSource *iface)
|
||||
@@ -211,8 +367,12 @@ static HRESULT WINAPI media_source_Shutdown(IMFMediaSource *iface)
|
||||
|
||||
FIXME("(%p): stub\n", source);
|
||||
source->state = SOURCE_SHUTDOWN;
|
||||
|
||||
+ if (source->state == SOURCE_SHUTDOWN)
|
||||
+ return MF_E_SHUTDOWN;
|
||||
+
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
static HRESULT media_source_teardown(struct media_source *source)
|
||||
{
|
||||
+ if (source->my_src)
|
||||
+ gst_object_unref(GST_OBJECT(source->my_src));
|
||||
if (source->event_queue)
|
||||
IMFMediaEventQueue_Release(source->event_queue);
|
||||
IMFMediaEventQueue_Shutdown(source->event_queue);
|
||||
+ if (source->byte_stream)
|
||||
+ IMFByteStream_Release(source->byte_stream);
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
@@ -227,19 +401,35 @@ static const IMFMediaSourceVtbl IMFMediaSource_vtbl =
|
||||
@@ -236,19 +396,34 @@ static const IMFMediaSourceVtbl IMFMediaSource_vtbl =
|
||||
|
||||
static HRESULT media_source_constructor(IMFByteStream *bytestream, enum source_type type, struct media_source **out_media_source)
|
||||
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,
|
||||
+ source_descs[type].bytestream_caps);
|
||||
+ GST_STATIC_CAPS_ANY);
|
||||
+
|
||||
struct media_source *object = heap_alloc_zero(sizeof(*object));
|
||||
HRESULT hr;
|
||||
@ -362,7 +355,6 @@ index 09a40a0620..48119e4a89 100644
|
||||
|
||||
+ object->IMFMediaSource_iface.lpVtbl = &IMFMediaSource_vtbl;
|
||||
+ object->ref = 1;
|
||||
+ object->type = type;
|
||||
+ object->byte_stream = bytestream;
|
||||
+ IMFByteStream_AddRef(bytestream);
|
||||
+
|
||||
@ -383,21 +375,10 @@ index 09a40a0620..48119e4a89 100644
|
||||
|
||||
*out_media_source = object;
|
||||
return S_OK;
|
||||
@@ -249,6 +439,7 @@ static HRESULT media_source_constructor(IMFByteStream *bytestream, enum source_t
|
||||
@@ -717,3 +892,41 @@ HRESULT winegstreamer_stream_handler_create(REFIID riid, void **obj)
|
||||
|
||||
media_source_teardown(object);
|
||||
heap_free(object);
|
||||
+ *out_media_source = NULL;
|
||||
return hr;
|
||||
}
|
||||
|
||||
@@ -712,4 +903,42 @@ HRESULT container_stream_handler_construct(REFIID riid, void **obj, enum source_
|
||||
IMFByteStreamHandler_Release(&this->IMFByteStreamHandler_iface);
|
||||
|
||||
return hr;
|
||||
-}
|
||||
\ No newline at end of file
|
||||
+}
|
||||
+
|
||||
+/* helper for callback forwarding */
|
||||
+void perform_cb_media_source(struct cb_data *cbdata)
|
@ -1,24 +1,38 @@
|
||||
From ebb9f982f78533993b773b896cf8b542a301b104 Mon Sep 17 00:00:00 2001
|
||||
From 27ea26494dfa10570c1d2c838660e2169ac9add3 Mon Sep 17 00:00:00 2001
|
||||
From: Derek Lesho <dlesho@codeweavers.com>
|
||||
Date: Mon, 20 Apr 2020 13:02:23 -0500
|
||||
Subject: [PATCH] winegstreamer: Use the demuxer to establish IMFMediaStreams.
|
||||
Date: Tue, 31 Mar 2020 13:34:57 -0500
|
||||
Subject: [PATCH 02/52] winegstreamer: Use decodebin to initialize media
|
||||
streams.
|
||||
|
||||
Signed-off-by: Derek Lesho <dlesho@codeweavers.com>
|
||||
---
|
||||
dlls/winegstreamer/gst_cbs.c | 44 ++++
|
||||
dlls/winegstreamer/gst_cbs.h | 13 +
|
||||
dlls/winegstreamer/media_source.c | 407 ++++++++++++++++++++++++++++++
|
||||
3 files changed, 464 insertions(+)
|
||||
dlls/winegstreamer/gst_cbs.c | 45 ++++
|
||||
dlls/winegstreamer/gst_cbs.h | 8 +
|
||||
dlls/winegstreamer/media_source.c | 416 +++++++++++++++++++++++++++++-
|
||||
3 files changed, 468 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/dlls/winegstreamer/gst_cbs.c b/dlls/winegstreamer/gst_cbs.c
|
||||
index cf49745f1d..d2d36aeb86 100644
|
||||
index 8f48368c96a..4755f5b42f1 100644
|
||||
--- a/dlls/winegstreamer/gst_cbs.c
|
||||
+++ b/dlls/winegstreamer/gst_cbs.c
|
||||
@@ -372,3 +372,47 @@ GstBusSyncReply watch_source_bus_wrapper(GstBus *bus, GstMessage *message, gpoin
|
||||
@@ -359,3 +359,48 @@ gboolean process_bytestream_pad_event_wrapper(GstPad *pad, GstObject *parent, Gs
|
||||
|
||||
return cbdata.u.watch_bus_data.ret;
|
||||
return cbdata.u.event_src_data.ret;
|
||||
}
|
||||
+
|
||||
+GstBusSyncReply watch_source_bus_wrapper(GstBus *bus, GstMessage *message, gpointer user)
|
||||
+{
|
||||
+ struct cb_data cbdata = { WATCH_SOURCE_BUS };
|
||||
+
|
||||
+ 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 source_stream_added_wrapper(GstElement *bin, GstPad *pad, gpointer user)
|
||||
+{
|
||||
+ struct cb_data cbdata = { SOURCE_STREAM_ADDED };
|
||||
@ -50,61 +64,36 @@ index cf49745f1d..d2d36aeb86 100644
|
||||
+
|
||||
+ call_cb(&cbdata);
|
||||
+}
|
||||
+
|
||||
+GstFlowReturn stream_new_sample_wrapper(GstElement *appsink, gpointer user)
|
||||
+{
|
||||
+ struct cb_data cbdata = { STREAM_NEW_SAMPLE };
|
||||
+
|
||||
+ cbdata.u.new_sample_data.appsink = appsink;
|
||||
+ cbdata.u.new_sample_data.user = user;
|
||||
+
|
||||
+ call_cb(&cbdata);
|
||||
+
|
||||
+ return cbdata.u.new_sample_data.ret;
|
||||
+}
|
||||
\ No newline at end of file
|
||||
diff --git a/dlls/winegstreamer/gst_cbs.h b/dlls/winegstreamer/gst_cbs.h
|
||||
index 0d7acaf0b8..106368a064 100644
|
||||
index 10e999feea7..d87cc8c21e9 100644
|
||||
--- a/dlls/winegstreamer/gst_cbs.h
|
||||
+++ b/dlls/winegstreamer/gst_cbs.h
|
||||
@@ -49,6 +49,10 @@ enum CB_TYPE {
|
||||
@@ -48,6 +48,10 @@ enum CB_TYPE {
|
||||
QUERY_BYTESTREAM,
|
||||
ACTIVATE_BYTESTREAM_PAD_MODE,
|
||||
PROCESS_BYTESTREAM_PAD_EVENT,
|
||||
WATCH_SOURCE_BUS,
|
||||
+ WATCH_SOURCE_BUS,
|
||||
+ SOURCE_STREAM_ADDED,
|
||||
+ SOURCE_STREAM_REMOVED,
|
||||
+ SOURCE_ALL_STREAMS,
|
||||
+ STREAM_NEW_SAMPLE,
|
||||
MEDIA_SOURCE_MAX,
|
||||
};
|
||||
|
||||
@@ -134,6 +138,11 @@ struct cb_data {
|
||||
GstQuery *query;
|
||||
gboolean ret;
|
||||
} query_sink_data;
|
||||
+ struct new_sample_data {
|
||||
+ GstElement *appsink;
|
||||
+ gpointer user;
|
||||
+ GstFlowReturn ret;
|
||||
+ } new_sample_data;
|
||||
} u;
|
||||
|
||||
int finished;
|
||||
@@ -166,5 +175,9 @@ gboolean query_bytestream_wrapper(GstPad *pad, GstObject *parent, GstQuery *quer
|
||||
@@ -164,5 +168,9 @@ GstFlowReturn pull_from_bytestream_wrapper(GstPad *pad, GstObject *parent, guint
|
||||
gboolean query_bytestream_wrapper(GstPad *pad, GstObject *parent, GstQuery *query) DECLSPEC_HIDDEN;
|
||||
gboolean activate_bytestream_pad_mode_wrapper(GstPad *pad, GstObject *parent, GstPadMode mode, gboolean activate) DECLSPEC_HIDDEN;
|
||||
gboolean process_bytestream_pad_event_wrapper(GstPad *pad, GstObject *parent, GstEvent *event) DECLSPEC_HIDDEN;
|
||||
GstBusSyncReply watch_source_bus_wrapper(GstBus *bus, GstMessage *message, gpointer user) DECLSPEC_HIDDEN;
|
||||
+GstBusSyncReply watch_source_bus_wrapper(GstBus *bus, GstMessage *message, gpointer user) DECLSPEC_HIDDEN;
|
||||
+void source_stream_added_wrapper(GstElement *bin, GstPad *pad, gpointer user) DECLSPEC_HIDDEN;
|
||||
+void source_stream_removed_wrapper(GstElement *element, GstPad *pad, gpointer user) DECLSPEC_HIDDEN;
|
||||
+void source_all_streams_wrapper(GstElement *element, gpointer user) DECLSPEC_HIDDEN;
|
||||
+GstFlowReturn stream_new_sample_wrapper(GstElement *appsink, gpointer user) DECLSPEC_HIDDEN;
|
||||
|
||||
#endif
|
||||
diff --git a/dlls/winegstreamer/media_source.c b/dlls/winegstreamer/media_source.c
|
||||
index e1f5c77375..192550688d 100644
|
||||
index 6b3bd4a7869..29af2b72def 100644
|
||||
--- a/dlls/winegstreamer/media_source.c
|
||||
+++ b/dlls/winegstreamer/media_source.c
|
||||
@@ -5,6 +5,7 @@
|
||||
@@ -24,6 +24,7 @@
|
||||
#include "gst_private.h"
|
||||
#include "gst_cbs.h"
|
||||
|
||||
@ -112,9 +101,9 @@ index e1f5c77375..192550688d 100644
|
||||
#include <stdarg.h>
|
||||
|
||||
#define COBJMACROS
|
||||
@@ -31,6 +32,26 @@ static struct source_desc
|
||||
}
|
||||
};
|
||||
@@ -40,21 +41,48 @@
|
||||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(mfplat);
|
||||
|
||||
+struct media_stream
|
||||
+{
|
||||
@ -122,16 +111,12 @@ index e1f5c77375..192550688d 100644
|
||||
+ LONG ref;
|
||||
+ struct media_source *parent_source;
|
||||
+ IMFMediaEventQueue *event_queue;
|
||||
+ IMFStreamDescriptor *descriptor;
|
||||
+ GstElement *appsink;
|
||||
+ GstPad *their_src, *my_sink;
|
||||
+ /* usually reflects state of source */
|
||||
+ enum
|
||||
+ {
|
||||
+ STREAM_STUB,
|
||||
+ STREAM_INACTIVE,
|
||||
+ STREAM_ENABLED,
|
||||
+ STREAM_PAUSED,
|
||||
+ STREAM_RUNNING,
|
||||
+ STREAM_SHUTDOWN,
|
||||
+ } state;
|
||||
+};
|
||||
@ -139,8 +124,20 @@ index e1f5c77375..192550688d 100644
|
||||
struct media_source
|
||||
{
|
||||
IMFMediaSource IMFMediaSource_iface;
|
||||
@@ -52,13 +73,32 @@ struct media_source
|
||||
SOURCE_RUNNING,
|
||||
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;
|
||||
@ -154,125 +151,39 @@ index e1f5c77375..192550688d 100644
|
||||
static inline struct media_source *impl_from_IMFMediaSource(IMFMediaSource *iface)
|
||||
{
|
||||
return CONTAINING_RECORD(iface, struct media_source, IMFMediaSource_iface);
|
||||
@@ -208,6 +236,243 @@ static gboolean process_bytestream_pad_event(GstPad *pad, GstObject *parent, Gst
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
+/* inactive stream sample discarder */
|
||||
+static GstFlowReturn stream_new_sample(GstElement *appsink, gpointer user)
|
||||
+{
|
||||
+ struct media_stream *stream = (struct media_stream *) user;
|
||||
+ GstSample *discard_sample;
|
||||
+
|
||||
+ TRACE("(%p) got sample\n", stream);
|
||||
+
|
||||
+ g_signal_emit_by_name(stream->appsink, "pull-sample", &discard_sample);
|
||||
+ gst_sample_unref(discard_sample);
|
||||
+ return GST_FLOW_OK;
|
||||
+}
|
||||
+
|
||||
GstFlowReturn pull_from_bytestream(GstPad *pad, GstObject *parent, guint64 ofs, guint len,
|
||||
GstBuffer **buf)
|
||||
{
|
||||
@@ -238,6 +278,315 @@ GstBusSyncReply watch_source_bus(GstBus *bus, GstMessage *message, gpointer user
|
||||
return GST_BUS_PASS;
|
||||
}
|
||||
|
||||
+static HRESULT media_stream_constructor(struct media_source *source, GstPad *pad, DWORD stream_id, struct media_stream **out_stream);
|
||||
+static void source_stream_added(GstElement *element, GstPad *pad, gpointer user)
|
||||
+GstBusSyncReply watch_source_bus(GstBus *bus, GstMessage *message, gpointer user)
|
||||
+{
|
||||
+ struct media_source *source = (struct media_source *) user;
|
||||
+ struct media_stream **new_stream_array;
|
||||
+ struct media_stream *stream;
|
||||
+ gchar *g_stream_id;
|
||||
+ DWORD stream_id;
|
||||
+ unsigned int i;
|
||||
+ gchar *dbg_info = NULL;
|
||||
+ GError *err = NULL;
|
||||
+
|
||||
+ /* Most/All seen randomly calculate the initial part of the stream id, the last three digits are the only deterministic part */
|
||||
+ g_stream_id = gst_pad_get_stream_id(pad);
|
||||
+ sscanf(strstr(g_stream_id, "/"), "/%03u", &stream_id);
|
||||
+ g_free(g_stream_id);
|
||||
+ TRACE("source %p message type %s\n", source, GST_MESSAGE_TYPE_NAME(message));
|
||||
+
|
||||
+ TRACE("stream-id: %u\n", stream_id);
|
||||
+
|
||||
+ /* find existing stream */
|
||||
+ for (i = 0; i < source->stream_count; i++)
|
||||
+ switch (message->type)
|
||||
+ {
|
||||
+ DWORD existing_stream_id;
|
||||
+ IMFStreamDescriptor *descriptor = source->streams[i]->descriptor;
|
||||
+
|
||||
+ if (FAILED(IMFStreamDescriptor_GetStreamIdentifier(descriptor, &existing_stream_id)))
|
||||
+ goto leave;
|
||||
+
|
||||
+ if (existing_stream_id == stream_id)
|
||||
+ {
|
||||
+ struct media_stream *existing_stream = source->streams[i];
|
||||
+ GstPadLinkReturn ret;
|
||||
+
|
||||
+ TRACE("Found existing stream %p\n", existing_stream);
|
||||
+
|
||||
+ if (!existing_stream->my_sink)
|
||||
+ {
|
||||
+ ERR("Couldn't find our sink\n");
|
||||
+ goto leave;
|
||||
+ }
|
||||
+
|
||||
+ existing_stream->their_src = pad;
|
||||
+ gst_pad_set_element_private(pad, existing_stream);
|
||||
+
|
||||
+ if ((ret = gst_pad_link(existing_stream->their_src, existing_stream->my_sink)) != GST_PAD_LINK_OK)
|
||||
+ {
|
||||
+ ERR("Error linking demuxer to stream %p, err = %d\n", existing_stream, ret);
|
||||
+ }
|
||||
+ gst_element_sync_state_with_parent(existing_stream->appsink);
|
||||
+
|
||||
+ goto leave;
|
||||
+ }
|
||||
+ 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;
|
||||
+ }
|
||||
+
|
||||
+ if (FAILED(media_stream_constructor(source, pad, stream_id, &stream)))
|
||||
+ {
|
||||
+ goto leave;
|
||||
+ }
|
||||
+
|
||||
+ if (!(new_stream_array = heap_realloc(source->streams, (source->stream_count + 1) * (sizeof(*new_stream_array)))))
|
||||
+ {
|
||||
+ ERR("Failed to add stream to source\n");
|
||||
+ goto leave;
|
||||
+ }
|
||||
+
|
||||
+ source->streams = new_stream_array;
|
||||
+ source->streams[source->stream_count++] = stream;
|
||||
+
|
||||
+ leave:
|
||||
+ return;
|
||||
+}
|
||||
+
|
||||
+static void source_stream_removed(GstElement *element, GstPad *pad, gpointer user)
|
||||
+{
|
||||
+ struct media_stream *stream;
|
||||
+
|
||||
+ if (gst_pad_get_direction(pad) != GST_PAD_SRC)
|
||||
+ return;
|
||||
+
|
||||
+ stream = (struct media_stream *) gst_pad_get_element_private(pad);
|
||||
+
|
||||
+ if (stream)
|
||||
+ {
|
||||
+ TRACE("Stream %p of Source %p removed\n", stream, stream->parent_source);
|
||||
+
|
||||
+ assert (stream->their_src == pad);
|
||||
+
|
||||
+ gst_pad_unlink(stream->their_src, stream->my_sink);
|
||||
+
|
||||
+ stream->their_src = NULL;
|
||||
+ gst_pad_set_element_private(pad, NULL);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static void source_all_streams(GstElement *element, gpointer user)
|
||||
+{
|
||||
+ struct media_source *source = (struct media_source *) user;
|
||||
+
|
||||
+ SetEvent(source->all_streams_event);
|
||||
+ return GST_BUS_PASS;
|
||||
+}
|
||||
+
|
||||
+static HRESULT WINAPI media_stream_QueryInterface(IMFMediaStream *iface, REFIID riid, void **out)
|
||||
@ -318,13 +229,8 @@ index e1f5c77375..192550688d 100644
|
||||
+
|
||||
+ if (!ref)
|
||||
+ {
|
||||
+ if (stream->their_src)
|
||||
+ gst_object_unref(GST_OBJECT(stream->their_src));
|
||||
+ 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)
|
||||
@ -435,7 +341,8 @@ index e1f5c77375..192550688d 100644
|
||||
+ media_stream_RequestSample
|
||||
+};
|
||||
+
|
||||
+static HRESULT media_stream_constructor(struct media_source *source, GstPad *pad, DWORD stream_id, struct media_stream **out_stream)
|
||||
+/* creates a stub 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;
|
||||
@ -449,7 +356,7 @@ index e1f5c77375..192550688d 100644
|
||||
+ object->parent_source = source;
|
||||
+ object->their_src = pad;
|
||||
+
|
||||
+ object->state = STREAM_INACTIVE;
|
||||
+ object->state = STREAM_STUB;
|
||||
+
|
||||
+ if (FAILED(hr = MFCreateEventQueue(&object->event_queue)))
|
||||
+ goto fail;
|
||||
@ -463,19 +370,19 @@ index e1f5c77375..192550688d 100644
|
||||
+
|
||||
+ g_object_set(object->appsink, "emit-signals", TRUE, NULL);
|
||||
+ g_object_set(object->appsink, "sync", FALSE, NULL);
|
||||
+ g_object_set(object->appsink, "async", FALSE, NULL); /* <- This allows us interact with the bin w/o prerolling */
|
||||
+ g_signal_connect(object->appsink, "new-sample", G_CALLBACK(stream_new_sample_wrapper), object);
|
||||
+ g_object_set(object->appsink, "max-buffers", 5, NULL);
|
||||
+ g_object_set(object->appsink, "wait-on-eos", FALSE, NULL);
|
||||
+
|
||||
+ object->my_sink = gst_element_get_static_pad(object->appsink, "sink");
|
||||
+ gst_pad_set_element_private(pad, object);
|
||||
+ 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:
|
||||
@ -488,20 +395,27 @@ index e1f5c77375..192550688d 100644
|
||||
static HRESULT WINAPI media_source_QueryInterface(IMFMediaSource *iface, REFIID riid, void **out)
|
||||
{
|
||||
struct media_source *source = impl_from_IMFMediaSource(iface);
|
||||
@@ -398,6 +747,8 @@ static HRESULT WINAPI media_source_Pause(IMFMediaSource *iface)
|
||||
@@ -367,13 +632,34 @@ static HRESULT WINAPI media_source_Shutdown(IMFMediaSource *iface)
|
||||
|
||||
static HRESULT media_source_teardown(struct media_source *source)
|
||||
{
|
||||
+ unsigned int i;
|
||||
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)
|
||||
@@ -412,6 +763,18 @@ static HRESULT media_source_teardown(struct media_source *source)
|
||||
+ 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++)
|
||||
+ for (unsigned int i = 0; i < source->stream_count; i++)
|
||||
+ {
|
||||
+ source->streams[i]->state = STREAM_SHUTDOWN;
|
||||
+ IMFMediaStream_Release(&source->streams[i]->IMFMediaStream_iface);
|
||||
@ -516,29 +430,126 @@ index e1f5c77375..192550688d 100644
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
@@ -464,6 +827,7 @@ static HRESULT media_source_constructor(IMFByteStream *bytestream, enum source_t
|
||||
object->type = type;
|
||||
@@ -394,6 +680,63 @@ static const IMFMediaSourceVtbl IMFMediaSource_vtbl =
|
||||
media_source_Shutdown,
|
||||
};
|
||||
|
||||
+static void source_stream_added(GstElement *element, GstPad *pad, gpointer user)
|
||||
+{
|
||||
+ struct media_source *source = (struct media_source *) user;
|
||||
+ struct media_stream **new_stream_array;
|
||||
+ struct media_stream *stream;
|
||||
+ gchar *g_stream_id;
|
||||
+ DWORD stream_id;
|
||||
+
|
||||
+ if (gst_pad_get_direction(pad) != GST_PAD_SRC)
|
||||
+ return;
|
||||
+
|
||||
+ /* Most/All seen randomly calculate the initial part of the stream id, the last three digits are the only deterministic part */
|
||||
+ g_stream_id = GST_PAD_NAME(pad);
|
||||
+ sscanf(strstr(g_stream_id, "_"), "_%u", &stream_id);
|
||||
+
|
||||
+ TRACE("stream-id: %u\n", stream_id);
|
||||
+
|
||||
+ if (FAILED(new_media_stream(source, pad, stream_id, &stream)))
|
||||
+ {
|
||||
+ goto leave;
|
||||
+ }
|
||||
+
|
||||
+ if (!(new_stream_array = heap_realloc(source->streams, (source->stream_count + 1) * (sizeof(*new_stream_array)))))
|
||||
+ {
|
||||
+ ERR("Failed to add stream to source\n");
|
||||
+ goto leave;
|
||||
+ }
|
||||
+
|
||||
+ source->streams = new_stream_array;
|
||||
+ source->streams[source->stream_count++] = stream;
|
||||
+
|
||||
+ leave:
|
||||
+ return;
|
||||
+}
|
||||
+
|
||||
+static void source_stream_removed(GstElement *element, GstPad *pad, gpointer user)
|
||||
+{
|
||||
+ struct media_source *source = (struct media_source *)user;
|
||||
+
|
||||
+ for (unsigned int i = 0; i < source->stream_count; i++)
|
||||
+ {
|
||||
+ struct media_stream *stream = source->streams[i];
|
||||
+ if (stream->their_src != pad)
|
||||
+ continue;
|
||||
+ stream->their_src = NULL;
|
||||
+ if (stream->state != STREAM_INACTIVE)
|
||||
+ stream->state = STREAM_INACTIVE;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static void source_all_streams(GstElement *element, gpointer user)
|
||||
+{
|
||||
+ struct media_source *source = (struct media_source *) user;
|
||||
+
|
||||
+ SetEvent(source->all_streams_event);
|
||||
+}
|
||||
+
|
||||
static HRESULT media_source_constructor(IMFByteStream *bytestream, struct media_source **out_media_source)
|
||||
{
|
||||
GstStaticPadTemplate src_template = GST_STATIC_PAD_TEMPLATE(
|
||||
@@ -404,6 +747,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;
|
||||
@@ -412,10 +756,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;
|
||||
@@ -509,6 +873,10 @@ static HRESULT media_source_constructor(IMFByteStream *bytestream, enum source_t
|
||||
}
|
||||
gst_bin_add(GST_BIN(object->container), object->demuxer);
|
||||
|
||||
+ g_signal_connect(object->demuxer, "pad-added", G_CALLBACK(source_stream_added_wrapper), object);
|
||||
+ g_signal_connect(object->demuxer, "pad-removed", G_CALLBACK(source_stream_removed_wrapper), object);
|
||||
+ g_signal_connect(object->demuxer, "no-more-pads", G_CALLBACK(source_all_streams_wrapper), object);
|
||||
+ object->container = gst_bin_new(NULL);
|
||||
+ object->bus = gst_bus_new();
|
||||
+ gst_bus_set_sync_handler(object->bus, watch_source_bus_wrapper, object, NULL);
|
||||
+ gst_element_set_bus(object->container, object->bus);
|
||||
+
|
||||
object->their_sink = gst_element_get_static_pad(object->demuxer, "sink");
|
||||
|
||||
if ((ret = gst_pad_link(object->my_src, object->their_sink)) < 0)
|
||||
@@ -518,6 +886,21 @@ static HRESULT media_source_constructor(IMFByteStream *bytestream, enum source_t
|
||||
goto fail;
|
||||
}
|
||||
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, pull_from_bytestream_wrapper);
|
||||
@@ -423,6 +773,46 @@ static HRESULT media_source_constructor(IMFByteStream *bytestream, struct media_
|
||||
gst_pad_set_activatemode_function(object->my_src, activate_bytestream_pad_mode_wrapper);
|
||||
gst_pad_set_event_function(object->my_src, process_bytestream_pad_event_wrapper);
|
||||
|
||||
+ object->decodebin = gst_element_factory_make("decodebin", NULL);
|
||||
+ if (!(object->decodebin))
|
||||
+ {
|
||||
+ WARN("Failed to create decodebin for source\n");
|
||||
+ hr = E_OUTOFMEMORY;
|
||||
+ goto fail;
|
||||
+ }
|
||||
+ /* the appsinks determine the maximum amount of buffering instead, this means that if one stream isn't read, a leak will happen, like on windows */
|
||||
+ 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(source_stream_added_wrapper), object);
|
||||
+ g_signal_connect(object->decodebin, "pad-removed", G_CALLBACK(source_stream_removed_wrapper), object);
|
||||
+ g_signal_connect(object->decodebin, "no-more-pads", G_CALLBACK(source_all_streams_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);
|
||||
@ -551,16 +562,20 @@ index e1f5c77375..192550688d 100644
|
||||
+ }
|
||||
+
|
||||
+ WaitForSingleObject(object->all_streams_event, INFINITE);
|
||||
+
|
||||
+ gst_element_set_state(object->container, GST_STATE_READY);
|
||||
+
|
||||
object->state = SOURCE_STOPPED;
|
||||
|
||||
*out_media_source = object;
|
||||
@@ -1032,6 +1415,30 @@ void perform_cb_media_source(struct cb_data *cbdata)
|
||||
cbdata->u.watch_bus_data.ret = watch_source_bus(data->bus, data->msg, data->user);
|
||||
@@ -923,6 +1313,30 @@ void perform_cb_media_source(struct cb_data *cbdata)
|
||||
cbdata->u.event_src_data.ret = process_bytestream_pad_event(data->pad, data->parent, data->event);
|
||||
break;
|
||||
}
|
||||
+ case WATCH_SOURCE_BUS:
|
||||
+ {
|
||||
+ struct watch_bus_data *data = &cbdata->u.watch_bus_data;
|
||||
+ cbdata->u.watch_bus_data.ret = watch_source_bus(data->bus, data->msg, data->user);
|
||||
+ break;
|
||||
+ }
|
||||
+ case SOURCE_STREAM_ADDED:
|
||||
+ {
|
||||
+ struct pad_added_data *data = &cbdata->u.pad_added_data;
|
||||
@ -578,12 +593,6 @@ index e1f5c77375..192550688d 100644
|
||||
+ struct no_more_pads_data *data = &cbdata->u.no_more_pads_data;
|
||||
+ source_all_streams(data->element, data->user);
|
||||
+ break;
|
||||
+ }
|
||||
+ case STREAM_NEW_SAMPLE:
|
||||
+ {
|
||||
+ struct new_sample_data *data = &cbdata->u.new_sample_data;
|
||||
+ cbdata->u.new_sample_data.ret = stream_new_sample(data->appsink, data->user);
|
||||
+ break;
|
||||
+ }
|
||||
default:
|
||||
{
|
@ -0,0 +1,555 @@
|
||||
From 2bbf345d820cfb52620bfbde10ce5d920854baf1 Mon Sep 17 00:00:00 2001
|
||||
From: Derek Lesho <dlesho@codeweavers.com>
|
||||
Date: Tue, 31 Mar 2020 11:11:05 -0500
|
||||
Subject: [PATCH 03/52] winegstreamer: Implement
|
||||
IMFMediaStream::GetStreamDescriptor.
|
||||
|
||||
Signed-off-by: Derek Lesho <dlesho@codeweavers.com>
|
||||
---
|
||||
dlls/winegstreamer/gst_cbs.c | 13 ++
|
||||
dlls/winegstreamer/gst_cbs.h | 8 ++
|
||||
dlls/winegstreamer/gst_private.h | 5 +
|
||||
dlls/winegstreamer/media_source.c | 137 +++++++++++++++++++-
|
||||
dlls/winegstreamer/mfplat.c | 208 ++++++++++++++++++++++++++++++
|
||||
5 files changed, 368 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/dlls/winegstreamer/gst_cbs.c b/dlls/winegstreamer/gst_cbs.c
|
||||
index 4755f5b42f1..e56c987eb38 100644
|
||||
--- a/dlls/winegstreamer/gst_cbs.c
|
||||
+++ b/dlls/winegstreamer/gst_cbs.c
|
||||
@@ -404,3 +404,16 @@ void source_all_streams_wrapper(GstElement *element, gpointer user)
|
||||
|
||||
call_cb(&cbdata);
|
||||
}
|
||||
+
|
||||
+GstPadProbeReturn caps_listener_wrapper(GstPad *pad, GstPadProbeInfo *info, gpointer user)
|
||||
+{
|
||||
+ struct cb_data cbdata = { STREAM_PAD_EVENT };
|
||||
+
|
||||
+ cbdata.u.pad_probe_data.pad = pad;
|
||||
+ cbdata.u.pad_probe_data.info = info;
|
||||
+ cbdata.u.pad_probe_data.user = user;
|
||||
+
|
||||
+ call_cb(&cbdata);
|
||||
+
|
||||
+ return cbdata.u.pad_probe_data.ret;
|
||||
+}
|
||||
diff --git a/dlls/winegstreamer/gst_cbs.h b/dlls/winegstreamer/gst_cbs.h
|
||||
index d87cc8c21e9..7173c09746e 100644
|
||||
--- a/dlls/winegstreamer/gst_cbs.h
|
||||
+++ b/dlls/winegstreamer/gst_cbs.h
|
||||
@@ -52,6 +52,7 @@ enum CB_TYPE {
|
||||
SOURCE_STREAM_ADDED,
|
||||
SOURCE_STREAM_REMOVED,
|
||||
SOURCE_ALL_STREAMS,
|
||||
+ STREAM_PAD_EVENT,
|
||||
MEDIA_SOURCE_MAX,
|
||||
};
|
||||
|
||||
@@ -137,6 +138,12 @@ struct cb_data {
|
||||
GstQuery *query;
|
||||
gboolean ret;
|
||||
} query_sink_data;
|
||||
+ struct pad_probe_data {
|
||||
+ GstPad *pad;
|
||||
+ GstPadProbeInfo *info;
|
||||
+ gpointer user;
|
||||
+ GstPadProbeReturn ret;
|
||||
+ } pad_probe_data;
|
||||
} u;
|
||||
|
||||
int finished;
|
||||
@@ -172,5 +179,6 @@ GstBusSyncReply watch_source_bus_wrapper(GstBus *bus, GstMessage *message, gpoin
|
||||
void source_stream_added_wrapper(GstElement *bin, GstPad *pad, gpointer user) DECLSPEC_HIDDEN;
|
||||
void source_stream_removed_wrapper(GstElement *element, GstPad *pad, gpointer user) DECLSPEC_HIDDEN;
|
||||
void source_all_streams_wrapper(GstElement *element, gpointer user) DECLSPEC_HIDDEN;
|
||||
+GstPadProbeReturn caps_listener_wrapper(GstPad *pad, GstPadProbeInfo *info, gpointer user);
|
||||
|
||||
#endif
|
||||
diff --git a/dlls/winegstreamer/gst_private.h b/dlls/winegstreamer/gst_private.h
|
||||
index ef07d3591e7..86392eea4e3 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,10 @@ 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;
|
||||
+GstCaps *make_mf_compatible_caps(GstCaps *caps);
|
||||
+IMFMediaType *mf_media_type_from_caps(GstCaps *caps);
|
||||
+
|
||||
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 29af2b72def..345b1fe4528 100644
|
||||
--- a/dlls/winegstreamer/media_source.c
|
||||
+++ b/dlls/winegstreamer/media_source.c
|
||||
@@ -47,14 +47,19 @@ struct media_stream
|
||||
LONG ref;
|
||||
struct media_source *parent_source;
|
||||
IMFMediaEventQueue *event_queue;
|
||||
+ IMFStreamDescriptor *descriptor;
|
||||
GstElement *appsink;
|
||||
GstPad *their_src, *my_sink;
|
||||
+ GstCaps *their_caps;
|
||||
enum
|
||||
{
|
||||
STREAM_STUB,
|
||||
STREAM_INACTIVE,
|
||||
STREAM_SHUTDOWN,
|
||||
} state;
|
||||
+ /* used when in STUB state: */
|
||||
+ DWORD stream_id;
|
||||
+ HANDLE caps_event;
|
||||
};
|
||||
|
||||
struct media_source
|
||||
@@ -312,6 +317,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)
|
||||
@@ -393,7 +400,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)
|
||||
@@ -436,9 +446,12 @@ static HRESULT new_media_stream(struct media_source *source, GstPad *pad, DWORD
|
||||
IMFMediaSource_AddRef(&source->IMFMediaSource_iface);
|
||||
object->parent_source = source;
|
||||
object->their_src = pad;
|
||||
+ object->stream_id = stream_id;
|
||||
|
||||
object->state = STREAM_STUB;
|
||||
|
||||
+ object->caps_event = CreateEventA(NULL, TRUE, FALSE, NULL);
|
||||
+
|
||||
if (FAILED(hr = MFCreateEventQueue(&object->event_queue)))
|
||||
goto fail;
|
||||
|
||||
@@ -455,10 +468,10 @@ static HRESULT new_media_stream(struct media_source *source, GstPad *pad, DWORD
|
||||
g_object_set(object->appsink, "wait-on-eos", FALSE, 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_pad_add_probe(object->my_sink, GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM, caps_listener_wrapper, object, NULL);
|
||||
+
|
||||
gst_element_sync_state_with_parent(object->appsink);
|
||||
|
||||
TRACE("->(%p)\n", object);
|
||||
@@ -473,6 +486,43 @@ static HRESULT new_media_stream(struct media_source *source, GstPad *pad, DWORD
|
||||
return hr;
|
||||
}
|
||||
|
||||
+static HRESULT media_stream_init_desc(struct media_stream *stream)
|
||||
+{
|
||||
+ HRESULT hr;
|
||||
+ IMFMediaTypeHandler *type_handler;
|
||||
+ IMFMediaType *stream_type = NULL;
|
||||
+
|
||||
+ stream->their_caps = gst_caps_fixate(stream->their_caps);
|
||||
+
|
||||
+ stream_type = mf_media_type_from_caps(stream->their_caps);
|
||||
+ gst_caps_unref(stream->their_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:
|
||||
+ ERR("media stream initialization failed with %x\n", hr);
|
||||
+ 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);
|
||||
@@ -680,6 +730,23 @@ static const IMFMediaSourceVtbl IMFMediaSource_vtbl =
|
||||
media_source_Shutdown,
|
||||
};
|
||||
|
||||
+/* If this callback is extended to use any significant win32 APIs, a wrapper function
|
||||
+ should be added */
|
||||
+gboolean stream_found(GstElement *bin, GstPad *pad, GstCaps *caps, gpointer user)
|
||||
+{
|
||||
+ GstCaps *target_caps;
|
||||
+
|
||||
+ /* if the stream can be converted into an MF compatible type, we'll go that route
|
||||
+ otherwise, we'll rely on decodebin for the whole process */
|
||||
+
|
||||
+ if ((target_caps = make_mf_compatible_caps(caps)))
|
||||
+ {
|
||||
+ gst_caps_unref(target_caps);
|
||||
+ return FALSE;
|
||||
+ }
|
||||
+ return TRUE;
|
||||
+}
|
||||
+
|
||||
static void source_stream_added(GstElement *element, GstPad *pad, gpointer user)
|
||||
{
|
||||
struct media_source *source = (struct media_source *) user;
|
||||
@@ -697,6 +764,36 @@ static void source_stream_added(GstElement *element, GstPad *pad, gpointer user)
|
||||
|
||||
TRACE("stream-id: %u\n", stream_id);
|
||||
|
||||
+ /* This codepath is currently never triggered, as we don't need to ever restart the gstreamer pipeline. It is retained in
|
||||
+ case this becomes necessary in the future, for example in a case where different media types require different
|
||||
+ post-processing elements. */
|
||||
+ for (unsigned int i = 0; i < source->stream_count; i++)
|
||||
+ {
|
||||
+ DWORD existing_stream_id;
|
||||
+ IMFStreamDescriptor *descriptor = source->streams[i]->descriptor;
|
||||
+
|
||||
+ if (source->streams[i]->state == STREAM_STUB)
|
||||
+ continue;
|
||||
+
|
||||
+ if (FAILED(IMFStreamDescriptor_GetStreamIdentifier(descriptor, &existing_stream_id)))
|
||||
+ goto leave;
|
||||
+
|
||||
+ if (existing_stream_id == stream_id)
|
||||
+ {
|
||||
+ struct media_stream *existing_stream = source->streams[i];
|
||||
+ GstPadLinkReturn ret;
|
||||
+
|
||||
+ TRACE("Found existing stream %p\n", existing_stream);
|
||||
+
|
||||
+ existing_stream->their_src = pad;
|
||||
+
|
||||
+ if ((ret = gst_pad_link(existing_stream->their_src, existing_stream->my_sink)) != GST_PAD_LINK_OK)
|
||||
+ ERR("Error linking decodebin pad to stream %p, err = %d\n", existing_stream, ret);
|
||||
+
|
||||
+ goto leave;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
if (FAILED(new_media_stream(source, pad, stream_id, &stream)))
|
||||
{
|
||||
goto leave;
|
||||
@@ -737,6 +834,26 @@ static void source_all_streams(GstElement *element, gpointer user)
|
||||
SetEvent(source->all_streams_event);
|
||||
}
|
||||
|
||||
+static GstPadProbeReturn caps_listener(GstPad *pad, GstPadProbeInfo *info, gpointer user)
|
||||
+{
|
||||
+ struct media_stream *stream = (struct media_stream *) user;
|
||||
+ GstEvent *event = gst_pad_probe_info_get_event(info);
|
||||
+
|
||||
+ if (GST_EVENT_TYPE(event) == GST_EVENT_CAPS)
|
||||
+ {
|
||||
+ GstCaps *caps;
|
||||
+ TRACE("got caps for stream %p\n", stream);
|
||||
+
|
||||
+ gst_event_parse_caps(event, &caps);
|
||||
+ stream->their_caps = gst_caps_copy(caps);
|
||||
+ SetEvent(stream->caps_event);
|
||||
+
|
||||
+ return GST_PAD_PROBE_REMOVE;
|
||||
+ }
|
||||
+
|
||||
+ return GST_PAD_PROBE_OK;
|
||||
+}
|
||||
+
|
||||
static HRESULT media_source_constructor(IMFByteStream *bytestream, struct media_source **out_media_source)
|
||||
{
|
||||
GstStaticPadTemplate src_template = GST_STATIC_PAD_TEMPLATE(
|
||||
@@ -787,6 +904,8 @@ static HRESULT media_source_constructor(IMFByteStream *bytestream, struct media_
|
||||
|
||||
gst_bin_add(GST_BIN(object->container), object->decodebin);
|
||||
|
||||
+ if(!GetEnvironmentVariableA("MF_DECODE_IN_SOURCE", NULL, 0))
|
||||
+ g_signal_connect(object->decodebin, "autoplug-continue", G_CALLBACK(stream_found), object);
|
||||
g_signal_connect(object->decodebin, "pad-added", G_CALLBACK(source_stream_added_wrapper), object);
|
||||
g_signal_connect(object->decodebin, "pad-removed", G_CALLBACK(source_stream_removed_wrapper), object);
|
||||
g_signal_connect(object->decodebin, "no-more-pads", G_CALLBACK(source_all_streams_wrapper), object);
|
||||
@@ -812,6 +931,12 @@ static HRESULT media_source_constructor(IMFByteStream *bytestream, struct media_
|
||||
}
|
||||
|
||||
WaitForSingleObject(object->all_streams_event, INFINITE);
|
||||
+ for (unsigned int i = 0; i < object->stream_count; i++)
|
||||
+ {
|
||||
+ WaitForSingleObject(object->streams[i]->caps_event, INFINITE);
|
||||
+ if (FAILED(hr = media_stream_init_desc(object->streams[i])))
|
||||
+ goto fail;
|
||||
+ }
|
||||
|
||||
object->state = SOURCE_STOPPED;
|
||||
|
||||
@@ -1337,6 +1462,12 @@ void perform_cb_media_source(struct cb_data *cbdata)
|
||||
source_all_streams(data->element, data->user);
|
||||
break;
|
||||
}
|
||||
+ case STREAM_PAD_EVENT:
|
||||
+ {
|
||||
+ struct pad_probe_data *data = &cbdata->u.pad_probe_data;
|
||||
+ cbdata->u.pad_probe_data.ret = caps_listener(data->pad, data->info, data->user);
|
||||
+ break;
|
||||
+ }
|
||||
default:
|
||||
{
|
||||
ERR("Wrong callback forwarder called\n");
|
||||
diff --git a/dlls/winegstreamer/mfplat.c b/dlls/winegstreamer/mfplat.c
|
||||
index c996f06211e..3667bc3cc38 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,206 @@ HRESULT mfplat_get_class_object(REFCLSID rclsid, REFIID riid, void **obj)
|
||||
|
||||
return CLASS_E_CLASSNOTAVAILABLE;
|
||||
}
|
||||
+
|
||||
+const static struct
|
||||
+{
|
||||
+ const GUID *subtype;
|
||||
+ GstVideoFormat format;
|
||||
+}
|
||||
+uncompressed_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},
|
||||
+};
|
||||
+
|
||||
+/* caps will be modified to represent the exact type needed for the format */
|
||||
+static IMFMediaType* transform_to_media_type(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_formats); i++)
|
||||
+ {
|
||||
+ if (uncompressed_formats[i].format == video_info.finfo->format)
|
||||
+ {
|
||||
+ IMFMediaType_SetGUID(media_type, &MF_MT_SUBTYPE, uncompressed_formats[i].subtype);
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+ if (i == ARRAY_SIZE(uncompressed_formats))
|
||||
+ FIXME("Unrecognized format.\n");
|
||||
+ }
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ FIXME("Unrecognized video format %s\n", mime_type);
|
||||
+ IMFMediaType_Release(media_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, (DWORD)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")))
|
||||
+ {
|
||||
+ const char *format;
|
||||
+ if ((format = gst_structure_get_string(info, "format")))
|
||||
+ {
|
||||
+ char type;
|
||||
+ unsigned int bits_per_sample;
|
||||
+ char endian[2];
|
||||
+ char new_format[6];
|
||||
+ if ((strlen(format) > 5) || (sscanf(format, "%c%u%2c", &type, &bits_per_sample, endian) < 2))
|
||||
+ {
|
||||
+ FIXME("Unhandled audio format %s\n", format);
|
||||
+ IMFMediaType_Release(media_type);
|
||||
+ return NULL;
|
||||
+ }
|
||||
+
|
||||
+ if (type == 'F')
|
||||
+ {
|
||||
+ IMFMediaType_SetGUID(media_type, &MF_MT_SUBTYPE, &MFAudioFormat_Float);
|
||||
+ }
|
||||
+ else if (type == 'U' || type == 'S')
|
||||
+ {
|
||||
+ IMFMediaType_SetGUID(media_type, &MF_MT_SUBTYPE, &MFAudioFormat_PCM);
|
||||
+ if (bits_per_sample == 8)
|
||||
+ type = 'U';
|
||||
+ else
|
||||
+ type = 'S';
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ FIXME("Unrecognized audio format: %s\n", format);
|
||||
+ IMFMediaType_Release(media_type);
|
||||
+ return NULL;
|
||||
+ }
|
||||
+
|
||||
+ IMFMediaType_SetUINT32(media_type, &MF_MT_AUDIO_BITS_PER_SAMPLE, bits_per_sample);
|
||||
+
|
||||
+ if (endian[0] == 'B')
|
||||
+ endian[0] = 'L';
|
||||
+
|
||||
+ sprintf(new_format, "%c%u%.2s", type, bits_per_sample, bits_per_sample > 8 ? endian : 0);
|
||||
+ gst_caps_set_simple(caps, "format", G_TYPE_STRING, new_format, NULL);
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ ERR("Failed to get audio format\n");
|
||||
+ }
|
||||
+ }
|
||||
+ 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;
|
||||
+}
|
||||
+
|
||||
+/* returns NULL if doesn't match exactly */
|
||||
+IMFMediaType *mf_media_type_from_caps(GstCaps *caps)
|
||||
+{
|
||||
+ GstCaps *writeable_caps;
|
||||
+ IMFMediaType *ret;
|
||||
+
|
||||
+ writeable_caps = gst_caps_copy(caps);
|
||||
+ ret = transform_to_media_type(writeable_caps);
|
||||
+
|
||||
+ if (!(gst_caps_is_equal(caps, writeable_caps)))
|
||||
+ {
|
||||
+ IMFMediaType_Release(ret);
|
||||
+ ret = NULL;
|
||||
+ }
|
||||
+ gst_caps_unref(writeable_caps);
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+GstCaps *make_mf_compatible_caps(GstCaps *caps)
|
||||
+{
|
||||
+ GstCaps *ret;
|
||||
+ IMFMediaType *media_type;
|
||||
+
|
||||
+ ret = gst_caps_copy(caps);
|
||||
+
|
||||
+ if ((media_type = transform_to_media_type(ret)))
|
||||
+ IMFMediaType_Release(media_type);
|
||||
+
|
||||
+ if (!media_type)
|
||||
+ {
|
||||
+ gst_caps_unref(ret);
|
||||
+ return NULL;
|
||||
+ }
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
--
|
||||
2.28.0
|
||||
|
@ -1,50 +0,0 @@
|
||||
From a78920ed5d799815126b294c4ecf0b039cf5671c Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Sergio=20G=C3=B3mez=20Del=20Real?=
|
||||
<sdelreal@codeweavers.com>
|
||||
Date: Wed, 1 Apr 2020 16:11:05 -0500
|
||||
Subject: [PATCH 04/54] mf/tests: Sink objects are stream sinks, not media
|
||||
sinks.
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Signed-off-by: Sergio Gómez Del Real <sdelreal@codeweavers.com>
|
||||
---
|
||||
dlls/mf/tests/mf.c | 7 +++++--
|
||||
1 file changed, 5 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/dlls/mf/tests/mf.c b/dlls/mf/tests/mf.c
|
||||
index aa2c5199b9..9e190388ee 100644
|
||||
--- a/dlls/mf/tests/mf.c
|
||||
+++ b/dlls/mf/tests/mf.c
|
||||
@@ -1400,6 +1400,7 @@ static void test_topology_loader(void)
|
||||
IMFPresentationDescriptor *pd;
|
||||
IMFSourceResolver *resolver;
|
||||
IMFActivate *sink_activate;
|
||||
+ IMFStreamSink *stream_sink;
|
||||
unsigned int count, value;
|
||||
IMFMediaType *media_type;
|
||||
IMFStreamDescriptor *sd;
|
||||
@@ -1512,7 +1513,10 @@ todo_wine
|
||||
hr = IMFActivate_ActivateObject(sink_activate, &IID_IMFMediaSink, (void **)&sink);
|
||||
ok(hr == S_OK, "Failed to activate, hr %#x.\n", hr);
|
||||
|
||||
- hr = IMFTopologyNode_SetObject(sink_node, (IUnknown *)sink);
|
||||
+ hr = IMFMediaSink_GetStreamSinkByIndex(sink, 0, &stream_sink);
|
||||
+ ok(hr == S_OK, "Failed to get stream sink, hr %#x.\n", hr);
|
||||
+
|
||||
+ hr = IMFTopologyNode_SetObject(sink_node, (IUnknown *)stream_sink);
|
||||
ok(hr == S_OK, "Failed to set object, hr %#x.\n", hr);
|
||||
|
||||
hr = IMFTopology_GetCount(topology, &count);
|
||||
@@ -1520,7 +1524,6 @@ todo_wine
|
||||
ok(count == 0, "Unexpected count %u.\n", count);
|
||||
|
||||
hr = IMFTopoLoader_Load(loader, topology, &full_topology, NULL);
|
||||
-todo_wine
|
||||
ok(hr == S_OK, "Failed to resolve topology, hr %#x.\n", hr);
|
||||
ok(full_topology != topology, "Unexpected instance.\n");
|
||||
|
||||
--
|
||||
2.28.0
|
||||
|
@ -0,0 +1,169 @@
|
||||
From c8effecf2d89b5169b03f4d71243729b68d4c3ba Mon Sep 17 00:00:00 2001
|
||||
From: Derek Lesho <dlesho@codeweavers.com>
|
||||
Date: Tue, 31 Mar 2020 15:11:31 -0500
|
||||
Subject: [PATCH 04/52] winegstreamer: Insert parser into pipeline to rectify
|
||||
type differences.
|
||||
|
||||
Signed-off-by: Derek Lesho <dlesho@codeweavers.com>
|
||||
---
|
||||
dlls/winegstreamer/media_source.c | 130 +++++++++++++++++++++++++++++-
|
||||
1 file changed, 127 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/dlls/winegstreamer/media_source.c b/dlls/winegstreamer/media_source.c
|
||||
index 345b1fe4528..f1e8c5799f7 100644
|
||||
--- a/dlls/winegstreamer/media_source.c
|
||||
+++ b/dlls/winegstreamer/media_source.c
|
||||
@@ -432,6 +432,122 @@ static const IMFMediaStreamVtbl media_stream_vtbl =
|
||||
media_stream_RequestSample
|
||||
};
|
||||
|
||||
+/* There are two paths this function can take.
|
||||
+ 1) In the first path, we are acting as a real media source, purely demuxing the input data,
|
||||
+ in whichever format it may be in, and passing it along. However, there can be different ways
|
||||
+ to interpret the same streams. Subtypes in MF usually carry an implicit meaning, so we define
|
||||
+ what caps an IMFMediaType corresponds to in mfplat.c, and insert a parser between decodebin
|
||||
+ and the appsink, which usually can resolve these differences. As an example, MFVideoFormat_H264
|
||||
+ implies stream-format=byte-stream, and inserting h264parse can transform stream-format=avc
|
||||
+ into stream-format=byte-stream.
|
||||
+ 2) In the second path, we are dealing with x-raw output from decodebin. In this case, we just
|
||||
+ have to setup a chain of elements which should hopefully allow transformations to any IMFMediaType
|
||||
+ the user throws at us through gstreamer's caps negotiation.*/
|
||||
+static HRESULT media_stream_align_with_mf(struct media_stream *stream)
|
||||
+{
|
||||
+ GstCaps *source_caps = NULL;
|
||||
+ GstCaps *target_caps = NULL;
|
||||
+ HRESULT hr = E_FAIL;
|
||||
+
|
||||
+ if (!(source_caps = gst_pad_query_caps(stream->their_src, NULL)))
|
||||
+ goto done;
|
||||
+
|
||||
+ if (TRACE_ON(mfplat))
|
||||
+ {
|
||||
+ gchar *source_caps_str = gst_caps_to_string(source_caps);
|
||||
+ TRACE("source caps %s\n", debugstr_a(source_caps_str));
|
||||
+ g_free(source_caps_str);
|
||||
+ }
|
||||
+
|
||||
+ if (!strcmp(gst_structure_get_name(gst_caps_get_structure(source_caps, 0)), "video/x-raw") ||
|
||||
+ !strcmp(gst_structure_get_name(gst_caps_get_structure(source_caps, 0)), "audio/x-raw"))
|
||||
+ {
|
||||
+ stream->my_sink = gst_element_get_static_pad(stream->appsink, "sink");
|
||||
+ g_object_set(stream->appsink, "caps", source_caps, NULL);
|
||||
+ assert(gst_pad_link(stream->their_src, stream->my_sink) == GST_PAD_LINK_OK);
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ GstElement *parser = NULL;
|
||||
+
|
||||
+ assert(gst_caps_is_fixed(source_caps));
|
||||
+
|
||||
+ if (!(target_caps = make_mf_compatible_caps(source_caps)))
|
||||
+ goto done;
|
||||
+
|
||||
+ if (TRACE_ON(mfplat))
|
||||
+ {
|
||||
+ gchar *target_caps_str = gst_caps_to_string(target_caps);
|
||||
+ TRACE("target caps %s\n", debugstr_a(target_caps_str));
|
||||
+ g_free(target_caps_str);
|
||||
+ }
|
||||
+
|
||||
+ g_object_set(stream->appsink, "caps", target_caps, NULL);
|
||||
+
|
||||
+ if (!(gst_caps_is_equal(source_caps, target_caps)))
|
||||
+ {
|
||||
+ GList *parser_list_one, *parser_list_two;
|
||||
+ GstElementFactory *parser_factory;
|
||||
+
|
||||
+ parser_list_one = gst_element_factory_list_get_elements(GST_ELEMENT_FACTORY_TYPE_PARSER, 1);
|
||||
+
|
||||
+ parser_list_two = gst_element_factory_list_filter(parser_list_one, source_caps, GST_PAD_SINK, 0);
|
||||
+ gst_plugin_feature_list_free(parser_list_one);
|
||||
+ parser_list_one = parser_list_two;
|
||||
+
|
||||
+ parser_list_two = gst_element_factory_list_filter(parser_list_one, target_caps, GST_PAD_SRC, 0);
|
||||
+ gst_plugin_feature_list_free(parser_list_one);
|
||||
+ parser_list_one = parser_list_two;
|
||||
+
|
||||
+ if (!(g_list_length(parser_list_one)))
|
||||
+ {
|
||||
+ gst_plugin_feature_list_free(parser_list_one);
|
||||
+ ERR("Failed to find parser for stream\n");
|
||||
+ hr = E_FAIL;
|
||||
+ goto done;
|
||||
+ }
|
||||
+
|
||||
+ parser_factory = g_list_first(parser_list_one)->data;
|
||||
+ TRACE("Found parser %s.\n", GST_ELEMENT_NAME(parser_factory));
|
||||
+
|
||||
+ parser = gst_element_factory_create(parser_factory, NULL);
|
||||
+
|
||||
+ gst_plugin_feature_list_free(parser_list_one);
|
||||
+
|
||||
+ if (!parser)
|
||||
+ {
|
||||
+ hr = E_FAIL;
|
||||
+ goto done;
|
||||
+ }
|
||||
+
|
||||
+ gst_bin_add(GST_BIN(stream->parent_source->container), parser);
|
||||
+
|
||||
+ assert(gst_pad_link(stream->their_src, gst_element_get_static_pad(parser, "sink")) == GST_PAD_LINK_OK);
|
||||
+
|
||||
+ assert(gst_element_link(parser, stream->appsink));
|
||||
+
|
||||
+ gst_element_sync_state_with_parent(parser);
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ assert(gst_pad_link(stream->their_src, gst_element_get_static_pad(stream->appsink, "sink")) == GST_PAD_LINK_OK);
|
||||
+ }
|
||||
+
|
||||
+ stream->my_sink = gst_element_get_static_pad(parser ? parser : stream->appsink, "sink");
|
||||
+ }
|
||||
+
|
||||
+ hr = S_OK;
|
||||
+
|
||||
+ done:
|
||||
+ if (source_caps)
|
||||
+ gst_caps_unref(source_caps);
|
||||
+ if (target_caps)
|
||||
+ gst_caps_unref(target_caps);
|
||||
+
|
||||
+ return hr;
|
||||
+}
|
||||
+
|
||||
+
|
||||
/* creates a stub stream */
|
||||
static HRESULT new_media_stream(struct media_source *source, GstPad *pad, DWORD stream_id, struct media_stream **out_stream)
|
||||
{
|
||||
@@ -467,8 +583,7 @@ static HRESULT new_media_stream(struct media_source *source, GstPad *pad, DWORD
|
||||
g_object_set(object->appsink, "max-buffers", 5, NULL);
|
||||
g_object_set(object->appsink, "wait-on-eos", FALSE, NULL);
|
||||
|
||||
- object->my_sink = gst_element_get_static_pad(object->appsink, "sink");
|
||||
- gst_pad_link(object->their_src, object->my_sink);
|
||||
+ media_stream_align_with_mf(object);
|
||||
|
||||
gst_pad_add_probe(object->my_sink, GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM, caps_listener_wrapper, object, NULL);
|
||||
|
||||
@@ -494,7 +609,16 @@ static HRESULT media_stream_init_desc(struct media_stream *stream)
|
||||
|
||||
stream->their_caps = gst_caps_fixate(stream->their_caps);
|
||||
|
||||
- stream_type = mf_media_type_from_caps(stream->their_caps);
|
||||
+ if (strcmp(gst_structure_get_name(gst_caps_get_structure(stream->their_caps, 0)), "video/x-raw") &&
|
||||
+ strcmp(gst_structure_get_name(gst_caps_get_structure(stream->their_caps, 0)), "audio/x-raw"))
|
||||
+ {
|
||||
+ GstCaps *compatible_caps = make_mf_compatible_caps(stream->their_caps);
|
||||
+ stream_type = mf_media_type_from_caps(compatible_caps);
|
||||
+ gst_caps_unref(compatible_caps);
|
||||
+ }
|
||||
+ else
|
||||
+ stream_type = mf_media_type_from_caps(stream->their_caps);
|
||||
+
|
||||
gst_caps_unref(stream->their_caps);
|
||||
if (!stream_type)
|
||||
{
|
||||
--
|
||||
2.28.0
|
||||
|
@ -1,499 +0,0 @@
|
||||
From dfb5190b00ce04f7ac0c811cb6350af37826015e Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Sergio=20G=C3=B3mez=20Del=20Real?=
|
||||
<sdelreal@codeweavers.com>
|
||||
Date: Wed, 1 Apr 2020 16:11:06 -0500
|
||||
Subject: [PATCH 05/54] mf/tests: Add tests for the topology loader.
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Signed-off-by: Sergio Gómez Del Real <sdelreal@codeweavers.com>
|
||||
---
|
||||
dlls/mf/tests/mf.c | 435 ++++++++++++++++++++++++++++++++++++++++++++-
|
||||
1 file changed, 433 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/dlls/mf/tests/mf.c b/dlls/mf/tests/mf.c
|
||||
index 9e190388ee..8691ef55c9 100644
|
||||
--- a/dlls/mf/tests/mf.c
|
||||
+++ b/dlls/mf/tests/mf.c
|
||||
@@ -1392,26 +1392,169 @@ static const IMFSampleGrabberSinkCallbackVtbl test_grabber_callback_vtbl =
|
||||
test_grabber_callback_OnShutdown,
|
||||
};
|
||||
|
||||
+static HRESULT WINAPI test_media_source_QueryInterface(IMFMediaSource *iface, REFIID riid, void **out)
|
||||
+{
|
||||
+ if (IsEqualIID(riid, &IID_IMFMediaSource) ||
|
||||
+ IsEqualIID(riid, &IID_IMFMediaEventGenerator) ||
|
||||
+ IsEqualIID(riid, &IID_IUnknown))
|
||||
+ {
|
||||
+ *out = iface;
|
||||
+ IUnknown_AddRef((IUnknown*)*out);
|
||||
+ return S_OK;
|
||||
+ }
|
||||
+
|
||||
+ *out = NULL;
|
||||
+ return E_NOINTERFACE;
|
||||
+}
|
||||
+
|
||||
+static ULONG WINAPI test_media_source_AddRef(IMFMediaSource *iface)
|
||||
+{
|
||||
+ return 2;
|
||||
+}
|
||||
+
|
||||
+static ULONG WINAPI test_media_source_Release(IMFMediaSource *iface)
|
||||
+{
|
||||
+ return 1;
|
||||
+}
|
||||
+
|
||||
+static HRESULT WINAPI test_media_source_GetEvent(IMFMediaSource *iface, DWORD flags, IMFMediaEvent **event)
|
||||
+{
|
||||
+ return E_NOTIMPL;
|
||||
+}
|
||||
+
|
||||
+static HRESULT WINAPI test_media_source_BeginGetEvent(IMFMediaSource *iface, IMFAsyncCallback *callback, IUnknown *state)
|
||||
+{
|
||||
+ return E_NOTIMPL;
|
||||
+}
|
||||
+
|
||||
+static HRESULT WINAPI test_media_source_EndGetEvent(IMFMediaSource *iface, IMFAsyncResult *result, IMFMediaEvent **event)
|
||||
+{
|
||||
+ return E_NOTIMPL;
|
||||
+}
|
||||
+
|
||||
+static HRESULT WINAPI test_media_source_QueueEvent(IMFMediaSource *iface, MediaEventType event_type, REFGUID ext_type,
|
||||
+ HRESULT hr, const PROPVARIANT *value)
|
||||
+{
|
||||
+ return E_NOTIMPL;
|
||||
+}
|
||||
+
|
||||
+static HRESULT WINAPI test_media_source_GetCharacteristics(IMFMediaSource *iface, DWORD *characteristics)
|
||||
+{
|
||||
+ return E_NOTIMPL;
|
||||
+}
|
||||
+
|
||||
+static HRESULT WINAPI test_media_source_CreatePresentationDescriptor(IMFMediaSource *iface, IMFPresentationDescriptor **descriptor)
|
||||
+{
|
||||
+ HRESULT hr;
|
||||
+
|
||||
+ IMFPresentationDescriptor *pd;
|
||||
+ IMFMediaType *mediatypes[3];
|
||||
+ IMFStreamDescriptor *sd[2];
|
||||
+
|
||||
+ if (FAILED(hr = MFCreateMediaType(&mediatypes[0])))
|
||||
+ return hr;
|
||||
+ if (FAILED(hr = IMFMediaType_SetGUID(mediatypes[0], &MF_MT_MAJOR_TYPE, &MFMediaType_Video)))
|
||||
+ return hr;
|
||||
+ if (FAILED(hr = IMFMediaType_SetGUID(mediatypes[0], &MF_MT_SUBTYPE, &MFVideoFormat_YUY2)))
|
||||
+ return hr;
|
||||
+ if (FAILED(hr = MFCreateMediaType(&mediatypes[1])))
|
||||
+ return hr;
|
||||
+ if (FAILED(hr = IMFMediaType_SetGUID(mediatypes[1], &MF_MT_MAJOR_TYPE, &MFMediaType_Audio)))
|
||||
+ return hr;
|
||||
+ if (FAILED(hr = IMFMediaType_SetGUID(mediatypes[1], &MF_MT_SUBTYPE, &MFAudioFormat_MP3)))
|
||||
+ return hr;
|
||||
+ if (FAILED(hr = IMFMediaType_SetUINT32(mediatypes[1], &MF_MT_AUDIO_SAMPLES_PER_SECOND, 32000)))
|
||||
+ return hr;
|
||||
+ if (FAILED(hr = IMFMediaType_SetUINT32(mediatypes[1], &MF_MT_AUDIO_NUM_CHANNELS, 2)))
|
||||
+ return hr;
|
||||
+ if (FAILED(hr = IMFMediaType_SetUINT32(mediatypes[1], &MF_MT_AUDIO_PREFER_WAVEFORMATEX, 1)))
|
||||
+ return hr;
|
||||
+ if (FAILED(hr = MFCreateMediaType(&mediatypes[2])))
|
||||
+ return hr;
|
||||
+ if (FAILED(hr = IMFMediaType_SetGUID(mediatypes[2], &MF_MT_MAJOR_TYPE, &MFMediaType_Audio)))
|
||||
+ return hr;
|
||||
+ if (FAILED(hr = IMFMediaType_SetGUID(mediatypes[2], &MF_MT_SUBTYPE, &MFAudioFormat_PCM)))
|
||||
+ return hr;
|
||||
+ if (FAILED(hr = MFCreateStreamDescriptor(0, 3, mediatypes, &sd[0])))
|
||||
+ return hr;
|
||||
+ if (FAILED(hr = MFCreateStreamDescriptor(1, 3, mediatypes, &sd[1])))
|
||||
+ return hr;
|
||||
+ if (FAILED(hr = MFCreatePresentationDescriptor(2, sd, &pd)))
|
||||
+ return hr;
|
||||
+ *descriptor = pd;
|
||||
+
|
||||
+ IMFMediaType_Release(mediatypes[0]);
|
||||
+ IMFMediaType_Release(mediatypes[1]);
|
||||
+ IMFMediaType_Release(mediatypes[2]);
|
||||
+ IMFStreamDescriptor_Release(sd[0]);
|
||||
+ IMFStreamDescriptor_Release(sd[1]);
|
||||
+
|
||||
+ return S_OK;
|
||||
+}
|
||||
+
|
||||
+static HRESULT WINAPI test_media_source_Start(IMFMediaSource *iface, IMFPresentationDescriptor *descriptor,
|
||||
+ const GUID *time_format, const PROPVARIANT *start_position)
|
||||
+{
|
||||
+ return E_NOTIMPL;
|
||||
+}
|
||||
+
|
||||
+static HRESULT WINAPI test_media_source_Stop(IMFMediaSource *iface)
|
||||
+{
|
||||
+ return E_NOTIMPL;
|
||||
+}
|
||||
+
|
||||
+static HRESULT WINAPI test_media_source_Pause(IMFMediaSource *iface)
|
||||
+{
|
||||
+ return E_NOTIMPL;
|
||||
+}
|
||||
+
|
||||
+static HRESULT WINAPI test_media_source_Shutdown(IMFMediaSource *iface)
|
||||
+{
|
||||
+ return S_OK;
|
||||
+}
|
||||
+
|
||||
+static const IMFMediaSourceVtbl test_media_source_vtbl =
|
||||
+{
|
||||
+ test_media_source_QueryInterface,
|
||||
+ test_media_source_AddRef,
|
||||
+ test_media_source_Release,
|
||||
+ test_media_source_GetEvent,
|
||||
+ test_media_source_BeginGetEvent,
|
||||
+ test_media_source_EndGetEvent,
|
||||
+ test_media_source_QueueEvent,
|
||||
+ test_media_source_GetCharacteristics,
|
||||
+ test_media_source_CreatePresentationDescriptor,
|
||||
+ test_media_source_Start,
|
||||
+ test_media_source_Stop,
|
||||
+ test_media_source_Pause,
|
||||
+ test_media_source_Shutdown,
|
||||
+};
|
||||
+
|
||||
static void test_topology_loader(void)
|
||||
{
|
||||
IMFSampleGrabberSinkCallback test_grabber_callback = { &test_grabber_callback_vtbl };
|
||||
+ IMFMediaSource test_media_source = { &test_media_source_vtbl };
|
||||
IMFTopology *topology, *topology2, *full_topology;
|
||||
IMFTopologyNode *src_node, *sink_node;
|
||||
+ IMFMediaType *media_type, *current_media_type;
|
||||
IMFPresentationDescriptor *pd;
|
||||
IMFSourceResolver *resolver;
|
||||
IMFActivate *sink_activate;
|
||||
IMFStreamSink *stream_sink;
|
||||
unsigned int count, value;
|
||||
- IMFMediaType *media_type;
|
||||
+ IMFMediaTypeHandler *mth;
|
||||
IMFStreamDescriptor *sd;
|
||||
+ UINT32 enum_src, method;
|
||||
MF_OBJECT_TYPE obj_type;
|
||||
IMFMediaSource *source;
|
||||
IMFTopoLoader *loader;
|
||||
IMFByteStream *stream;
|
||||
IMFAttributes *attr;
|
||||
IMFMediaSink *sink;
|
||||
+ WORD node_count;
|
||||
WCHAR *filename;
|
||||
BOOL selected;
|
||||
+ DWORD flags;
|
||||
HRESULT hr;
|
||||
GUID guid;
|
||||
|
||||
@@ -1527,6 +1670,9 @@ todo_wine
|
||||
ok(hr == S_OK, "Failed to resolve topology, hr %#x.\n", hr);
|
||||
ok(full_topology != topology, "Unexpected instance.\n");
|
||||
|
||||
+ IMFTopology_GetNodeCount(full_topology, &node_count);
|
||||
+ ok(node_count == 2, "Topology node count is %#x.\n", node_count);
|
||||
+
|
||||
hr = IMFTopology_GetCount(topology, &count);
|
||||
ok(hr == S_OK, "Failed to get attribute count, hr %#x.\n", hr);
|
||||
ok(count == 0, "Unexpected count %u.\n", count);
|
||||
@@ -1553,10 +1699,295 @@ todo_wine {
|
||||
|
||||
IMFTopology_Release(topology2);
|
||||
IMFTopology_Release(full_topology);
|
||||
+ IMFByteStream_Release(stream);
|
||||
+ IMFStreamDescriptor_Release(sd);
|
||||
+
|
||||
+ /* test with stream deselected */
|
||||
+ IMFPresentationDescriptor_GetStreamDescriptorCount(pd, &count);
|
||||
+ ok(count == 1, "Unexpected stream descriptor count.\n");
|
||||
+ hr = IMFPresentationDescriptor_DeselectStream(pd, 0);
|
||||
+ ok(hr == S_OK, "Failed to deselect stream, hr %#x.\n", hr);
|
||||
+ hr = IMFTopoLoader_Load(loader, topology, &full_topology, NULL);
|
||||
+ ok(hr == S_OK, "Failed to resolve topology, hr %#x.\n", hr);
|
||||
+ IMFTopologyNode_Release(src_node);
|
||||
+ hr = IMFTopology_GetNode(full_topology, 0, &src_node);
|
||||
+ ok(hr == S_OK, "Failed to get full topology source node, hr %#x.\n", hr);
|
||||
+ IMFPresentationDescriptor_Release(pd);
|
||||
+ hr = IMFTopologyNode_GetUnknown(src_node, &MF_TOPONODE_PRESENTATION_DESCRIPTOR, &IID_IMFPresentationDescriptor, (void **)&pd);
|
||||
+ ok(hr == S_OK, "Failed to get presentation descriptor, hr %#x.\n", hr);
|
||||
+ IMFStreamDescriptor_Release(sd);
|
||||
+ IMFPresentationDescriptor_GetStreamDescriptorByIndex(pd, 0, &selected, &sd);
|
||||
+ ok(hr == S_OK, "Failed to get stream descriptor, hr %#x.\n", hr);
|
||||
+ ok(!selected, "Stream should not be selected\n.");
|
||||
|
||||
+ IMFPresentationDescriptor_Release(pd);
|
||||
+ IMFTopologyNode_Release(src_node);
|
||||
+ IMFTopology_Release(full_topology);
|
||||
+ IMFTopology_Release(topology);
|
||||
IMFMediaSource_Release(source);
|
||||
IMFSourceResolver_Release(resolver);
|
||||
- IMFByteStream_Release(stream);
|
||||
+
|
||||
+ /* test source stream with various media types */
|
||||
+ /* first, test default behavior; MF_TOPOLOGY_ENUMERATE_SOURCE_TYPES not set */
|
||||
+ hr = MFCreateTopology(&topology);
|
||||
+ ok(hr == S_OK, "Failed to create topology, hr %#x.\n", hr);
|
||||
+
|
||||
+ hr = IMFMediaSource_CreatePresentationDescriptor(&test_media_source, &pd);
|
||||
+ ok(hr == S_OK, "Failed to create descriptor, hr %#x.\n", hr);
|
||||
+
|
||||
+ hr = IMFPresentationDescriptor_GetStreamDescriptorByIndex(pd, 0, &selected, &sd);
|
||||
+ ok(hr == S_OK, "Failed to get stream descriptor, hr %#x.\n", hr);
|
||||
+
|
||||
+ hr = IMFStreamDescriptor_GetMediaTypeHandler(sd, &mth);
|
||||
+ ok(hr == S_OK, "Failed to get media type handler, hr %#x.\n", hr);
|
||||
+ hr = IMFMediaTypeHandler_GetCurrentMediaType(mth, &media_type);
|
||||
+ ok(hr == MF_E_NOT_INITIALIZED, "Unexpected hr %#x.\n", hr);
|
||||
+
|
||||
+ hr = MFCreateTopologyNode(MF_TOPOLOGY_SOURCESTREAM_NODE, &src_node);
|
||||
+ ok(hr == S_OK, "Failed to create topology node, hr %#x.\n", hr);
|
||||
+
|
||||
+ hr = IMFTopologyNode_SetUnknown(src_node, &MF_TOPONODE_SOURCE, (IUnknown *)&test_media_source);
|
||||
+ ok(hr == S_OK, "Failed to set node source, hr %#x.\n", hr);
|
||||
+ hr = IMFTopologyNode_SetUnknown(src_node, &MF_TOPONODE_PRESENTATION_DESCRIPTOR, (IUnknown *)pd);
|
||||
+ ok(hr == S_OK, "Failed to set node pd, hr %#x.\n", hr);
|
||||
+ hr = IMFTopologyNode_SetUnknown(src_node, &MF_TOPONODE_STREAM_DESCRIPTOR, (IUnknown *)sd);
|
||||
+ ok(hr == S_OK, "Failed to set node sd, hr %#x.\n", hr);
|
||||
+
|
||||
+ hr = IMFTopology_AddNode(topology, src_node);
|
||||
+ ok(hr == S_OK, "Failed to add a node, hr %#x.\n", hr);
|
||||
+
|
||||
+ hr = MFCreateMediaType(&media_type);
|
||||
+ ok(hr == S_OK, "Failed to create media type, hr %#x.\n", hr);
|
||||
+
|
||||
+ hr = IMFMediaType_SetGUID(media_type, &MF_MT_MAJOR_TYPE, &MFMediaType_Audio);
|
||||
+ ok(hr == S_OK, "Failed to set attribute, hr %#x.\n", hr);
|
||||
+ hr = IMFMediaType_SetGUID(media_type, &MF_MT_SUBTYPE, &MFAudioFormat_PCM);
|
||||
+ ok(hr == S_OK, "Failed to set attribute, hr %#x.\n", hr);
|
||||
+
|
||||
+ hr = MFCreateSampleGrabberSinkActivate(media_type, &test_grabber_callback, &sink_activate);
|
||||
+ ok(hr == S_OK, "Failed to create grabber sink, hr %#x.\n", hr);
|
||||
+ IMFMediaType_Release(media_type);
|
||||
+
|
||||
+ hr = IMFActivate_ActivateObject(sink_activate, &IID_IMFMediaSink, (void **)&sink);
|
||||
+ ok(hr == S_OK, "Failed to activate, hr %#x.\n", hr);
|
||||
+
|
||||
+ hr = IMFMediaSink_GetStreamSinkByIndex(sink, 0, &stream_sink);
|
||||
+ ok(hr == S_OK, "Failed to get stream sink, hr %#x.\n", hr);
|
||||
+
|
||||
+ hr = MFCreateTopologyNode(MF_TOPOLOGY_OUTPUT_NODE, &sink_node);
|
||||
+ ok(hr == S_OK, "Failed to create output node, hr %#x.\n", hr);
|
||||
+
|
||||
+ hr = IMFTopologyNode_SetObject(sink_node, (IUnknown *)stream_sink);
|
||||
+ ok(hr == S_OK, "Failed to set object, hr %#x.\n", hr);
|
||||
+
|
||||
+ hr = IMFTopology_AddNode(topology, sink_node);
|
||||
+ ok(hr == S_OK, "Failed to add sink node, hr %#x.\n", hr);
|
||||
+
|
||||
+ hr = IMFTopologyNode_ConnectOutput(src_node, 0, sink_node, 0);
|
||||
+ ok(hr == S_OK, "Failed to connect nodes, hr %#x.\n", hr);
|
||||
+
|
||||
+ hr = IMFTopology_GetUINT32(topology, &MF_TOPOLOGY_ENUMERATE_SOURCE_TYPES, &enum_src);
|
||||
+ ok(hr == MF_E_ATTRIBUTENOTFOUND, "Attribute should not be set\n.");
|
||||
+ /* if no current media type set, loader uses first index exclusively */
|
||||
+ hr = IMFTopoLoader_Load(loader, topology, &full_topology, NULL);
|
||||
+todo_wine
|
||||
+ /* when major types differ, error is MF_E_TOPO_CODEC_NOT_FOUND */
|
||||
+ ok(hr == MF_E_TOPO_CODEC_NOT_FOUND, "Unexpected hr %#x.\n", hr);
|
||||
+
|
||||
+ hr = IMFMediaTypeHandler_GetMediaTypeByIndex(mth, 2, &media_type);
|
||||
+ ok(hr == S_OK, "Failed getting media type, hr %#x.\n", hr);
|
||||
+
|
||||
+ /* setting current media type overrides previous behavior; tries with it, and only with it */
|
||||
+ hr = IMFMediaTypeHandler_SetCurrentMediaType(mth, media_type);
|
||||
+ ok(hr == S_OK, "Failed setting current media type, hr %#x.\n", hr);
|
||||
+
|
||||
+ hr = IMFTopoLoader_Load(loader, topology, &full_topology, NULL);
|
||||
+ ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
|
||||
+
|
||||
+ hr = IMFTopology_GetNodeCount(full_topology, &node_count);
|
||||
+ ok(hr == S_OK, "Failed to get node count, hr %#x.\n", hr);
|
||||
+ ok(node_count == 2, "Unexpected node count.\n");
|
||||
+
|
||||
+ hr = IMFMediaTypeHandler_GetMediaTypeByIndex(mth, 1, &media_type);
|
||||
+ ok(hr == S_OK, "Failed getting media type, hr %#x.\n", hr);
|
||||
+
|
||||
+ hr = IMFMediaTypeHandler_SetCurrentMediaType(mth, media_type);
|
||||
+ ok(hr == S_OK, "Failed setting current media type, hr %#x.\n", hr);
|
||||
+
|
||||
+ hr = IMFTopoLoader_Load(loader, topology, &full_topology, NULL);
|
||||
+ ok(hr == S_OK, "Failed to resolve topology, hr %#x.\n", hr);
|
||||
+
|
||||
+ hr = IMFTopology_GetNodeCount(full_topology, &node_count);
|
||||
+ ok(hr == S_OK, "Failed to get node count, hr %#x.\n", hr);
|
||||
+todo_wine
|
||||
+ ok(node_count == 3, "Unexpected node count.\n");
|
||||
+
|
||||
+ IMFTopology_Release(full_topology);
|
||||
+
|
||||
+ /* now test with MF_TOPOLOGY_ENUMERATE_SOURCE_TYPES set on topology */
|
||||
+ hr = IMFTopology_SetUINT32(topology, &MF_TOPOLOGY_ENUMERATE_SOURCE_TYPES, 1);
|
||||
+ ok(hr == S_OK, "Failed setting attribute\n.");
|
||||
+ hr = IMFMediaTypeHandler_GetMediaTypeByIndex(mth, 2, &media_type);
|
||||
+ ok(hr == S_OK, "Failed getting media type, hr %#x.\n", hr);
|
||||
+
|
||||
+ /* first, if MF_CONNECT_RESOLVE_INDEPENDENT_OUTPUTTYPES is not set on source */
|
||||
+ IMFTopologyNode_GetUINT32(src_node, &MF_TOPONODE_CONNECT_METHOD, &method);
|
||||
+ ok(hr == S_OK, "Attribute should be set\n.");
|
||||
+ IMFTopologyNode_SetUINT32(src_node, &MF_TOPONODE_CONNECT_METHOD, method & ~MF_CONNECT_RESOLVE_INDEPENDENT_OUTPUTTYPES);
|
||||
+ ok(hr == S_OK, "Failed setting attribute %#x\n.", hr);
|
||||
+
|
||||
+ hr = IMFTopoLoader_Load(loader, topology, &full_topology, NULL);
|
||||
+ ok(hr == S_OK, "Failed to resolve topology, hr %#x.\n", hr);
|
||||
+
|
||||
+ hr = IMFTopology_GetNodeCount(full_topology, &node_count);
|
||||
+ ok(hr == S_OK, "Failed to get node count, hr %#x.\n", hr);
|
||||
+ ok(node_count == 2, "Unexpected node count.\n");
|
||||
+ IMFTopologyNode_Release(src_node);
|
||||
+ hr = IMFTopology_GetNode(full_topology, 0, &src_node);
|
||||
+ ok(hr == S_OK, "Failed to get node, hr %#x.\n", hr);
|
||||
+ IMFStreamDescriptor_Release(sd);
|
||||
+ hr = IMFTopologyNode_GetUnknown(src_node, &MF_TOPONODE_STREAM_DESCRIPTOR, &IID_IMFStreamDescriptor, (void **)&sd);
|
||||
+ ok(hr == S_OK, "Failed to get stream descriptor, hr %#x.\n", hr);
|
||||
+ IMFMediaTypeHandler_Release(mth);
|
||||
+ hr = IMFStreamDescriptor_GetMediaTypeHandler(sd, &mth);
|
||||
+ ok(hr == S_OK, "Failed to get media type handler, hr %#x.\n", hr);
|
||||
+ hr = IMFMediaTypeHandler_GetCurrentMediaType(mth, ¤t_media_type);
|
||||
+ ok(hr == S_OK, "Failed to get current media type, hr %#x.\n", hr);
|
||||
+ hr = IMFMediaType_IsEqual(current_media_type, media_type, &flags);
|
||||
+todo_wine {
|
||||
+ ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
|
||||
+ ok(flags & MF_MEDIATYPE_EQUAL_FORMAT_DATA, "Types should be equal.\n");
|
||||
+}
|
||||
+
|
||||
+ IMFMediaType_Release(media_type);
|
||||
+ IMFMediaType_Release(current_media_type);
|
||||
+ IMFMediaTypeHandler_Release(mth);
|
||||
+ IMFStreamSink_Release(stream_sink);
|
||||
+ IMFMediaSink_Release(sink);
|
||||
+ IMFActivate_Release(sink_activate);
|
||||
+ IMFStreamDescriptor_Release(sd);
|
||||
+
|
||||
+ /* add second branch with a valid first branch */
|
||||
+ hr = IMFTopology_SetUINT32(topology, &MF_TOPOLOGY_ENUMERATE_SOURCE_TYPES, 0);
|
||||
+ ok(hr == S_OK, "Failed setting attribute\n.");
|
||||
+ IMFTopologyNode_Release(src_node);
|
||||
+ hr = IMFTopology_GetNode(topology, 0, &src_node);
|
||||
+ ok(hr == S_OK, "Failed to get node, hr %#x.\n", hr);
|
||||
+ hr = IMFTopologyNode_GetUnknown(src_node, &MF_TOPONODE_STREAM_DESCRIPTOR, &IID_IMFStreamDescriptor, (void **)&sd);
|
||||
+ ok(hr == S_OK, "Failed to get stream descriptor, hr %#x.\n", hr);
|
||||
+ hr = IMFStreamDescriptor_GetMediaTypeHandler(sd, &mth);
|
||||
+ ok(hr == S_OK, "Failed to get media type handler, hr %#x.\n", hr);
|
||||
+ hr = IMFMediaTypeHandler_GetMediaTypeByIndex(mth, 1, &media_type);
|
||||
+ ok(hr == S_OK, "Failed getting media type, hr %#x.\n", hr);
|
||||
+ hr = IMFMediaTypeHandler_SetCurrentMediaType(mth, media_type);
|
||||
+ ok(hr == S_OK, "Failed setting current media type, hr %#x.\n", hr);
|
||||
+
|
||||
+ hr = IMFTopoLoader_Load(loader, topology, &full_topology, NULL);
|
||||
+ ok(hr == S_OK, "Failed to resolve topology, hr %#x.\n", hr);
|
||||
+
|
||||
+ IMFTopology_Release(full_topology);
|
||||
+
|
||||
+ IMFStreamDescriptor_Release(sd);
|
||||
+ hr = IMFPresentationDescriptor_GetStreamDescriptorByIndex(pd, 1, &selected, &sd);
|
||||
+ ok(hr == S_OK, "Failed to get stream descriptor, hr %#x.\n", hr);
|
||||
+
|
||||
+ hr = IMFStreamDescriptor_GetMediaTypeHandler(sd, &mth);
|
||||
+ ok(hr == S_OK, "Failed to get media type handler, hr %#x.\n", hr);
|
||||
+ hr = IMFMediaTypeHandler_GetCurrentMediaType(mth, &media_type);
|
||||
+ ok(hr == MF_E_NOT_INITIALIZED, "Unexpected hr %#x.\n", hr);
|
||||
+
|
||||
+ IMFTopologyNode_Release(src_node);
|
||||
+ hr = MFCreateTopologyNode(MF_TOPOLOGY_SOURCESTREAM_NODE, &src_node);
|
||||
+ ok(hr == S_OK, "Failed to create topology node, hr %#x.\n", hr);
|
||||
+
|
||||
+ hr = IMFTopologyNode_SetUnknown(src_node, &MF_TOPONODE_SOURCE, (IUnknown *)&test_media_source);
|
||||
+ ok(hr == S_OK, "Failed to set node source, hr %#x.\n", hr);
|
||||
+ hr = IMFTopologyNode_SetUnknown(src_node, &MF_TOPONODE_PRESENTATION_DESCRIPTOR, (IUnknown *)pd);
|
||||
+ ok(hr == S_OK, "Failed to set node pd, hr %#x.\n", hr);
|
||||
+ hr = IMFTopologyNode_SetUnknown(src_node, &MF_TOPONODE_STREAM_DESCRIPTOR, (IUnknown *)sd);
|
||||
+ ok(hr == S_OK, "Failed to set node sd, hr %#x.\n", hr);
|
||||
+
|
||||
+ hr = IMFTopology_AddNode(topology, src_node);
|
||||
+ ok(hr == S_OK, "Failed to add a node, hr %#x.\n", hr);
|
||||
+
|
||||
+ hr = MFCreateMediaType(&media_type);
|
||||
+ ok(hr == S_OK, "Failed to create media type, hr %#x.\n", hr);
|
||||
+
|
||||
+ hr = IMFMediaType_SetGUID(media_type, &MF_MT_MAJOR_TYPE, &MFMediaType_Audio);
|
||||
+ ok(hr == S_OK, "Failed to set attribute, hr %#x.\n", hr);
|
||||
+ hr = IMFMediaType_SetGUID(media_type, &MF_MT_SUBTYPE, &MFAudioFormat_PCM);
|
||||
+ ok(hr == S_OK, "Failed to set attribute, hr %#x.\n", hr);
|
||||
+
|
||||
+ hr = MFCreateSampleGrabberSinkActivate(media_type, &test_grabber_callback, &sink_activate);
|
||||
+ ok(hr == S_OK, "Failed to create grabber sink, hr %#x.\n", hr);
|
||||
+ IMFMediaType_Release(media_type);
|
||||
+
|
||||
+ hr = IMFActivate_ActivateObject(sink_activate, &IID_IMFMediaSink, (void **)&sink);
|
||||
+ ok(hr == S_OK, "Failed to activate, hr %#x.\n", hr);
|
||||
+
|
||||
+ hr = IMFMediaSink_GetStreamSinkByIndex(sink, 0, &stream_sink);
|
||||
+ ok(hr == S_OK, "Failed to get stream sink, hr %#x.\n", hr);
|
||||
+
|
||||
+ hr = MFCreateTopologyNode(MF_TOPOLOGY_OUTPUT_NODE, &sink_node);
|
||||
+ ok(hr == S_OK, "Failed to create output node, hr %#x.\n", hr);
|
||||
+
|
||||
+ hr = IMFTopologyNode_SetObject(sink_node, (IUnknown *)stream_sink);
|
||||
+ ok(hr == S_OK, "Failed to set object, hr %#x.\n", hr);
|
||||
+
|
||||
+ hr = IMFTopology_AddNode(topology, sink_node);
|
||||
+ ok(hr == S_OK, "Failed to add sink node, hr %#x.\n", hr);
|
||||
+
|
||||
+ hr = IMFTopology_GetNodeCount(topology, &node_count);
|
||||
+ ok(hr == S_OK, "Failed to get node count, hr %#x.\n", hr);
|
||||
+ ok(node_count == 4, "Unexpected node count.\n");
|
||||
+
|
||||
+ hr = IMFTopoLoader_Load(loader, topology, &full_topology, NULL);
|
||||
+ ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
|
||||
+
|
||||
+ /* unconnected nodes in partial topology are discarded */
|
||||
+ hr = IMFTopology_GetNodeCount(full_topology, &node_count);
|
||||
+ ok(hr == S_OK, "Failed to get node count, hr %#x.\n", hr);
|
||||
+todo_wine
|
||||
+ ok(node_count == 3, "Unexpected node count %d.\n", node_count);
|
||||
+
|
||||
+ IMFTopology_Release(full_topology);
|
||||
+
|
||||
+ /* connect nodes for second branch */
|
||||
+ hr = IMFTopologyNode_ConnectOutput(src_node, 0, sink_node, 0);
|
||||
+ ok(hr == S_OK, "Failed to connect nodes, hr %#x.\n", hr);
|
||||
+
|
||||
+ /* all branches must have valid media types */
|
||||
+ hr = IMFTopoLoader_Load(loader, topology, &full_topology, NULL);
|
||||
+todo_wine
|
||||
+ ok(hr == MF_E_TOPO_CODEC_NOT_FOUND, "Unexpected hr %#x.\n", hr);
|
||||
+
|
||||
+ /* set valid media type for second branch */
|
||||
+ hr = IMFMediaTypeHandler_GetMediaTypeByIndex(mth, 1, &media_type);
|
||||
+ ok(hr == S_OK, "Failed getting media type, hr %#x.\n", hr);
|
||||
+
|
||||
+ hr = IMFMediaTypeHandler_SetCurrentMediaType(mth, media_type);
|
||||
+ ok(hr == S_OK, "Failed setting current media type, hr %#x.\n", hr);
|
||||
+
|
||||
+ hr = IMFTopoLoader_Load(loader, topology, &full_topology, NULL);
|
||||
+ ok(hr == S_OK, "Failed to resolve topology, hr %#x.\n", hr);
|
||||
+
|
||||
+ hr = IMFTopology_GetNodeCount(full_topology, &node_count);
|
||||
+ ok(hr == S_OK, "Failed to get node count, hr %#x.\n", hr);
|
||||
+todo_wine
|
||||
+ ok(node_count == 6, "Unexpected node count %d.\n", node_count);
|
||||
+
|
||||
+ IMFTopology_Release(full_topology);
|
||||
+ IMFMediaType_Release(media_type);
|
||||
+ IMFTopologyNode_Release(src_node);
|
||||
+ IMFTopologyNode_Release(sink_node);
|
||||
+ IMFMediaTypeHandler_Release(mth);
|
||||
+ IMFStreamSink_Release(stream_sink);
|
||||
+ IMFMediaSink_Release(sink);
|
||||
+ IMFActivate_Release(sink_activate);
|
||||
+ IMFStreamDescriptor_Release(sd);
|
||||
+
|
||||
+ IMFPresentationDescriptor_Release(pd);
|
||||
+ IMFTopology_Release(topology);
|
||||
IMFTopoLoader_Release(loader);
|
||||
|
||||
hr = MFShutdown();
|
||||
--
|
||||
2.28.0
|
||||
|
@ -0,0 +1,164 @@
|
||||
From 862d76c09ef0005d40e63b271a03c98874f78828 Mon Sep 17 00:00:00 2001
|
||||
From: Derek Lesho <dlesho@codeweavers.com>
|
||||
Date: Tue, 25 Aug 2020 17:35:49 -0500
|
||||
Subject: [PATCH 05/52] winegstreamer: Insert videoconvert into decoded-video
|
||||
streams.
|
||||
|
||||
Signed-off-by: Derek Lesho <dlesho@codeweavers.com>
|
||||
---
|
||||
dlls/winegstreamer/media_source.c | 104 ++++++++++++++++++++++++++----
|
||||
1 file changed, 91 insertions(+), 13 deletions(-)
|
||||
|
||||
diff --git a/dlls/winegstreamer/media_source.c b/dlls/winegstreamer/media_source.c
|
||||
index f1e8c5799f7..209753608b6 100644
|
||||
--- a/dlls/winegstreamer/media_source.c
|
||||
+++ b/dlls/winegstreamer/media_source.c
|
||||
@@ -459,8 +459,22 @@ static HRESULT media_stream_align_with_mf(struct media_stream *stream)
|
||||
g_free(source_caps_str);
|
||||
}
|
||||
|
||||
- if (!strcmp(gst_structure_get_name(gst_caps_get_structure(source_caps, 0)), "video/x-raw") ||
|
||||
- !strcmp(gst_structure_get_name(gst_caps_get_structure(source_caps, 0)), "audio/x-raw"))
|
||||
+ if (!strcmp(gst_structure_get_name(gst_caps_get_structure(source_caps, 0)), "video/x-raw"))
|
||||
+ {
|
||||
+ GstElement *videoconvert = gst_element_factory_make("videoconvert", NULL);
|
||||
+
|
||||
+ gst_bin_add(GST_BIN(stream->parent_source->container), videoconvert);
|
||||
+
|
||||
+ stream->my_sink = gst_element_get_static_pad(videoconvert, "sink");
|
||||
+
|
||||
+ assert(gst_pad_link(stream->their_src, stream->my_sink) == GST_PAD_LINK_OK);
|
||||
+ assert(gst_element_link(videoconvert, stream->appsink));
|
||||
+
|
||||
+ gst_element_sync_state_with_parent(videoconvert);
|
||||
+
|
||||
+ g_object_set(stream->appsink, "caps", source_caps, NULL);
|
||||
+ }
|
||||
+ else if(!strcmp(gst_structure_get_name(gst_caps_get_structure(source_caps, 0)), "audio/x-raw"))
|
||||
{
|
||||
stream->my_sink = gst_element_get_static_pad(stream->appsink, "sink");
|
||||
g_object_set(stream->appsink, "caps", source_caps, NULL);
|
||||
@@ -605,45 +619,109 @@ static HRESULT media_stream_init_desc(struct media_stream *stream)
|
||||
{
|
||||
HRESULT hr;
|
||||
IMFMediaTypeHandler *type_handler;
|
||||
+ IMFMediaType **stream_types = NULL;
|
||||
IMFMediaType *stream_type = NULL;
|
||||
+ DWORD type_count = 0;
|
||||
+ unsigned int i;
|
||||
|
||||
stream->their_caps = gst_caps_fixate(stream->their_caps);
|
||||
|
||||
- if (strcmp(gst_structure_get_name(gst_caps_get_structure(stream->their_caps, 0)), "video/x-raw") &&
|
||||
- strcmp(gst_structure_get_name(gst_caps_get_structure(stream->their_caps, 0)), "audio/x-raw"))
|
||||
+ if (!strcmp(gst_structure_get_name(gst_caps_get_structure(stream->their_caps, 0)), "video/x-raw"))
|
||||
{
|
||||
- GstCaps *compatible_caps = make_mf_compatible_caps(stream->their_caps);
|
||||
- stream_type = mf_media_type_from_caps(compatible_caps);
|
||||
- gst_caps_unref(compatible_caps);
|
||||
+ GstElementFactory *videoconvert_factory = gst_element_factory_find("videoconvert");
|
||||
+ /* output every format supported by videoconvert */
|
||||
+ const GList *template_list = gst_element_factory_get_static_pad_templates(videoconvert_factory);
|
||||
+ for (;template_list; template_list = template_list->next)
|
||||
+ {
|
||||
+ GstStaticPadTemplate *template = (GstStaticPadTemplate *)template_list->data;
|
||||
+ GstCaps *src_caps;
|
||||
+ GValueArray *formats;
|
||||
+ if (template->direction != GST_PAD_SRC)
|
||||
+ continue;
|
||||
+ src_caps = gst_static_pad_template_get_caps(template);
|
||||
+ gst_structure_get_list(gst_caps_get_structure(src_caps, 0), "format", &formats);
|
||||
+ type_count = formats->n_values;
|
||||
+ stream_types = heap_alloc( sizeof(IMFMediaType*) * type_count );
|
||||
+ for (i = 0; i < formats->n_values; i++)
|
||||
+ {
|
||||
+ GValue *format = g_value_array_get_nth(formats, i);
|
||||
+ GstCaps *modified_caps = gst_caps_copy(stream->their_caps);
|
||||
+ gst_caps_set_value(modified_caps, "format", format);
|
||||
+ stream_types[i] = mf_media_type_from_caps(modified_caps);
|
||||
+ gst_caps_unref(modified_caps);
|
||||
+ if (!stream_types[i])
|
||||
+ {
|
||||
+ i--;
|
||||
+ type_count--;
|
||||
+ }
|
||||
+ }
|
||||
+ g_value_array_free(formats);
|
||||
+ gst_caps_unref(src_caps);
|
||||
+ break;
|
||||
+ }
|
||||
}
|
||||
- else
|
||||
+ else if (!strcmp(gst_structure_get_name(gst_caps_get_structure(stream->their_caps, 0)), "audio/x-raw"))
|
||||
+ {
|
||||
stream_type = mf_media_type_from_caps(stream->their_caps);
|
||||
+ if (stream_type)
|
||||
+ {
|
||||
+ stream_types = &stream_type;
|
||||
+ type_count = 1;
|
||||
+ }
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ GstCaps *compatible_caps = make_mf_compatible_caps(stream->their_caps);
|
||||
+ if (compatible_caps)
|
||||
+ {
|
||||
+ stream_type = mf_media_type_from_caps(compatible_caps);
|
||||
+ gst_caps_unref(compatible_caps);
|
||||
+ if (stream_type)
|
||||
+ {
|
||||
+ stream_types = &stream_type;
|
||||
+ type_count = 1;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
|
||||
gst_caps_unref(stream->their_caps);
|
||||
- if (!stream_type)
|
||||
+
|
||||
+ if (!type_count)
|
||||
{
|
||||
+ ERR("Failed to establish an IMFMediaType from any of the possible stream caps!\n");
|
||||
hr = E_FAIL;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
- if (FAILED(hr = MFCreateStreamDescriptor(stream->stream_id, 1, &stream_type, &stream->descriptor)))
|
||||
+ if (FAILED(hr = MFCreateStreamDescriptor(stream->stream_id, type_count, stream_types, &stream->descriptor)))
|
||||
goto fail;
|
||||
|
||||
if (FAILED(hr = IMFStreamDescriptor_GetMediaTypeHandler(stream->descriptor, &type_handler)))
|
||||
goto fail;
|
||||
|
||||
- if (FAILED(hr = IMFMediaTypeHandler_SetCurrentMediaType(type_handler, stream_type)))
|
||||
+ if (FAILED(hr = IMFMediaTypeHandler_SetCurrentMediaType(type_handler, stream_types[0])))
|
||||
goto fail;
|
||||
|
||||
- IMFMediaTypeHandler_Release(type_handler);
|
||||
-
|
||||
stream->state = STREAM_INACTIVE;
|
||||
|
||||
+ IMFMediaTypeHandler_Release(type_handler);
|
||||
+ for (i = 0; i < type_count; i++)
|
||||
+ IMFMediaType_Release(stream_types[i]);
|
||||
+ if (stream_types != &stream_type)
|
||||
+ heap_free(stream_types);
|
||||
+
|
||||
return S_OK;
|
||||
fail:
|
||||
ERR("media stream initialization failed with %x\n", hr);
|
||||
if (type_handler)
|
||||
IMFMediaTypeHandler_Release(type_handler);
|
||||
+ if (stream_types)
|
||||
+ {
|
||||
+ for (i = 0; i < type_count; i++)
|
||||
+ IMFMediaType_Release(stream_types[i]);
|
||||
+ if (stream_types != &stream_type)
|
||||
+ heap_free(stream_types);
|
||||
+ }
|
||||
return hr;
|
||||
}
|
||||
|
||||
--
|
||||
2.28.0
|
||||
|
@ -0,0 +1,39 @@
|
||||
From 35f58b2470a342db3fe665549ac1983b4877157a Mon Sep 17 00:00:00 2001
|
||||
From: Derek Lesho <dlesho@codeweavers.com>
|
||||
Date: Tue, 25 Aug 2020 17:37:28 -0500
|
||||
Subject: [PATCH 06/52] winegstreamer: Insert audioconvert into decoded audio
|
||||
streams.
|
||||
|
||||
Signed-off-by: Derek Lesho <dlesho@codeweavers.com>
|
||||
---
|
||||
dlls/winegstreamer/media_source.c | 13 +++++++++++--
|
||||
1 file changed, 11 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/dlls/winegstreamer/media_source.c b/dlls/winegstreamer/media_source.c
|
||||
index 209753608b6..66cfdbdc0fd 100644
|
||||
--- a/dlls/winegstreamer/media_source.c
|
||||
+++ b/dlls/winegstreamer/media_source.c
|
||||
@@ -476,9 +476,18 @@ static HRESULT media_stream_align_with_mf(struct media_stream *stream)
|
||||
}
|
||||
else if(!strcmp(gst_structure_get_name(gst_caps_get_structure(source_caps, 0)), "audio/x-raw"))
|
||||
{
|
||||
- stream->my_sink = gst_element_get_static_pad(stream->appsink, "sink");
|
||||
- g_object_set(stream->appsink, "caps", source_caps, NULL);
|
||||
+ GstElement *audioconvert = gst_element_factory_make("audioconvert", NULL);
|
||||
+
|
||||
+ gst_bin_add(GST_BIN(stream->parent_source->container), audioconvert);
|
||||
+
|
||||
+ stream->my_sink = gst_element_get_static_pad(audioconvert, "sink");
|
||||
+
|
||||
assert(gst_pad_link(stream->their_src, stream->my_sink) == GST_PAD_LINK_OK);
|
||||
+ assert(gst_element_link(audioconvert, stream->appsink));
|
||||
+
|
||||
+ gst_element_sync_state_with_parent(audioconvert);
|
||||
+
|
||||
+ g_object_set(stream->appsink, "caps", source_caps, NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
--
|
||||
2.28.0
|
||||
|
@ -1,15 +1,15 @@
|
||||
From 483ebc1d94c11b675fa17d22c7b5fe04d3d3381f Mon Sep 17 00:00:00 2001
|
||||
From 0cb401346e8c106fad5cf1cd4d9364e7508d282b Mon Sep 17 00:00:00 2001
|
||||
From: Derek Lesho <dlesho@codeweavers.com>
|
||||
Date: Tue, 24 Mar 2020 16:00:26 -0500
|
||||
Subject: [PATCH] winegstreamer: Translate H.264 caps to attributes.
|
||||
Subject: [PATCH 07/52] winegstreamer: Translate H.264 caps to attributes.
|
||||
|
||||
Signed-off-by: Derek Lesho <dlesho@codeweavers.com>
|
||||
---
|
||||
dlls/winegstreamer/mfplat.c | 68 +++++++++++++++++++++++++++++++++++++
|
||||
1 file changed, 68 insertions(+)
|
||||
dlls/winegstreamer/mfplat.c | 67 +++++++++++++++++++++++++++++++++++++
|
||||
1 file changed, 67 insertions(+)
|
||||
|
||||
diff --git a/dlls/winegstreamer/mfplat.c b/dlls/winegstreamer/mfplat.c
|
||||
index 90eb583c4a..e0ef5e16db 100644
|
||||
index 3667bc3cc38..77a2dad093a 100644
|
||||
--- a/dlls/winegstreamer/mfplat.c
|
||||
+++ b/dlls/winegstreamer/mfplat.c
|
||||
@@ -26,6 +26,7 @@
|
||||
@ -20,14 +20,13 @@ index 90eb583c4a..e0ef5e16db 100644
|
||||
|
||||
#include "wine/debug.h"
|
||||
#include "wine/heap.h"
|
||||
@@ -525,6 +526,73 @@ static IMFMediaType* transform_to_media_type(GstCaps *caps)
|
||||
@@ -519,6 +520,72 @@ static IMFMediaType* transform_to_media_type(GstCaps *caps)
|
||||
FIXME("Unrecognized format.\n");
|
||||
}
|
||||
}
|
||||
+ else if (!(strcmp(mime_type, "video/x-h264")))
|
||||
+ {
|
||||
+ const char *profile, *level;
|
||||
+ unsigned int i;
|
||||
+
|
||||
+ IMFMediaType_SetGUID(media_type, &MF_MT_SUBTYPE, &MFVideoFormat_H264);
|
||||
+ IMFMediaType_SetUINT32(media_type, &MF_MT_COMPRESSED, TRUE);
|
||||
@ -85,15 +84,15 @@ index 90eb583c4a..e0ef5e16db 100644
|
||||
+ }
|
||||
+ gst_caps_set_simple(caps, "stream-format", G_TYPE_STRING, "byte-stream", NULL);
|
||||
+ gst_caps_set_simple(caps, "alignment", G_TYPE_STRING, "au", NULL);
|
||||
+ for (i = 0; i < gst_caps_get_size(caps); i++)
|
||||
+ for (unsigned int i = 0; i < gst_caps_get_size(caps); i++)
|
||||
+ {
|
||||
+ GstStructure *structure = gst_caps_get_structure (caps, i);
|
||||
+ gst_structure_remove_field(structure, "codec_data");
|
||||
+ }
|
||||
+ }
|
||||
else
|
||||
{
|
||||
FIXME("Unrecognized video format %s\n", mime_type);
|
||||
}
|
||||
--
|
||||
2.28.0
|
||||
|
@ -1,7 +1,7 @@
|
||||
From 3c23e1570ad895c52069c895a3e50353730d20c1 Mon Sep 17 00:00:00 2001
|
||||
From 966b172363a8a3e22f9f5585cd41590f6c799b36 Mon Sep 17 00:00:00 2001
|
||||
From: Derek Lesho <dlesho@codeweavers.com>
|
||||
Date: Tue, 24 Mar 2020 16:01:20 -0500
|
||||
Subject: [PATCH 14/54] winegstreamer: Translate WMV caps to attributes.
|
||||
Subject: [PATCH 08/52] winegstreamer: Translate WMV caps to attributes.
|
||||
|
||||
Signed-off-by: Derek Lesho <dlesho@codeweavers.com>
|
||||
---
|
||||
@ -9,10 +9,10 @@ Signed-off-by: Derek Lesho <dlesho@codeweavers.com>
|
||||
1 file changed, 51 insertions(+)
|
||||
|
||||
diff --git a/dlls/winegstreamer/mfplat.c b/dlls/winegstreamer/mfplat.c
|
||||
index 1b37e1cc90..96195c887c 100644
|
||||
index 77a2dad093a..3963d97041d 100644
|
||||
--- a/dlls/winegstreamer/mfplat.c
|
||||
+++ b/dlls/winegstreamer/mfplat.c
|
||||
@@ -463,6 +463,24 @@ uncompressed_formats[] =
|
||||
@@ -457,6 +457,24 @@ uncompressed_formats[] =
|
||||
{&MFVideoFormat_RGB555, GST_VIDEO_FORMAT_BGR15},
|
||||
};
|
||||
|
||||
@ -37,7 +37,7 @@ index 1b37e1cc90..96195c887c 100644
|
||||
/* caps will be modified to represent the exact type needed for the format */
|
||||
static IMFMediaType* transform_to_media_type(GstCaps *caps)
|
||||
{
|
||||
@@ -592,6 +610,39 @@ static IMFMediaType* transform_to_media_type(GstCaps *caps)
|
||||
@@ -586,6 +604,39 @@ static IMFMediaType* transform_to_media_type(GstCaps *caps)
|
||||
gst_structure_remove_field(structure, "codec_data");
|
||||
}
|
||||
}
|
||||
@ -75,8 +75,8 @@ index 1b37e1cc90..96195c887c 100644
|
||||
+ codec_data_to_user_data(info, media_type);
|
||||
+ }
|
||||
else
|
||||
{
|
||||
FIXME("Unrecognized video format %s\n", mime_type);
|
||||
}
|
||||
--
|
||||
2.28.0
|
||||
|
@ -1,18 +1,18 @@
|
||||
From 13019300d005d7bcea386435894841a7154231e9 Mon Sep 17 00:00:00 2001
|
||||
From 8cf90bd8896f33646211c5ca6b2b18930789a2b2 Mon Sep 17 00:00:00 2001
|
||||
From: Derek Lesho <dlesho@codeweavers.com>
|
||||
Date: Tue, 24 Mar 2020 16:02:27 -0500
|
||||
Subject: [PATCH 15/54] winegstreamer: Translate AAC caps to attributes.
|
||||
Subject: [PATCH 09/52] winegstreamer: Translate AAC caps to attributes.
|
||||
|
||||
Signed-off-by: Derek Lesho <dlesho@codeweavers.com>
|
||||
---
|
||||
dlls/winegstreamer/mfplat.c | 107 ++++++++++++++++++++++++++++++++++++
|
||||
1 file changed, 107 insertions(+)
|
||||
dlls/winegstreamer/mfplat.c | 108 ++++++++++++++++++++++++++++++++++++
|
||||
1 file changed, 108 insertions(+)
|
||||
|
||||
diff --git a/dlls/winegstreamer/mfplat.c b/dlls/winegstreamer/mfplat.c
|
||||
index 96195c887c..ecb5de8b88 100644
|
||||
index 3963d97041d..4cff74f2d41 100644
|
||||
--- a/dlls/winegstreamer/mfplat.c
|
||||
+++ b/dlls/winegstreamer/mfplat.c
|
||||
@@ -463,6 +463,15 @@ uncompressed_formats[] =
|
||||
@@ -457,6 +457,15 @@ uncompressed_formats[] =
|
||||
{&MFVideoFormat_RGB555, GST_VIDEO_FORMAT_BGR15},
|
||||
};
|
||||
|
||||
@ -28,7 +28,7 @@ index 96195c887c..ecb5de8b88 100644
|
||||
static void codec_data_to_user_data(GstStructure *structure, IMFMediaType *type)
|
||||
{
|
||||
const GValue *codec_data;
|
||||
@@ -708,6 +717,104 @@ static IMFMediaType* transform_to_media_type(GstCaps *caps)
|
||||
@@ -710,6 +719,105 @@ static IMFMediaType* transform_to_media_type(GstCaps *caps)
|
||||
ERR("Failed to get audio format\n");
|
||||
}
|
||||
}
|
||||
@ -52,6 +52,7 @@ index 96195c887c..ecb5de8b88 100644
|
||||
+ struct aac_user_data *user_data = NULL;
|
||||
+
|
||||
+ IMFMediaType_SetGUID(media_type, &MF_MT_SUBTYPE, &MFAudioFormat_AAC);
|
||||
+ IMFMediaType_SetUINT32(media_type, &MF_MT_AUDIO_BITS_PER_SAMPLE, 16);
|
||||
+
|
||||
+ codec_data = gst_structure_get_value(info, "codec_data");
|
||||
+ if (codec_data)
|
||||
@ -131,8 +132,8 @@ index 96195c887c..ecb5de8b88 100644
|
||||
+ }
|
||||
+ }
|
||||
else
|
||||
{
|
||||
FIXME("Unrecognized audio format %s\n", mime_type);
|
||||
}
|
||||
--
|
||||
2.28.0
|
||||
|
@ -1,221 +0,0 @@
|
||||
From 42170f6bd111e333694f4122e38944c5f87ac1f2 Mon Sep 17 00:00:00 2001
|
||||
From: Derek Lesho <dlesho@codeweavers.com>
|
||||
Date: Tue, 31 Mar 2020 13:34:57 -0500
|
||||
Subject: [PATCH 10/54] winegstreamer: Find an appropriate demuxer for the
|
||||
source.
|
||||
|
||||
We can add a path later which uses decodebin as the demuxer, for use with formats not supported on windows. (like Theora)
|
||||
|
||||
Signed-off-by: Derek Lesho <dlesho@codeweavers.com>
|
||||
---
|
||||
dlls/winegstreamer/gst_cbs.c | 15 ++++-
|
||||
dlls/winegstreamer/gst_cbs.h | 2 +
|
||||
dlls/winegstreamer/media_source.c | 99 ++++++++++++++++++++++++++++++-
|
||||
3 files changed, 114 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/dlls/winegstreamer/gst_cbs.c b/dlls/winegstreamer/gst_cbs.c
|
||||
index dfe33dd627..cf49745f1d 100644
|
||||
--- a/dlls/winegstreamer/gst_cbs.c
|
||||
+++ b/dlls/winegstreamer/gst_cbs.c
|
||||
@@ -358,4 +358,17 @@ gboolean process_bytestream_pad_event_wrapper(GstPad *pad, GstObject *parent, Gs
|
||||
call_cb(&cbdata);
|
||||
|
||||
return cbdata.u.event_src_data.ret;
|
||||
-}
|
||||
\ No newline at end of file
|
||||
+}
|
||||
+
|
||||
+GstBusSyncReply watch_source_bus_wrapper(GstBus *bus, GstMessage *message, gpointer user)
|
||||
+{
|
||||
+ struct cb_data cbdata = { WATCH_SOURCE_BUS };
|
||||
+
|
||||
+ 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;
|
||||
+}
|
||||
diff --git a/dlls/winegstreamer/gst_cbs.h b/dlls/winegstreamer/gst_cbs.h
|
||||
index 10e999feea..0d7acaf0b8 100644
|
||||
--- a/dlls/winegstreamer/gst_cbs.h
|
||||
+++ b/dlls/winegstreamer/gst_cbs.h
|
||||
@@ -48,6 +48,7 @@ enum CB_TYPE {
|
||||
QUERY_BYTESTREAM,
|
||||
ACTIVATE_BYTESTREAM_PAD_MODE,
|
||||
PROCESS_BYTESTREAM_PAD_EVENT,
|
||||
+ WATCH_SOURCE_BUS,
|
||||
MEDIA_SOURCE_MAX,
|
||||
};
|
||||
|
||||
@@ -164,5 +165,6 @@ GstFlowReturn pull_from_bytestream_wrapper(GstPad *pad, GstObject *parent, guint
|
||||
gboolean query_bytestream_wrapper(GstPad *pad, GstObject *parent, GstQuery *query) DECLSPEC_HIDDEN;
|
||||
gboolean activate_bytestream_pad_mode_wrapper(GstPad *pad, GstObject *parent, GstPadMode mode, gboolean activate) DECLSPEC_HIDDEN;
|
||||
gboolean process_bytestream_pad_event_wrapper(GstPad *pad, GstObject *parent, GstEvent *event) DECLSPEC_HIDDEN;
|
||||
+GstBusSyncReply watch_source_bus_wrapper(GstBus *bus, GstMessage *message, gpointer user) DECLSPEC_HIDDEN;
|
||||
|
||||
#endif
|
||||
diff --git a/dlls/winegstreamer/media_source.c b/dlls/winegstreamer/media_source.c
|
||||
index 48119e4a89..e1f5c77375 100644
|
||||
--- a/dlls/winegstreamer/media_source.c
|
||||
+++ b/dlls/winegstreamer/media_source.c
|
||||
@@ -38,7 +38,12 @@ struct media_source
|
||||
enum source_type type;
|
||||
IMFMediaEventQueue *event_queue;
|
||||
IMFByteStream *byte_stream;
|
||||
- GstPad *my_src;
|
||||
+ struct media_stream **streams;
|
||||
+ ULONG stream_count;
|
||||
+ GstBus *bus;
|
||||
+ GstElement *container;
|
||||
+ GstElement *demuxer;
|
||||
+ GstPad *my_src, *their_sink;
|
||||
enum
|
||||
{
|
||||
SOURCE_OPENING,
|
||||
@@ -202,6 +207,37 @@ static gboolean process_bytestream_pad_event(GstPad *pad, GstObject *parent, Gst
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
+GstBusSyncReply watch_source_bus(GstBus *bus, GstMessage *message, gpointer user)
|
||||
+{
|
||||
+ struct media_source *source = (struct media_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;
|
||||
+ }
|
||||
+
|
||||
+ return GST_BUS_PASS;
|
||||
+}
|
||||
+
|
||||
static HRESULT WINAPI media_source_QueryInterface(IMFMediaSource *iface, REFIID riid, void **out)
|
||||
{
|
||||
struct media_source *source = impl_from_IMFMediaSource(iface);
|
||||
@@ -364,6 +400,13 @@ static HRESULT media_source_teardown(struct media_source *source)
|
||||
{
|
||||
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->container)
|
||||
+ {
|
||||
+ gst_element_set_state(source->container, GST_STATE_NULL);
|
||||
+ gst_object_unref(GST_OBJECT(source->container));
|
||||
+ }
|
||||
if (source->event_queue)
|
||||
IMFMediaEventQueue_Release(source->event_queue);
|
||||
if (source->byte_stream)
|
||||
@@ -408,7 +451,10 @@ static HRESULT media_source_constructor(IMFByteStream *bytestream, enum source_t
|
||||
source_descs[type].bytestream_caps);
|
||||
|
||||
struct media_source *object = heap_alloc_zero(sizeof(*object));
|
||||
+ GList *demuxer_list_one, *demuxer_list_two;
|
||||
+ GstElementFactory *demuxer_factory = NULL;
|
||||
HRESULT hr;
|
||||
+ int ret;
|
||||
|
||||
if (!object)
|
||||
return E_OUTOFMEMORY;
|
||||
@@ -422,6 +468,11 @@ static HRESULT media_source_constructor(IMFByteStream *bytestream, enum source_t
|
||||
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, watch_source_bus_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, pull_from_bytestream_wrapper);
|
||||
@@ -429,6 +480,44 @@ static HRESULT media_source_constructor(IMFByteStream *bytestream, enum source_t
|
||||
gst_pad_set_activatemode_function(object->my_src, activate_bytestream_pad_mode_wrapper);
|
||||
gst_pad_set_event_function(object->my_src, process_bytestream_pad_event_wrapper);
|
||||
|
||||
+ /* Find demuxer */
|
||||
+ demuxer_list_one = gst_element_factory_list_get_elements(GST_ELEMENT_FACTORY_TYPE_DEMUXER, 1);
|
||||
+
|
||||
+ demuxer_list_two = gst_element_factory_list_filter(demuxer_list_one, gst_static_caps_get(&source_descs[type].bytestream_caps), GST_PAD_SINK, 0);
|
||||
+ gst_plugin_feature_list_free(demuxer_list_one);
|
||||
+
|
||||
+ if (!(g_list_length(demuxer_list_two)))
|
||||
+ {
|
||||
+ ERR("Failed to find demuxer for source.\n");
|
||||
+ gst_plugin_feature_list_free(demuxer_list_two);
|
||||
+ hr = E_FAIL;
|
||||
+ goto fail;
|
||||
+ }
|
||||
+
|
||||
+ demuxer_factory = g_list_first(demuxer_list_two)->data;
|
||||
+ gst_object_ref(demuxer_factory);
|
||||
+ gst_plugin_feature_list_free(demuxer_list_two);
|
||||
+
|
||||
+ TRACE("Found demuxer %s.\n", GST_ELEMENT_NAME(demuxer_factory));
|
||||
+
|
||||
+ object->demuxer = gst_element_factory_create(demuxer_factory, NULL);
|
||||
+ if (!(object->demuxer))
|
||||
+ {
|
||||
+ WARN("Failed to create demuxer for source\n");
|
||||
+ hr = E_OUTOFMEMORY;
|
||||
+ goto fail;
|
||||
+ }
|
||||
+ gst_bin_add(GST_BIN(object->container), object->demuxer);
|
||||
+
|
||||
+ object->their_sink = gst_element_get_static_pad(object->demuxer, "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_STOPPED;
|
||||
|
||||
*out_media_source = object;
|
||||
@@ -437,6 +526,8 @@ static HRESULT media_source_constructor(IMFByteStream *bytestream, enum source_t
|
||||
fail:
|
||||
WARN("Failed to construct MFMediaSource, hr %#x.\n", hr);
|
||||
|
||||
+ if (demuxer_factory)
|
||||
+ gst_object_unref(demuxer_factory);
|
||||
media_source_teardown(object);
|
||||
heap_free(object);
|
||||
*out_media_source = NULL;
|
||||
@@ -935,6 +1026,12 @@ void perform_cb_media_source(struct cb_data *cbdata)
|
||||
cbdata->u.event_src_data.ret = process_bytestream_pad_event(data->pad, data->parent, data->event);
|
||||
break;
|
||||
}
|
||||
+ case WATCH_SOURCE_BUS:
|
||||
+ {
|
||||
+ struct watch_bus_data *data = &cbdata->u.watch_bus_data;
|
||||
+ cbdata->u.watch_bus_data.ret = watch_source_bus(data->bus, data->msg, data->user);
|
||||
+ break;
|
||||
+ }
|
||||
default:
|
||||
{
|
||||
ERR("Wrong callback forwarder called\n");
|
||||
--
|
||||
2.28.0
|
||||
|
@ -1,7 +1,7 @@
|
||||
From f1afd8f222ee3f552368117ef85953a90464f719 Mon Sep 17 00:00:00 2001
|
||||
From 2100ecb112e69962c11e4d5c841cc0ab003db6bb Mon Sep 17 00:00:00 2001
|
||||
From: Derek Lesho <dlesho@codeweavers.com>
|
||||
Date: Wed, 25 Mar 2020 13:36:19 -0500
|
||||
Subject: [PATCH 16/54] winegstreamer: Translate MPEG-4 Section-2 caps to
|
||||
Subject: [PATCH 10/52] winegstreamer: Translate MPEG-4 Section-2 caps to
|
||||
attributes.
|
||||
|
||||
Signed-off-by: Derek Lesho <dlesho@codeweavers.com>
|
||||
@ -10,10 +10,10 @@ Signed-off-by: Derek Lesho <dlesho@codeweavers.com>
|
||||
1 file changed, 16 insertions(+)
|
||||
|
||||
diff --git a/dlls/winegstreamer/mfplat.c b/dlls/winegstreamer/mfplat.c
|
||||
index ecb5de8b88..c45cfacc08 100644
|
||||
index 4cff74f2d41..f99e5c6636d 100644
|
||||
--- a/dlls/winegstreamer/mfplat.c
|
||||
+++ b/dlls/winegstreamer/mfplat.c
|
||||
@@ -652,6 +652,22 @@ static IMFMediaType* transform_to_media_type(GstCaps *caps)
|
||||
@@ -646,6 +646,22 @@ static IMFMediaType* transform_to_media_type(GstCaps *caps)
|
||||
|
||||
codec_data_to_user_data(info, media_type);
|
||||
}
|
||||
@ -34,8 +34,8 @@ index ecb5de8b88..c45cfacc08 100644
|
||||
+ }
|
||||
+ }
|
||||
else
|
||||
{
|
||||
FIXME("Unrecognized video format %s\n", mime_type);
|
||||
}
|
||||
--
|
||||
2.28.0
|
||||
|
@ -1,7 +1,7 @@
|
||||
From bf38004a42ba81f27e8edc65c1c04cab3cfccf14 Mon Sep 17 00:00:00 2001
|
||||
From 8b3eaedb9bb5ce6813f45e2553c657133d80718f Mon Sep 17 00:00:00 2001
|
||||
From: Derek Lesho <dlesho@codeweavers.com>
|
||||
Date: Tue, 12 May 2020 17:05:41 -0500
|
||||
Subject: [PATCH 17/54] winegstreamer: Translate WMA caps to attributes.
|
||||
Subject: [PATCH 11/52] winegstreamer: Translate WMA caps to attributes.
|
||||
|
||||
Signed-off-by: Derek Lesho <dlesho@codeweavers.com>
|
||||
---
|
||||
@ -9,10 +9,10 @@ Signed-off-by: Derek Lesho <dlesho@codeweavers.com>
|
||||
1 file changed, 24 insertions(+)
|
||||
|
||||
diff --git a/dlls/winegstreamer/mfplat.c b/dlls/winegstreamer/mfplat.c
|
||||
index c45cfacc08..fe187e6cd1 100644
|
||||
index f99e5c6636d..2a8c2050ff9 100644
|
||||
--- a/dlls/winegstreamer/mfplat.c
|
||||
+++ b/dlls/winegstreamer/mfplat.c
|
||||
@@ -831,6 +831,30 @@ static IMFMediaType* transform_to_media_type(GstCaps *caps)
|
||||
@@ -834,6 +834,30 @@ static IMFMediaType* transform_to_media_type(GstCaps *caps)
|
||||
FIXME("Unhandled mpegversion %d\n", mpeg_version);
|
||||
}
|
||||
}
|
||||
@ -41,8 +41,8 @@ index c45cfacc08..fe187e6cd1 100644
|
||||
+ codec_data_to_user_data(info, media_type);
|
||||
+ }
|
||||
else
|
||||
{
|
||||
FIXME("Unrecognized audio format %s\n", mime_type);
|
||||
}
|
||||
--
|
||||
2.28.0
|
||||
|
@ -1,20 +1,20 @@
|
||||
From 9aad2524a0610d3df313e508617831415a0f5f02 Mon Sep 17 00:00:00 2001
|
||||
From 50c496fa883c7a3fae0e991b7bcc96136a77a3df Mon Sep 17 00:00:00 2001
|
||||
From: Derek Lesho <dlesho@codeweavers.com>
|
||||
Date: Tue, 31 Mar 2020 11:21:21 -0500
|
||||
Subject: [PATCH] winegstreamer: Implement
|
||||
Subject: [PATCH 12/52] winegstreamer: Implement
|
||||
IMFMediaSource::CreatePresentationDescriptor.
|
||||
|
||||
Signed-off-by: Derek Lesho <dlesho@codeweavers.com>
|
||||
---
|
||||
dlls/mfplat/tests/mfplat.c | 8 +++----
|
||||
dlls/winegstreamer/media_source.c | 37 +++++++++++++++++++++++++++++--
|
||||
2 files changed, 39 insertions(+), 6 deletions(-)
|
||||
dlls/mfplat/tests/mfplat.c | 9 ++++----
|
||||
dlls/winegstreamer/media_source.c | 36 +++++++++++++++++++++++++++++--
|
||||
2 files changed, 38 insertions(+), 7 deletions(-)
|
||||
|
||||
diff --git a/dlls/mfplat/tests/mfplat.c b/dlls/mfplat/tests/mfplat.c
|
||||
index af7e0d0459..8fef44181c 100644
|
||||
index 309f7b669a4..72d06e31880 100644
|
||||
--- a/dlls/mfplat/tests/mfplat.c
|
||||
+++ b/dlls/mfplat/tests/mfplat.c
|
||||
@@ -529,10 +529,7 @@ static void test_source_resolver(void)
|
||||
@@ -576,10 +576,7 @@ static void test_source_resolver(void)
|
||||
ok(obj_type == MF_OBJECT_MEDIASOURCE, "got %d\n", obj_type);
|
||||
|
||||
hr = IMFMediaSource_CreatePresentationDescriptor(mediasource, &descriptor);
|
||||
@ -25,7 +25,7 @@ index af7e0d0459..8fef44181c 100644
|
||||
ok(descriptor != NULL, "got %p\n", descriptor);
|
||||
|
||||
hr = IMFPresentationDescriptor_GetStreamDescriptorByIndex(descriptor, 0, &selected, &sd);
|
||||
@@ -560,7 +557,10 @@ todo_wine
|
||||
@@ -607,7 +604,10 @@ todo_wine
|
||||
|
||||
var.vt = VT_EMPTY;
|
||||
hr = IMFMediaSource_Start(mediasource, descriptor, &GUID_NULL, &var);
|
||||
@ -36,7 +36,7 @@ index af7e0d0459..8fef44181c 100644
|
||||
|
||||
get_event((IMFMediaEventGenerator *)mediasource, MENewStream, &var);
|
||||
ok(var.vt == VT_UNKNOWN, "Unexpected value type %u from MENewStream event.\n", var.vt);
|
||||
@@ -623,10 +623,10 @@ todo_wine
|
||||
@@ -670,11 +670,10 @@ todo_wine
|
||||
|
||||
get_event((IMFMediaEventGenerator *)mediasource, MEEndOfPresentation, NULL);
|
||||
|
||||
@ -45,22 +45,23 @@ index af7e0d0459..8fef44181c 100644
|
||||
IMFPresentationDescriptor_Release(descriptor);
|
||||
|
||||
-skip_source_tests:
|
||||
-
|
||||
hr = IMFMediaSource_Shutdown(mediasource);
|
||||
ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
|
||||
|
||||
diff --git a/dlls/winegstreamer/media_source.c b/dlls/winegstreamer/media_source.c
|
||||
index f0acfa2830..33af1a6068 100644
|
||||
index 66cfdbdc0fd..6c0c212a100 100644
|
||||
--- a/dlls/winegstreamer/media_source.c
|
||||
+++ b/dlls/winegstreamer/media_source.c
|
||||
@@ -61,6 +61,7 @@ struct media_source
|
||||
@@ -70,6 +70,7 @@ struct media_source
|
||||
IMFByteStream *byte_stream;
|
||||
struct media_stream **streams;
|
||||
ULONG stream_count;
|
||||
+ IMFPresentationDescriptor *pres_desc;
|
||||
GstBus *bus;
|
||||
GstElement *container;
|
||||
GstElement *demuxer;
|
||||
@@ -743,12 +744,19 @@ static HRESULT WINAPI media_source_CreatePresentationDescriptor(IMFMediaSource *
|
||||
GstElement *decodebin;
|
||||
@@ -837,12 +838,19 @@ static HRESULT WINAPI media_source_CreatePresentationDescriptor(IMFMediaSource *
|
||||
{
|
||||
struct media_source *source = impl_from_IMFMediaSource(iface);
|
||||
|
||||
@ -82,39 +83,31 @@ index f0acfa2830..33af1a6068 100644
|
||||
}
|
||||
|
||||
static HRESULT WINAPI media_source_Start(IMFMediaSource *iface, IMFPresentationDescriptor *descriptor,
|
||||
@@ -801,6 +809,8 @@ static HRESULT media_source_teardown(struct media_source *source)
|
||||
gst_element_set_state(source->container, GST_STATE_NULL);
|
||||
gst_object_unref(GST_OBJECT(source->container));
|
||||
}
|
||||
@@ -904,6 +912,8 @@ static HRESULT WINAPI media_source_Shutdown(IMFMediaSource *iface)
|
||||
if (source->their_sink)
|
||||
gst_object_unref(GST_OBJECT(source->their_sink));
|
||||
|
||||
+ if (source->pres_desc)
|
||||
+ IMFPresentationDescriptor_Release(source->pres_desc);
|
||||
if (source->event_queue)
|
||||
IMFMediaEventQueue_Release(source->event_queue);
|
||||
IMFMediaEventQueue_Shutdown(source->event_queue);
|
||||
if (source->byte_stream)
|
||||
@@ -850,6 +860,7 @@ static const IMFMediaSourceVtbl IMFMediaSource_vtbl =
|
||||
@@ -1074,6 +1084,7 @@ static HRESULT media_source_constructor(IMFByteStream *bytestream, struct media_
|
||||
GST_STATIC_CAPS_ANY);
|
||||
|
||||
static HRESULT media_source_constructor(IMFByteStream *bytestream, enum source_type type, struct media_source **out_media_source)
|
||||
{
|
||||
+ unsigned int i;
|
||||
GstStaticPadTemplate src_template = GST_STATIC_PAD_TEMPLATE(
|
||||
"mf_src",
|
||||
GST_PAD_SRC,
|
||||
@@ -859,6 +870,7 @@ static HRESULT media_source_constructor(IMFByteStream *bytestream, enum source_t
|
||||
struct media_source *object = heap_alloc_zero(sizeof(*object));
|
||||
GList *demuxer_list_one, *demuxer_list_two;
|
||||
GstElementFactory *demuxer_factory = NULL;
|
||||
+ IMFStreamDescriptor **descriptors = NULL;
|
||||
HRESULT hr;
|
||||
int ret;
|
||||
|
||||
@@ -942,6 +954,25 @@ static HRESULT media_source_constructor(IMFByteStream *bytestream, enum source_t
|
||||
|
||||
WaitForSingleObject(object->all_streams_event, INFINITE);
|
||||
@@ -1149,6 +1160,25 @@ static HRESULT media_source_constructor(IMFByteStream *bytestream, struct media_
|
||||
goto fail;
|
||||
}
|
||||
|
||||
+ /* init presentation descriptor */
|
||||
+
|
||||
+ descriptors = heap_alloc(object->stream_count * sizeof(IMFStreamDescriptor*));
|
||||
+ for (i = 0; i < object->stream_count; i++)
|
||||
+ for (unsigned int i = 0; i < object->stream_count; i++)
|
||||
+ {
|
||||
+ IMFMediaStream_GetStreamDescriptor(&object->streams[i]->IMFMediaStream_iface, &descriptors[i]);
|
||||
+ }
|
||||
@ -122,7 +115,7 @@ index f0acfa2830..33af1a6068 100644
|
||||
+ if (FAILED(MFCreatePresentationDescriptor(object->stream_count, descriptors, &object->pres_desc)))
|
||||
+ goto fail;
|
||||
+
|
||||
+ for (i = 0; i < object->stream_count; i++)
|
||||
+ for (unsigned int i = 0; i < object->stream_count; i++)
|
||||
+ {
|
||||
+ IMFPresentationDescriptor_SelectStream(object->pres_desc, i);
|
||||
+ IMFStreamDescriptor_Release(descriptors[i]);
|
||||
@ -130,18 +123,18 @@ index f0acfa2830..33af1a6068 100644
|
||||
+ heap_free(descriptors);
|
||||
+ descriptors = NULL;
|
||||
+
|
||||
gst_element_set_state(object->container, GST_STATE_READY);
|
||||
|
||||
object->state = SOURCE_STOPPED;
|
||||
@@ -954,6 +985,8 @@ static HRESULT media_source_constructor(IMFByteStream *bytestream, enum source_t
|
||||
|
||||
if (demuxer_factory)
|
||||
gst_object_unref(demuxer_factory);
|
||||
*out_media_source = object;
|
||||
@@ -1157,6 +1187,8 @@ static HRESULT media_source_constructor(IMFByteStream *bytestream, struct media_
|
||||
fail:
|
||||
WARN("Failed to construct MFMediaSource, hr %#x.\n", hr);
|
||||
|
||||
+ if (descriptors)
|
||||
+ heap_free(descriptors);
|
||||
media_source_teardown(object);
|
||||
heap_free(object);
|
||||
*out_media_source = NULL;
|
||||
IMFMediaSource_Release(&object->IMFMediaSource_iface);
|
||||
return hr;
|
||||
}
|
||||
--
|
||||
2.28.0
|
||||
|
@ -1,327 +0,0 @@
|
||||
From c8d76047c38b229c76f6ecd810e0fdb2f73ee788 Mon Sep 17 00:00:00 2001
|
||||
From: Derek Lesho <dlesho@codeweavers.com>
|
||||
Date: Tue, 31 Mar 2020 11:11:05 -0500
|
||||
Subject: [PATCH 12/54] winegstreamer: Implement
|
||||
IMFMediaStream::GetStreamDescriptor.
|
||||
|
||||
Signed-off-by: Derek Lesho <dlesho@codeweavers.com>
|
||||
---
|
||||
dlls/winegstreamer/gst_private.h | 4 +
|
||||
dlls/winegstreamer/media_source.c | 45 ++++++-
|
||||
dlls/winegstreamer/mfplat.c | 196 ++++++++++++++++++++++++++++++
|
||||
3 files changed, 244 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/dlls/winegstreamer/gst_private.h b/dlls/winegstreamer/gst_private.h
|
||||
index 71ca429088..780cf1b02f 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;
|
||||
|
||||
+GstCaps *make_mf_compatible_caps(GstCaps *caps);
|
||||
+IMFMediaType *mf_media_type_from_caps(GstCaps *caps);
|
||||
+
|
||||
enum source_type
|
||||
{
|
||||
SOURCE_TYPE_MPEG_4,
|
||||
diff --git a/dlls/winegstreamer/media_source.c b/dlls/winegstreamer/media_source.c
|
||||
index 8335c64338..a654d555bc 100644
|
||||
--- a/dlls/winegstreamer/media_source.c
|
||||
+++ b/dlls/winegstreamer/media_source.c
|
||||
@@ -507,7 +507,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)
|
||||
@@ -539,6 +542,9 @@ static const IMFMediaStreamVtbl media_stream_vtbl =
|
||||
static HRESULT media_stream_constructor(struct media_source *source, GstPad *pad, DWORD stream_id, struct media_stream **out_stream)
|
||||
{
|
||||
struct media_stream *object = heap_alloc_zero(sizeof(*object));
|
||||
+ IMFMediaTypeHandler *type_handler = NULL;
|
||||
+ IMFMediaType *stream_type = NULL;
|
||||
+ GstCaps *caps = NULL;
|
||||
HRESULT hr;
|
||||
|
||||
TRACE("(%p %p)->(%p)\n", source, pad, out_stream);
|
||||
@@ -567,6 +573,36 @@ static HRESULT media_stream_constructor(struct media_source *source, GstPad *pad
|
||||
g_object_set(object->appsink, "async", FALSE, NULL); /* <- This allows us interact with the bin w/o prerolling */
|
||||
g_signal_connect(object->appsink, "new-sample", G_CALLBACK(stream_new_sample_wrapper), object);
|
||||
|
||||
+ if (!(caps = gst_pad_query_caps(pad, NULL)))
|
||||
+ goto fail;
|
||||
+
|
||||
+ if (TRACE_ON(mfplat))
|
||||
+ {
|
||||
+ gchar *caps_str = gst_caps_to_string(caps);
|
||||
+ TRACE("caps %s\n", debugstr_a(caps_str));
|
||||
+ g_free(caps_str);
|
||||
+ }
|
||||
+
|
||||
+ if (!(stream_type = mf_media_type_from_caps(caps)))
|
||||
+ goto fail;
|
||||
+
|
||||
+ gst_caps_unref(caps);
|
||||
+ caps = NULL;
|
||||
+
|
||||
+ if (FAILED(hr = MFCreateStreamDescriptor(stream_id, 1, &stream_type, &object->descriptor)))
|
||||
+ goto fail;
|
||||
+
|
||||
+ if (FAILED(hr = IMFStreamDescriptor_GetMediaTypeHandler(object->descriptor, &type_handler)))
|
||||
+ goto fail;
|
||||
+
|
||||
+ if (FAILED(hr = IMFMediaTypeHandler_SetCurrentMediaType(type_handler, stream_type)))
|
||||
+ goto fail;
|
||||
+
|
||||
+ IMFMediaTypeHandler_Release(type_handler);
|
||||
+ type_handler = NULL;
|
||||
+ IMFMediaType_Release(stream_type);
|
||||
+ stream_type = NULL;
|
||||
+
|
||||
object->my_sink = gst_element_get_static_pad(object->appsink, "sink");
|
||||
gst_pad_set_element_private(pad, object);
|
||||
|
||||
@@ -582,6 +618,13 @@ static HRESULT media_stream_constructor(struct media_source *source, GstPad *pad
|
||||
fail:
|
||||
WARN("Failed to construct media stream, hr %#x.\n", hr);
|
||||
|
||||
+ if (caps)
|
||||
+ gst_caps_unref(caps);
|
||||
+ if (stream_type)
|
||||
+ IMFMediaType_Release(stream_type);
|
||||
+ if (type_handler)
|
||||
+ IMFMediaTypeHandler_Release(type_handler);
|
||||
+
|
||||
IMFMediaStream_Release(&object->IMFMediaStream_iface);
|
||||
return hr;
|
||||
}
|
||||
diff --git a/dlls/winegstreamer/mfplat.c b/dlls/winegstreamer/mfplat.c
|
||||
index 16e55247de..90eb583c4a 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"
|
||||
@@ -442,3 +447,194 @@ HRESULT mfplat_get_class_object(REFCLSID rclsid, REFIID riid, void **obj)
|
||||
|
||||
return CLASS_E_CLASSNOTAVAILABLE;
|
||||
}
|
||||
+
|
||||
+const static struct
|
||||
+{
|
||||
+ const GUID *subtype;
|
||||
+ GstVideoFormat format;
|
||||
+}
|
||||
+uncompressed_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},
|
||||
+};
|
||||
+
|
||||
+/* caps will be modified to represent the exact type needed for the format */
|
||||
+static IMFMediaType* transform_to_media_type(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_formats); i++)
|
||||
+ {
|
||||
+ if (uncompressed_formats[i].format == video_info.finfo->format)
|
||||
+ {
|
||||
+ IMFMediaType_SetGUID(media_type, &MF_MT_SUBTYPE, uncompressed_formats[i].subtype);
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+ if (i == ARRAY_SIZE(uncompressed_formats))
|
||||
+ FIXME("Unrecognized format.\n");
|
||||
+ }
|
||||
+ }
|
||||
+ else
|
||||
+ FIXME("Unrecognized video format %s\n", mime_type);
|
||||
+ }
|
||||
+ else if (!(strncmp(mime_type, "audio", 5)))
|
||||
+ {
|
||||
+ gint rate, channels, bitrate;
|
||||
+ 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_int(info, "bitrate", &bitrate))
|
||||
+ IMFMediaType_SetUINT32(media_type, &MF_MT_AVG_BITRATE, bitrate);
|
||||
+
|
||||
+ if (!(strcmp(mime_type, "audio/x-raw")))
|
||||
+ {
|
||||
+ const char *format;
|
||||
+ if ((format = gst_structure_get_string(info, "format")))
|
||||
+ {
|
||||
+ char type;
|
||||
+ unsigned int bits_per_sample;
|
||||
+ char endian[2];
|
||||
+ char new_format[6];
|
||||
+ if ((strlen(format) > 5) || (sscanf(format, "%c%u%2c", &type, &bits_per_sample, endian) < 2))
|
||||
+ {
|
||||
+ FIXME("Unhandled audio format %s\n", format);
|
||||
+ IMFMediaType_Release(media_type);
|
||||
+ return NULL;
|
||||
+ }
|
||||
+
|
||||
+ if (type == 'F')
|
||||
+ {
|
||||
+ IMFMediaType_SetGUID(media_type, &MF_MT_SUBTYPE, &MFAudioFormat_Float);
|
||||
+ }
|
||||
+ else if (type == 'U' || type == 'S')
|
||||
+ {
|
||||
+ IMFMediaType_SetGUID(media_type, &MF_MT_SUBTYPE, &MFAudioFormat_PCM);
|
||||
+ if (bits_per_sample == 8)
|
||||
+ type = 'U';
|
||||
+ else
|
||||
+ type = 'S';
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ FIXME("Unrecognized audio format: %s\n", format);
|
||||
+ IMFMediaType_Release(media_type);
|
||||
+ return NULL;
|
||||
+ }
|
||||
+
|
||||
+ IMFMediaType_SetUINT32(media_type, &MF_MT_AUDIO_BITS_PER_SAMPLE, bits_per_sample);
|
||||
+
|
||||
+ if (endian[0] == 'B')
|
||||
+ endian[0] = 'L';
|
||||
+
|
||||
+ sprintf(new_format, "%c%u%.2s", type, bits_per_sample, bits_per_sample > 8 ? endian : 0);
|
||||
+ gst_caps_set_simple(caps, "format", G_TYPE_STRING, new_format, NULL);
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ ERR("Failed to get audio format\n");
|
||||
+ }
|
||||
+ }
|
||||
+ else
|
||||
+ FIXME("Unrecognized audio format %s\n", mime_type);
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ IMFMediaType_Release(media_type);
|
||||
+ return NULL;
|
||||
+ }
|
||||
+
|
||||
+ return media_type;
|
||||
+}
|
||||
+
|
||||
+/* returns NULL if doesn't match exactly */
|
||||
+IMFMediaType *mf_media_type_from_caps(GstCaps *caps)
|
||||
+{
|
||||
+ GstCaps *writeable_caps;
|
||||
+ IMFMediaType *ret;
|
||||
+
|
||||
+ writeable_caps = gst_caps_copy(caps);
|
||||
+ ret = transform_to_media_type(writeable_caps);
|
||||
+
|
||||
+ if (!(gst_caps_is_equal(caps, writeable_caps)))
|
||||
+ {
|
||||
+ IMFMediaType_Release(ret);
|
||||
+ ret = NULL;
|
||||
+ }
|
||||
+ gst_caps_unref(writeable_caps);
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+GstCaps *make_mf_compatible_caps(GstCaps *caps)
|
||||
+{
|
||||
+ GstCaps *ret;
|
||||
+ IMFMediaType *media_type;
|
||||
+
|
||||
+ ret = gst_caps_copy(caps);
|
||||
+
|
||||
+ if ((media_type = transform_to_media_type(ret)))
|
||||
+ IMFMediaType_Release(media_type);
|
||||
+
|
||||
+ if (!media_type)
|
||||
+ {
|
||||
+ gst_caps_unref(ret);
|
||||
+ return NULL;
|
||||
+ }
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
\ No newline at end of file
|
||||
--
|
||||
2.28.0
|
||||
|
@ -1,35 +1,36 @@
|
||||
From 32b23b1380f44a6c3106e0e789e31c5cbed94b5e Mon Sep 17 00:00:00 2001
|
||||
From 309bf9ba18c12e8f6eb9a29c7455983fa7bf3603 Mon Sep 17 00:00:00 2001
|
||||
From: Derek Lesho <dlesho@codeweavers.com>
|
||||
Date: Tue, 24 Mar 2020 16:15:35 -0500
|
||||
Subject: [PATCH 26/54] winegstreamer: Introduce IMFMediaType -> GstCaps
|
||||
Subject: [PATCH 13/52] winegstreamer: Introduce IMFMediaType -> GstCaps
|
||||
converter.
|
||||
|
||||
Signed-off-by: Derek Lesho <dlesho@codeweavers.com>
|
||||
---
|
||||
dlls/winegstreamer/gst_private.h | 1 +
|
||||
dlls/winegstreamer/mfplat.c | 145 +++++++++++++++++++++++++++++++
|
||||
2 files changed, 146 insertions(+)
|
||||
dlls/winegstreamer/mfplat.c | 149 +++++++++++++++++++++++++++++++
|
||||
2 files changed, 150 insertions(+)
|
||||
|
||||
diff --git a/dlls/winegstreamer/gst_private.h b/dlls/winegstreamer/gst_private.h
|
||||
index 823e023f52..20d3beef02 100644
|
||||
index 86392eea4e3..d0628cc8df3 100644
|
||||
--- a/dlls/winegstreamer/gst_private.h
|
||||
+++ b/dlls/winegstreamer/gst_private.h
|
||||
@@ -57,6 +57,7 @@ extern HRESULT mfplat_get_class_object(REFCLSID rclsid, REFIID riid, void **obj)
|
||||
|
||||
@@ -58,6 +58,7 @@ extern HRESULT mfplat_get_class_object(REFCLSID rclsid, REFIID riid, void **obj)
|
||||
HRESULT winegstreamer_stream_handler_create(REFIID riid, void **obj) DECLSPEC_HIDDEN;
|
||||
GstCaps *make_mf_compatible_caps(GstCaps *caps);
|
||||
IMFMediaType *mf_media_type_from_caps(GstCaps *caps);
|
||||
+GstCaps *caps_from_mf_media_type(IMFMediaType *type);
|
||||
IMFSample *mf_sample_from_gst_buffer(GstBuffer *in);
|
||||
|
||||
enum source_type
|
||||
HRESULT winegstreamer_stream_handler_create(REFIID riid, void **obj) DECLSPEC_HIDDEN;
|
||||
|
||||
diff --git a/dlls/winegstreamer/mfplat.c b/dlls/winegstreamer/mfplat.c
|
||||
index e09309fd4d..ba2a32e610 100644
|
||||
index 2a8c2050ff9..648cdd23421 100644
|
||||
--- a/dlls/winegstreamer/mfplat.c
|
||||
+++ b/dlls/winegstreamer/mfplat.c
|
||||
@@ -904,6 +904,151 @@ GstCaps *make_mf_compatible_caps(GstCaps *caps)
|
||||
@@ -910,3 +910,152 @@ GstCaps *make_mf_compatible_caps(GstCaps *caps)
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
+
|
||||
+GstCaps *caps_from_mf_media_type(IMFMediaType *type)
|
||||
+{
|
||||
+ GUID major_type;
|
||||
@ -116,7 +117,7 @@ index e09309fd4d..ba2a32e610 100644
|
||||
+ }
|
||||
+ else if (IsEqualGUID(&major_type, &MFMediaType_Audio))
|
||||
+ {
|
||||
+ DWORD rate, channels, bitrate;
|
||||
+ DWORD rate, channels, channel_mask, bitrate;
|
||||
+
|
||||
+ if (IsEqualGUID(&subtype, &MFAudioFormat_Float))
|
||||
+ {
|
||||
@ -162,6 +163,10 @@ index e09309fd4d..ba2a32e610 100644
|
||||
+ {
|
||||
+ gst_caps_set_simple(output, "channels", G_TYPE_INT, channels, NULL);
|
||||
+ }
|
||||
+ if (SUCCEEDED(IMFMediaType_GetUINT32(type, &MF_MT_AUDIO_CHANNEL_MASK, &channel_mask)))
|
||||
+ {
|
||||
+ gst_caps_set_simple(output, "channel-mask", GST_TYPE_BITMASK, (guint64) channel_mask, NULL);
|
||||
+ }
|
||||
+
|
||||
+ if (SUCCEEDED(IMFMediaType_GetUINT32(type, &MF_MT_AVG_BITRATE, &bitrate)))
|
||||
+ {
|
||||
@ -174,10 +179,6 @@ index e09309fd4d..ba2a32e610 100644
|
||||
+ FIXME("Unrecognized major type %s\n", debugstr_guid(&major_type));
|
||||
+ return NULL;
|
||||
+}
|
||||
+
|
||||
/* IMFSample = GstBuffer
|
||||
IMFBuffer = GstMemory */
|
||||
|
||||
--
|
||||
2.28.0
|
||||
|
@ -1,7 +1,7 @@
|
||||
From c60414ceb49b5ff025a101b9ffdf0aa665b0cf2c Mon Sep 17 00:00:00 2001
|
||||
From 98ccb2c72d763514c1e3232e93dab697bede4cad Mon Sep 17 00:00:00 2001
|
||||
From: Derek Lesho <dlesho@codeweavers.com>
|
||||
Date: Tue, 24 Mar 2020 16:18:40 -0500
|
||||
Subject: [PATCH 27/54] winegstreamer: Translate H.264 attributes to caps.
|
||||
Subject: [PATCH 14/52] winegstreamer: Translate H.264 attributes to caps.
|
||||
|
||||
Signed-off-by: Derek Lesho <dlesho@codeweavers.com>
|
||||
---
|
||||
@ -9,10 +9,10 @@ Signed-off-by: Derek Lesho <dlesho@codeweavers.com>
|
||||
1 file changed, 48 insertions(+)
|
||||
|
||||
diff --git a/dlls/winegstreamer/mfplat.c b/dlls/winegstreamer/mfplat.c
|
||||
index ba2a32e610..26ad75584d 100644
|
||||
index 648cdd23421..bc0259f2a64 100644
|
||||
--- a/dlls/winegstreamer/mfplat.c
|
||||
+++ b/dlls/winegstreamer/mfplat.c
|
||||
@@ -973,6 +973,54 @@ GstCaps *caps_from_mf_media_type(IMFMediaType *type)
|
||||
@@ -980,6 +980,54 @@ GstCaps *caps_from_mf_media_type(IMFMediaType *type)
|
||||
}
|
||||
|
||||
}
|
@ -1,18 +1,18 @@
|
||||
From 79ffdf47055128475526a432b175362bbbaf57da Mon Sep 17 00:00:00 2001
|
||||
From 884a00b050f17191a7c48364de4e55e5fcc17cc9 Mon Sep 17 00:00:00 2001
|
||||
From: Derek Lesho <dlesho@codeweavers.com>
|
||||
Date: Tue, 24 Mar 2020 16:20:17 -0500
|
||||
Subject: [PATCH 28/54] winegstreamer: Translate WMV attributes to caps.
|
||||
Subject: [PATCH 15/52] winegstreamer: Translate WMV attributes to caps.
|
||||
|
||||
Signed-off-by: Derek Lesho <dlesho@codeweavers.com>
|
||||
---
|
||||
dlls/winegstreamer/mfplat.c | 24 ++++++++++++++++++++++++
|
||||
1 file changed, 24 insertions(+)
|
||||
dlls/winegstreamer/mfplat.c | 51 +++++++++++++++++++++++++++++++++++++
|
||||
1 file changed, 51 insertions(+)
|
||||
|
||||
diff --git a/dlls/winegstreamer/mfplat.c b/dlls/winegstreamer/mfplat.c
|
||||
index 26ad75584d..f5b44f9214 100644
|
||||
index bc0259f2a64..a9abffedcd0 100644
|
||||
--- a/dlls/winegstreamer/mfplat.c
|
||||
+++ b/dlls/winegstreamer/mfplat.c
|
||||
@@ -904,6 +904,21 @@ GstCaps *make_mf_compatible_caps(GstCaps *caps)
|
||||
@@ -911,6 +911,21 @@ GstCaps *make_mf_compatible_caps(GstCaps *caps)
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -34,10 +34,37 @@ index 26ad75584d..f5b44f9214 100644
|
||||
GstCaps *caps_from_mf_media_type(IMFMediaType *type)
|
||||
{
|
||||
GUID major_type;
|
||||
@@ -1021,6 +1036,15 @@ GstCaps *caps_from_mf_media_type(IMFMediaType *type)
|
||||
@@ -1028,6 +1043,42 @@ GstCaps *caps_from_mf_media_type(IMFMediaType *type)
|
||||
gst_caps_set_simple(output, "level", G_TYPE_STRING, level, NULL);
|
||||
}
|
||||
}
|
||||
+ else if (IsEqualGUID(&subtype, &MFVideoFormat_WMV1))
|
||||
+ {
|
||||
+ output = gst_caps_new_empty_simple("video/x-wmv");
|
||||
+ gst_caps_set_simple(output, "format", G_TYPE_STRING, "WMV1", NULL);
|
||||
+
|
||||
+ gst_caps_set_simple(output, "wmvversion", G_TYPE_INT, 1, NULL);
|
||||
+
|
||||
+ user_data_to_codec_data(type, output);
|
||||
+ }
|
||||
+ else if (IsEqualGUID(&subtype, &MFVideoFormat_WMV2))
|
||||
+ {
|
||||
+ output = gst_caps_new_empty_simple("video/x-wmv");
|
||||
+ gst_caps_set_simple(output, "format", G_TYPE_STRING, "WMV2", NULL);
|
||||
+
|
||||
+ gst_caps_set_simple(output, "wmvversion", G_TYPE_INT, 2, NULL);
|
||||
+
|
||||
+ user_data_to_codec_data(type, output);
|
||||
+ }
|
||||
+ else if (IsEqualGUID(&subtype, &MFVideoFormat_WMV3))
|
||||
+ {
|
||||
+ output = gst_caps_new_empty_simple("video/x-wmv");
|
||||
+ gst_caps_set_simple(output, "format", G_TYPE_STRING, "WMV3", NULL);
|
||||
+
|
||||
+ gst_caps_set_simple(output, "wmvversion", G_TYPE_INT, 3, NULL);
|
||||
+
|
||||
+ user_data_to_codec_data(type, output);
|
||||
+ }
|
||||
+ else if (IsEqualGUID(&subtype, &MFVideoFormat_WVC1))
|
||||
+ {
|
||||
+ output = gst_caps_new_empty_simple("video/x-wmv");
|
@ -1,7 +1,7 @@
|
||||
From f94f3362a246e5f1f476f6a51465424e1ae6d7c7 Mon Sep 17 00:00:00 2001
|
||||
From 7fd3f66161894a1242d43b6abd54e65ed6831270 Mon Sep 17 00:00:00 2001
|
||||
From: Derek Lesho <dlesho@codeweavers.com>
|
||||
Date: Tue, 21 Apr 2020 10:31:02 -0500
|
||||
Subject: [PATCH 29/54] winegstreamer: Translate AAC attributes to caps.
|
||||
Subject: [PATCH 16/52] winegstreamer: Translate AAC attributes to caps.
|
||||
|
||||
Signed-off-by: Derek Lesho <dlesho@codeweavers.com>
|
||||
---
|
||||
@ -9,10 +9,10 @@ Signed-off-by: Derek Lesho <dlesho@codeweavers.com>
|
||||
1 file changed, 66 insertions(+)
|
||||
|
||||
diff --git a/dlls/winegstreamer/mfplat.c b/dlls/winegstreamer/mfplat.c
|
||||
index f5b44f9214..7e96e6af20 100644
|
||||
index a9abffedcd0..75d8e338128 100644
|
||||
--- a/dlls/winegstreamer/mfplat.c
|
||||
+++ b/dlls/winegstreamer/mfplat.c
|
||||
@@ -1094,6 +1094,72 @@ GstCaps *caps_from_mf_media_type(IMFMediaType *type)
|
||||
@@ -1128,6 +1128,72 @@ GstCaps *caps_from_mf_media_type(IMFMediaType *type)
|
||||
return NULL;
|
||||
}
|
||||
}
|
@ -1,19 +1,19 @@
|
||||
From 8bd70d8a970af6e9a31158fa57085918ee57817c Mon Sep 17 00:00:00 2001
|
||||
From f15f0c3530b20cff7de1e3295d2b7978e9b0d2c7 Mon Sep 17 00:00:00 2001
|
||||
From: Derek Lesho <dlesho@codeweavers.com>
|
||||
Date: Mon, 11 May 2020 16:03:09 -0500
|
||||
Subject: [PATCH 30/54] winegstreamer: Translate MPEG-4 Section-2 attributes to
|
||||
Subject: [PATCH 17/52] winegstreamer: Translate MPEG-4 Section-2 attributes to
|
||||
caps.
|
||||
|
||||
Signed-off-by: Derek Lesho <dlesho@codeweavers.com>
|
||||
---
|
||||
dlls/winegstreamer/mfplat.c | 7 +++++++
|
||||
1 file changed, 7 insertions(+)
|
||||
dlls/winegstreamer/mfplat.c | 8 ++++++++
|
||||
1 file changed, 8 insertions(+)
|
||||
|
||||
diff --git a/dlls/winegstreamer/mfplat.c b/dlls/winegstreamer/mfplat.c
|
||||
index 7e96e6af20..c7d6e4806a 100644
|
||||
index 75d8e338128..b7fa283133c 100644
|
||||
--- a/dlls/winegstreamer/mfplat.c
|
||||
+++ b/dlls/winegstreamer/mfplat.c
|
||||
@@ -1045,6 +1045,13 @@ GstCaps *caps_from_mf_media_type(IMFMediaType *type)
|
||||
@@ -1079,6 +1079,14 @@ GstCaps *caps_from_mf_media_type(IMFMediaType *type)
|
||||
|
||||
user_data_to_codec_data(type, output);
|
||||
}
|
||||
@ -21,6 +21,7 @@ index 7e96e6af20..c7d6e4806a 100644
|
||||
+ {
|
||||
+ output = gst_caps_new_empty_simple("video/mpeg");
|
||||
+ gst_caps_set_simple(output, "mpegversion", G_TYPE_INT, 4, NULL);
|
||||
+ gst_caps_set_simple(output, "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
|
||||
+
|
||||
+ user_data_to_codec_data(type, output);
|
||||
+ }
|
@ -1,7 +1,7 @@
|
||||
From e73bfd928bb2a0e02fe6243013132b0e63b27a52 Mon Sep 17 00:00:00 2001
|
||||
From ccb8ad4ef7bc35a62f7ec58d4ce591f6e2678598 Mon Sep 17 00:00:00 2001
|
||||
From: Derek Lesho <dlesho@codeweavers.com>
|
||||
Date: Tue, 12 May 2020 17:05:59 -0500
|
||||
Subject: [PATCH 31/54] winegstreamer: Translate WMA attributes to caps.
|
||||
Subject: [PATCH 18/52] winegstreamer: Translate WMA attributes to caps.
|
||||
|
||||
Signed-off-by: Derek Lesho <dlesho@codeweavers.com>
|
||||
---
|
||||
@ -9,10 +9,10 @@ Signed-off-by: Derek Lesho <dlesho@codeweavers.com>
|
||||
1 file changed, 15 insertions(+)
|
||||
|
||||
diff --git a/dlls/winegstreamer/mfplat.c b/dlls/winegstreamer/mfplat.c
|
||||
index c7d6e4806a..86f0f79630 100644
|
||||
index b7fa283133c..b291b21e8b5 100644
|
||||
--- a/dlls/winegstreamer/mfplat.c
|
||||
+++ b/dlls/winegstreamer/mfplat.c
|
||||
@@ -1167,6 +1167,21 @@ GstCaps *caps_from_mf_media_type(IMFMediaType *type)
|
||||
@@ -1202,6 +1202,21 @@ GstCaps *caps_from_mf_media_type(IMFMediaType *type)
|
||||
CoTaskMemFree(user_data);
|
||||
}
|
||||
}
|
@ -1,19 +1,19 @@
|
||||
From 5de8cd0751587ad6efe73f6b8cde6829a14d1203 Mon Sep 17 00:00:00 2001
|
||||
From d883eb8c94f0778d4ef955480a3862d575f7130a Mon Sep 17 00:00:00 2001
|
||||
From: Derek Lesho <dlesho@codeweavers.com>
|
||||
Date: Tue, 31 Mar 2020 15:10:03 -0500
|
||||
Subject: [PATCH] winegstreamer: Implement IMFMediaSource::Start.
|
||||
Subject: [PATCH 19/52] winegstreamer: Implement IMFMediaSource::Start.
|
||||
|
||||
Signed-off-by: Derek Lesho <dlesho@codeweavers.com>
|
||||
---
|
||||
dlls/mfplat/tests/mfplat.c | 8 +-
|
||||
dlls/winegstreamer/media_source.c | 285 +++++++++++++++++++++++++++++-
|
||||
2 files changed, 286 insertions(+), 7 deletions(-)
|
||||
dlls/winegstreamer/media_source.c | 313 +++++++++++++++++++++++++++++-
|
||||
2 files changed, 314 insertions(+), 7 deletions(-)
|
||||
|
||||
diff --git a/dlls/mfplat/tests/mfplat.c b/dlls/mfplat/tests/mfplat.c
|
||||
index 8fef44181c..c26c40d531 100644
|
||||
index 72d06e31880..e6a1694a11f 100644
|
||||
--- a/dlls/mfplat/tests/mfplat.c
|
||||
+++ b/dlls/mfplat/tests/mfplat.c
|
||||
@@ -557,10 +557,7 @@ static void test_source_resolver(void)
|
||||
@@ -604,10 +604,7 @@ static void test_source_resolver(void)
|
||||
|
||||
var.vt = VT_EMPTY;
|
||||
hr = IMFMediaSource_Start(mediasource, descriptor, &GUID_NULL, &var);
|
||||
@ -24,7 +24,7 @@ index 8fef44181c..c26c40d531 100644
|
||||
|
||||
get_event((IMFMediaEventGenerator *)mediasource, MENewStream, &var);
|
||||
ok(var.vt == VT_UNKNOWN, "Unexpected value type %u from MENewStream event.\n", var.vt);
|
||||
@@ -578,10 +575,13 @@ todo_wine
|
||||
@@ -625,10 +622,13 @@ todo_wine
|
||||
hr = IMFMediaStream_RequestSample(video_stream, NULL);
|
||||
if (i == sample_count)
|
||||
break;
|
||||
@ -38,7 +38,7 @@ index 8fef44181c..c26c40d531 100644
|
||||
|
||||
for (i = 0; i < sample_count; ++i)
|
||||
{
|
||||
@@ -619,11 +619,11 @@ todo_wine
|
||||
@@ -666,11 +666,11 @@ todo_wine
|
||||
|
||||
hr = IMFMediaStream_RequestSample(video_stream, NULL);
|
||||
ok(hr == MF_E_END_OF_STREAM, "Unexpected hr %#x.\n", hr);
|
||||
@ -52,13 +52,18 @@ index 8fef44181c..c26c40d531 100644
|
||||
IMFPresentationDescriptor_Release(descriptor);
|
||||
|
||||
diff --git a/dlls/winegstreamer/media_source.c b/dlls/winegstreamer/media_source.c
|
||||
index 33af1a6068..e5bf4d2b5d 100644
|
||||
index 6c0c212a100..c893664fbec 100644
|
||||
--- a/dlls/winegstreamer/media_source.c
|
||||
+++ b/dlls/winegstreamer/media_source.c
|
||||
@@ -50,12 +50,36 @@ struct media_stream
|
||||
STREAM_RUNNING,
|
||||
@@ -56,16 +56,41 @@ struct media_stream
|
||||
STREAM_STUB,
|
||||
STREAM_INACTIVE,
|
||||
STREAM_SHUTDOWN,
|
||||
+ STREAM_RUNNING,
|
||||
} state;
|
||||
/* used when in STUB state: */
|
||||
DWORD stream_id;
|
||||
HANDLE caps_event;
|
||||
+ BOOL eos;
|
||||
+};
|
||||
+
|
||||
@ -89,10 +94,18 @@ index 33af1a6068..e5bf4d2b5d 100644
|
||||
+ IMFAsyncCallback async_commands_callback;
|
||||
LONG ref;
|
||||
+ DWORD async_commands_queue;
|
||||
enum source_type type;
|
||||
IMFMediaEventQueue *event_queue;
|
||||
IMFByteStream *byte_stream;
|
||||
@@ -87,6 +111,238 @@ static inline struct media_source *impl_from_IMFMediaSource(IMFMediaSource *ifac
|
||||
struct media_stream **streams;
|
||||
@@ -79,6 +104,7 @@ struct media_source
|
||||
{
|
||||
SOURCE_OPENING,
|
||||
SOURCE_STOPPED,
|
||||
+ SOURCE_RUNNING,
|
||||
SOURCE_SHUTDOWN,
|
||||
} state;
|
||||
HANDLE all_streams_event;
|
||||
@@ -94,6 +120,264 @@ static inline struct media_source *impl_from_IMFMediaSource(IMFMediaSource *ifac
|
||||
return CONTAINING_RECORD(iface, struct media_source, IMFMediaSource_iface);
|
||||
}
|
||||
|
||||
@ -202,12 +215,11 @@ index 33af1a6068..e5bf4d2b5d 100644
|
||||
+{
|
||||
+ ULONG sd_count;
|
||||
+ IMFStreamDescriptor *ret;
|
||||
+ unsigned int i;
|
||||
+
|
||||
+ if (FAILED(IMFPresentationDescriptor_GetStreamDescriptorCount(pres_desc, &sd_count)))
|
||||
+ return NULL;
|
||||
+
|
||||
+ for (i = 0; i < sd_count; i++)
|
||||
+ for (unsigned int i = 0; i < sd_count; i++)
|
||||
+ {
|
||||
+ DWORD stream_id;
|
||||
+
|
||||
@ -226,23 +238,29 @@ index 33af1a6068..e5bf4d2b5d 100644
|
||||
+{
|
||||
+ PROPVARIANT *position = &command->u.start.position;
|
||||
+ BOOL seek_message = source->state != SOURCE_STOPPED && position->vt != VT_EMPTY;
|
||||
+ unsigned int i;
|
||||
+
|
||||
+ /* we can't seek until the pipeline is in a valid state */
|
||||
+ gst_element_set_state(source->container, GST_STATE_PAUSED);
|
||||
+ assert(gst_element_get_state(source->container, NULL, NULL, -1) == GST_STATE_CHANGE_SUCCESS);
|
||||
+ if (source->state == SOURCE_STOPPED)
|
||||
+
|
||||
+ /* seek to beginning on stop->play */
|
||||
+ if (source->state == SOURCE_STOPPED && position->vt == VT_EMPTY)
|
||||
+ {
|
||||
+ WaitForSingleObject(source->all_streams_event, INFINITE);
|
||||
+ position->vt = VT_I8;
|
||||
+ position->u.hVal.QuadPart = 0;
|
||||
+ }
|
||||
+
|
||||
+ for (i = 0; i < source->stream_count; i++)
|
||||
+ for (unsigned int i = 0; i < source->stream_count; i++)
|
||||
+ {
|
||||
+ struct media_stream *stream;
|
||||
+ IMFStreamDescriptor *sd;
|
||||
+ IMFMediaTypeHandler *mth;
|
||||
+ IMFMediaType *current_mt;
|
||||
+ GstCaps *current_caps;
|
||||
+ GstCaps *prev_caps;
|
||||
+ DWORD stream_id;
|
||||
+ BOOL was_active;
|
||||
+ BOOL selected;
|
||||
+ BOOL changed_caps;
|
||||
+
|
||||
+ stream = source->streams[i];
|
||||
+
|
||||
@ -253,6 +271,29 @@ index 33af1a6068..e5bf4d2b5d 100644
|
||||
+
|
||||
+ was_active = stream->state != STREAM_INACTIVE;
|
||||
+
|
||||
+ stream->state = selected ? STREAM_RUNNING : STREAM_INACTIVE;
|
||||
+
|
||||
+ if (selected)
|
||||
+ {
|
||||
+ IMFStreamDescriptor_GetMediaTypeHandler(stream->descriptor, &mth);
|
||||
+ IMFMediaTypeHandler_GetCurrentMediaType(mth, ¤t_mt);
|
||||
+ current_caps = caps_from_mf_media_type(current_mt);
|
||||
+ g_object_get(stream->appsink, "caps", &prev_caps, NULL);
|
||||
+ changed_caps = !gst_caps_is_equal(prev_caps, current_caps);
|
||||
+
|
||||
+ if (changed_caps)
|
||||
+ {
|
||||
+ g_object_set(stream->appsink, "caps", current_caps, NULL);
|
||||
+ GstEvent *reconfigure_event = gst_event_new_reconfigure();
|
||||
+ gst_pad_push_event(gst_element_get_static_pad(stream->appsink, "sink"), reconfigure_event);
|
||||
+ }
|
||||
+
|
||||
+ gst_caps_unref(current_caps);
|
||||
+ gst_caps_unref(prev_caps);
|
||||
+ IMFMediaType_Release(current_mt);
|
||||
+ IMFMediaTypeHandler_Release(mth);
|
||||
+ }
|
||||
+
|
||||
+ if (position->vt != VT_EMPTY)
|
||||
+ {
|
||||
+ GstEvent *seek_event = gst_event_new_seek(1.0, GST_FORMAT_TIME, GST_SEEK_FLAG_FLUSH,
|
||||
@ -265,8 +306,6 @@ index 33af1a6068..e5bf4d2b5d 100644
|
||||
+ stream->eos = FALSE;
|
||||
+ }
|
||||
+
|
||||
+ stream->state = selected ? STREAM_RUNNING : STREAM_INACTIVE;
|
||||
+
|
||||
+ if (selected)
|
||||
+ {
|
||||
+ TRACE("Stream %u (%p) selected\n", i, stream);
|
||||
@ -328,10 +367,10 @@ index 33af1a6068..e5bf4d2b5d 100644
|
||||
+ source_async_commands_Invoke,
|
||||
+};
|
||||
+
|
||||
/* inactive stream sample discarder */
|
||||
static GstFlowReturn stream_new_sample(GstElement *appsink, gpointer user)
|
||||
GstFlowReturn pull_from_bytestream(GstPad *pad, GstObject *parent, guint64 ofs, guint len,
|
||||
GstBuffer **buf)
|
||||
{
|
||||
@@ -760,16 +1016,32 @@ static HRESULT WINAPI media_source_CreatePresentationDescriptor(IMFMediaSource *
|
||||
@@ -854,16 +1138,32 @@ static HRESULT WINAPI media_source_CreatePresentationDescriptor(IMFMediaSource *
|
||||
}
|
||||
|
||||
static HRESULT WINAPI media_source_Start(IMFMediaSource *iface, IMFPresentationDescriptor *descriptor,
|
||||
@ -367,7 +406,7 @@ index 33af1a6068..e5bf4d2b5d 100644
|
||||
}
|
||||
|
||||
static HRESULT WINAPI media_source_Stop(IMFMediaSource *iface)
|
||||
@@ -828,6 +1100,9 @@ static HRESULT media_source_teardown(struct media_source *source)
|
||||
@@ -931,6 +1231,9 @@ static HRESULT WINAPI media_source_Shutdown(IMFMediaSource *iface)
|
||||
if (source->all_streams_event)
|
||||
CloseHandle(source->all_streams_event);
|
||||
|
||||
@ -377,15 +416,15 @@ index 33af1a6068..e5bf4d2b5d 100644
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
@@ -878,6 +1153,7 @@ static HRESULT media_source_constructor(IMFByteStream *bytestream, enum source_t
|
||||
@@ -1092,6 +1395,7 @@ static HRESULT media_source_constructor(IMFByteStream *bytestream, struct media_
|
||||
return E_OUTOFMEMORY;
|
||||
|
||||
object->IMFMediaSource_iface.lpVtbl = &IMFMediaSource_vtbl;
|
||||
+ object->async_commands_callback.lpVtbl = &source_async_commands_callback_vtbl;
|
||||
object->ref = 1;
|
||||
object->type = type;
|
||||
object->byte_stream = bytestream;
|
||||
@@ -887,6 +1163,9 @@ static HRESULT media_source_constructor(IMFByteStream *bytestream, enum source_t
|
||||
IMFByteStream_AddRef(bytestream);
|
||||
@@ -1100,6 +1404,9 @@ static HRESULT media_source_constructor(IMFByteStream *bytestream, struct media_
|
||||
if (FAILED(hr = MFCreateEventQueue(&object->event_queue)))
|
||||
goto fail;
|
||||
|
||||
|
@ -1,21 +1,21 @@
|
||||
From 0911c65f0087651e7d84b447783dd48f50218450 Mon Sep 17 00:00:00 2001
|
||||
From 366946876d7a53f80d91749f290f511294415cf5 Mon Sep 17 00:00:00 2001
|
||||
From: Derek Lesho <dlesho@codeweavers.com>
|
||||
Date: Wed, 25 Mar 2020 10:43:03 -0500
|
||||
Subject: [PATCH] winegstreamer: Implement IMFMediaStream::RequestSample.
|
||||
Subject: [PATCH 20/52] winegstreamer: Implement IMFMediaStream::RequestSample.
|
||||
|
||||
Signed-off-by: Derek Lesho <dlesho@codeweavers.com>
|
||||
---
|
||||
dlls/mfplat/tests/mfplat.c | 4 -
|
||||
dlls/mfplat/tests/mfplat.c | 4 --
|
||||
dlls/winegstreamer/gst_private.h | 1 +
|
||||
dlls/winegstreamer/media_source.c | 118 ++++++++++++++++++++++++++++--
|
||||
dlls/winegstreamer/mfplat.c | 91 +++++++++++++++++++++++
|
||||
4 files changed, 205 insertions(+), 9 deletions(-)
|
||||
dlls/winegstreamer/media_source.c | 108 +++++++++++++++++++++++++++++-
|
||||
dlls/winegstreamer/mfplat.c | 90 +++++++++++++++++++++++++
|
||||
4 files changed, 198 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/dlls/mfplat/tests/mfplat.c b/dlls/mfplat/tests/mfplat.c
|
||||
index c26c40d531..a9408c998c 100644
|
||||
index e6a1694a11f..6dd2c3cbe96 100644
|
||||
--- a/dlls/mfplat/tests/mfplat.c
|
||||
+++ b/dlls/mfplat/tests/mfplat.c
|
||||
@@ -575,13 +575,10 @@ static void test_source_resolver(void)
|
||||
@@ -622,13 +622,10 @@ static void test_source_resolver(void)
|
||||
hr = IMFMediaStream_RequestSample(video_stream, NULL);
|
||||
if (i == sample_count)
|
||||
break;
|
||||
@ -29,7 +29,7 @@ index c26c40d531..a9408c998c 100644
|
||||
|
||||
for (i = 0; i < sample_count; ++i)
|
||||
{
|
||||
@@ -622,7 +619,6 @@ todo_wine
|
||||
@@ -669,7 +666,6 @@ todo_wine
|
||||
|
||||
get_event((IMFMediaEventGenerator *)mediasource, MEEndOfPresentation, NULL);
|
||||
|
||||
@ -38,22 +38,22 @@ index c26c40d531..a9408c998c 100644
|
||||
IMFMediaTypeHandler_Release(handler);
|
||||
IMFPresentationDescriptor_Release(descriptor);
|
||||
diff --git a/dlls/winegstreamer/gst_private.h b/dlls/winegstreamer/gst_private.h
|
||||
index 780cf1b02f..823e023f52 100644
|
||||
index d0628cc8df3..664733c74cd 100644
|
||||
--- a/dlls/winegstreamer/gst_private.h
|
||||
+++ b/dlls/winegstreamer/gst_private.h
|
||||
@@ -57,6 +57,7 @@ extern HRESULT mfplat_get_class_object(REFCLSID rclsid, REFIID riid, void **obj)
|
||||
|
||||
@@ -59,6 +59,7 @@ HRESULT winegstreamer_stream_handler_create(REFIID riid, void **obj) DECLSPEC_HI
|
||||
GstCaps *make_mf_compatible_caps(GstCaps *caps);
|
||||
IMFMediaType *mf_media_type_from_caps(GstCaps *caps);
|
||||
GstCaps *caps_from_mf_media_type(IMFMediaType *type);
|
||||
+IMFSample *mf_sample_from_gst_buffer(GstBuffer *in);
|
||||
|
||||
enum source_type
|
||||
{
|
||||
HRESULT winegstreamer_stream_handler_create(REFIID riid, void **obj) DECLSPEC_HIDDEN;
|
||||
|
||||
diff --git a/dlls/winegstreamer/media_source.c b/dlls/winegstreamer/media_source.c
|
||||
index a412786d33..46e85626a0 100644
|
||||
index c893664fbec..15ad1796563 100644
|
||||
--- a/dlls/winegstreamer/media_source.c
|
||||
+++ b/dlls/winegstreamer/media_source.c
|
||||
@@ -56,6 +56,7 @@ struct media_stream
|
||||
@@ -67,6 +67,7 @@ struct media_stream
|
||||
enum source_async_op
|
||||
{
|
||||
SOURCE_ASYNC_START,
|
||||
@ -61,7 +61,7 @@ index a412786d33..46e85626a0 100644
|
||||
};
|
||||
|
||||
struct source_async_command
|
||||
@@ -71,6 +72,11 @@ struct source_async_command
|
||||
@@ -82,6 +83,11 @@ struct source_async_command
|
||||
GUID format;
|
||||
PROPVARIANT position;
|
||||
} start;
|
||||
@ -73,17 +73,16 @@ index a412786d33..46e85626a0 100644
|
||||
} u;
|
||||
};
|
||||
|
||||
@@ -306,6 +312,78 @@ static HRESULT start_pipeline(struct media_source *source, struct source_async_c
|
||||
@@ -341,6 +347,78 @@ static HRESULT start_pipeline(struct media_source *source, struct source_async_c
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
+static void dispatch_end_of_presentation(struct media_source *source)
|
||||
+{
|
||||
+ PROPVARIANT empty = {.vt = VT_EMPTY};
|
||||
+ unsigned int i;
|
||||
+
|
||||
+ /* A stream has ended, check whether all have */
|
||||
+ for (i = 0; i < source->stream_count; i++)
|
||||
+ for (unsigned int i = 0; i < source->stream_count; i++)
|
||||
+ {
|
||||
+ struct media_stream *stream = source->streams[i];
|
||||
+
|
||||
@ -124,7 +123,7 @@ index a412786d33..46e85626a0 100644
|
||||
+ TRACE("sample info %s\n", debugstr_a(sample_info_str));
|
||||
+ g_free(sample_info_str);
|
||||
+ }
|
||||
+ TRACE("PTS = %lu DTS = %llu\n", GST_BUFFER_PTS(buffer), GST_BUFFER_DTS(buffer));
|
||||
+ TRACE("PTS = %lu DTS = %lu\n", GST_BUFFER_PTS(buffer), GST_BUFFER_DTS(buffer));
|
||||
+ }
|
||||
+
|
||||
+ sample = mf_sample_from_gst_buffer(buffer);
|
||||
@ -134,6 +133,7 @@ index a412786d33..46e85626a0 100644
|
||||
+ IMFSample_SetUnknown(sample, &MFSampleExtension_Token, token);
|
||||
+
|
||||
+ IMFMediaEventQueue_QueueEventParamUnk(stream->event_queue, MEMediaSample, &GUID_NULL, S_OK, (IUnknown *)sample);
|
||||
+ IMFSample_Release(sample);
|
||||
+ }
|
||||
+
|
||||
+ g_object_get(stream->appsink, "eos", &stream->eos, NULL);
|
||||
@ -152,7 +152,7 @@ index a412786d33..46e85626a0 100644
|
||||
static HRESULT WINAPI source_async_commands_Invoke(IMFAsyncCallback *iface, IMFAsyncResult *result)
|
||||
{
|
||||
struct media_source *source = impl_from_async_commands_callback_IMFAsyncCallback(iface);
|
||||
@@ -325,6 +403,9 @@ static HRESULT WINAPI source_async_commands_Invoke(IMFAsyncCallback *iface, IMFA
|
||||
@@ -360,6 +438,9 @@ static HRESULT WINAPI source_async_commands_Invoke(IMFAsyncCallback *iface, IMFA
|
||||
case SOURCE_ASYNC_START:
|
||||
start_pipeline(source, command);
|
||||
break;
|
||||
@ -162,26 +162,7 @@ index a412786d33..46e85626a0 100644
|
||||
default:
|
||||
;
|
||||
}
|
||||
@@ -347,12 +428,14 @@ static const IMFAsyncCallbackVtbl source_async_commands_callback_vtbl =
|
||||
static GstFlowReturn stream_new_sample(GstElement *appsink, gpointer user)
|
||||
{
|
||||
struct media_stream *stream = (struct media_stream *) user;
|
||||
- GstSample *discard_sample;
|
||||
|
||||
- TRACE("(%p) got sample\n", stream);
|
||||
+ if (stream->state == STREAM_INACTIVE)
|
||||
+ {
|
||||
+ GstSample *discard_sample;
|
||||
+ g_signal_emit_by_name(stream->appsink, "pull-sample", &discard_sample);
|
||||
+ gst_sample_unref(discard_sample);
|
||||
+ }
|
||||
|
||||
- g_signal_emit_by_name(stream->appsink, "pull-sample", &discard_sample);
|
||||
- gst_sample_unref(discard_sample);
|
||||
return GST_FLOW_OK;
|
||||
}
|
||||
|
||||
@@ -773,13 +856,37 @@ static HRESULT WINAPI media_stream_GetStreamDescriptor(IMFMediaStream* iface, IM
|
||||
@@ -694,13 +775,37 @@ static HRESULT WINAPI media_stream_GetStreamDescriptor(IMFMediaStream* iface, IM
|
||||
static HRESULT WINAPI media_stream_RequestSample(IMFMediaStream *iface, IUnknown *token)
|
||||
{
|
||||
struct media_stream *stream = impl_from_IMFMediaStream(iface);
|
||||
@ -194,7 +175,7 @@ index a412786d33..46e85626a0 100644
|
||||
return MF_E_SHUTDOWN;
|
||||
|
||||
- return E_NOTIMPL;
|
||||
+ if (stream->state == STREAM_INACTIVE || stream->state == STREAM_ENABLED)
|
||||
+ if (stream->state == STREAM_INACTIVE)
|
||||
+ {
|
||||
+ WARN("Stream isn't active\n");
|
||||
+ return MF_E_MEDIA_SOURCE_WRONGSTATE;
|
||||
@ -220,23 +201,22 @@ index a412786d33..46e85626a0 100644
|
||||
}
|
||||
|
||||
static const IMFMediaStreamVtbl media_stream_vtbl =
|
||||
@@ -901,6 +1008,7 @@ static HRESULT media_stream_constructor(struct media_source *source, GstPad *pad
|
||||
object->their_src = pad;
|
||||
@@ -873,6 +978,7 @@ static HRESULT new_media_stream(struct media_source *source, GstPad *pad, DWORD
|
||||
object->stream_id = stream_id;
|
||||
|
||||
object->state = STREAM_INACTIVE;
|
||||
object->state = STREAM_STUB;
|
||||
+ object->eos = FALSE;
|
||||
|
||||
if (FAILED(hr = MFCreateEventQueue(&object->event_queue)))
|
||||
goto fail;
|
||||
object->caps_event = CreateEventA(NULL, TRUE, FALSE, NULL);
|
||||
|
||||
diff --git a/dlls/winegstreamer/mfplat.c b/dlls/winegstreamer/mfplat.c
|
||||
index fa24bcb8d9..5ba9495939 100644
|
||||
index b291b21e8b5..839f337538d 100644
|
||||
--- a/dlls/winegstreamer/mfplat.c
|
||||
+++ b/dlls/winegstreamer/mfplat.c
|
||||
@@ -903,4 +903,95 @@ GstCaps *make_mf_compatible_caps(GstCaps *caps)
|
||||
}
|
||||
|
||||
return ret;
|
||||
+}
|
||||
@@ -1247,3 +1247,93 @@ GstCaps *caps_from_mf_media_type(IMFMediaType *type)
|
||||
FIXME("Unrecognized major type %s\n", debugstr_guid(&major_type));
|
||||
return NULL;
|
||||
}
|
||||
+
|
||||
+/* IMFSample = GstBuffer
|
||||
+ IMFBuffer = GstMemory */
|
||||
@ -253,7 +233,6 @@ index fa24bcb8d9..5ba9495939 100644
|
||||
+ LONGLONG duration, time;
|
||||
+ int buffer_count;
|
||||
+ HRESULT hr;
|
||||
+ unsigned int i;
|
||||
+
|
||||
+ if (FAILED(hr = MFCreateSample(&out)))
|
||||
+ goto fail;
|
||||
@ -269,7 +248,7 @@ index fa24bcb8d9..5ba9495939 100644
|
||||
+
|
||||
+ buffer_count = gst_buffer_n_memory(gst_buffer);
|
||||
+
|
||||
+ for (i = 0; i < buffer_count; i++)
|
||||
+ for (unsigned int i = 0; i < buffer_count; i++)
|
||||
+ {
|
||||
+ GstMemory *memory = gst_buffer_get_memory(gst_buffer, i);
|
||||
+ IMFMediaBuffer *mf_buffer = NULL;
|
||||
@ -327,8 +306,7 @@ index fa24bcb8d9..5ba9495939 100644
|
||||
+ ERR("Failed to copy IMFSample to GstBuffer, hr = %#x\n", hr);
|
||||
+ IMFSample_Release(out);
|
||||
+ return NULL;
|
||||
}
|
||||
\ No newline at end of file
|
||||
+}
|
||||
--
|
||||
2.28.0
|
||||
|
@ -1,179 +0,0 @@
|
||||
From cb6513ea1aafad23b5c16ddb6fc287e9a0bf8a0c Mon Sep 17 00:00:00 2001
|
||||
From: Derek Lesho <dlesho@codeweavers.com>
|
||||
Date: Tue, 31 Mar 2020 15:11:31 -0500
|
||||
Subject: [PATCH 20/54] winegstreamer: Insert parser into pipeline to rectify
|
||||
type differences.
|
||||
|
||||
It's probably better to use caps negotiation here, but this seemed simpler for now.
|
||||
|
||||
Signed-off-by: Derek Lesho <dlesho@codeweavers.com>
|
||||
---
|
||||
dlls/winegstreamer/media_source.c | 114 ++++++++++++++++++++++++------
|
||||
1 file changed, 91 insertions(+), 23 deletions(-)
|
||||
|
||||
diff --git a/dlls/winegstreamer/media_source.c b/dlls/winegstreamer/media_source.c
|
||||
index abf0cfd56f..cb247adcef 100644
|
||||
--- a/dlls/winegstreamer/media_source.c
|
||||
+++ b/dlls/winegstreamer/media_source.c
|
||||
@@ -578,7 +578,6 @@ static void source_stream_added(GstElement *element, GstPad *pad, gpointer user)
|
||||
{
|
||||
ERR("Error linking demuxer to stream %p, err = %d\n", existing_stream, ret);
|
||||
}
|
||||
- gst_element_sync_state_with_parent(existing_stream->appsink);
|
||||
|
||||
goto leave;
|
||||
}
|
||||
@@ -794,12 +793,99 @@ static const IMFMediaStreamVtbl media_stream_vtbl =
|
||||
media_stream_RequestSample
|
||||
};
|
||||
|
||||
+/* TODO: Use gstreamer caps negotiation */
|
||||
+/* connects their_src to appsink */
|
||||
+static HRESULT media_stream_align_with_mf(struct media_stream *stream, IMFMediaType **stream_type)
|
||||
+{
|
||||
+ GstCaps *source_caps = NULL;
|
||||
+ GstCaps *target_caps = NULL;
|
||||
+ GstElement *parser = NULL;
|
||||
+ HRESULT hr = E_FAIL;
|
||||
+
|
||||
+ if (!(source_caps = gst_pad_query_caps(stream->their_src, NULL)))
|
||||
+ goto done;
|
||||
+ if (!(target_caps = make_mf_compatible_caps(source_caps)))
|
||||
+ goto done;
|
||||
+
|
||||
+ if (TRACE_ON(mfplat))
|
||||
+ {
|
||||
+ gchar *source_caps_str = gst_caps_to_string(source_caps), *target_caps_str = gst_caps_to_string(target_caps);
|
||||
+ TRACE("source caps %s\ntarget caps %s\n", debugstr_a(source_caps_str), debugstr_a(target_caps_str));
|
||||
+ g_free(source_caps_str);
|
||||
+ g_free(target_caps_str);
|
||||
+ }
|
||||
+
|
||||
+ g_object_set(stream->appsink, "caps", target_caps, NULL);
|
||||
+
|
||||
+ if (!(gst_caps_is_equal(source_caps, target_caps)))
|
||||
+ {
|
||||
+ GList *parser_list_one, *parser_list_two;
|
||||
+ GstElementFactory *parser_factory;
|
||||
+
|
||||
+ parser_list_one = gst_element_factory_list_get_elements(GST_ELEMENT_FACTORY_TYPE_PARSER, 1);
|
||||
+
|
||||
+ parser_list_two = gst_element_factory_list_filter(parser_list_one, source_caps, GST_PAD_SINK, 0);
|
||||
+ gst_plugin_feature_list_free(parser_list_one);
|
||||
+ parser_list_one = parser_list_two;
|
||||
+
|
||||
+ parser_list_two = gst_element_factory_list_filter(parser_list_one, target_caps, GST_PAD_SRC, 0);
|
||||
+ gst_plugin_feature_list_free(parser_list_one);
|
||||
+ parser_list_one = parser_list_two;
|
||||
+
|
||||
+ if (!(g_list_length(parser_list_one)))
|
||||
+ {
|
||||
+ gst_plugin_feature_list_free(parser_list_one);
|
||||
+ ERR("Failed to find parser for stream\n");
|
||||
+ hr = E_FAIL;
|
||||
+ goto done;
|
||||
+ }
|
||||
+
|
||||
+ parser_factory = g_list_first(parser_list_one)->data;
|
||||
+ TRACE("Found parser %s.\n", GST_ELEMENT_NAME(parser_factory));
|
||||
+
|
||||
+ parser = gst_element_factory_create(parser_factory, NULL);
|
||||
+
|
||||
+ gst_plugin_feature_list_free(parser_list_one);
|
||||
+
|
||||
+ if (!parser)
|
||||
+ {
|
||||
+ hr = E_FAIL;
|
||||
+ goto done;
|
||||
+ }
|
||||
+
|
||||
+ gst_bin_add(GST_BIN(stream->parent_source->container), parser);
|
||||
+
|
||||
+ assert(gst_pad_link(stream->their_src, gst_element_get_static_pad(parser, "sink")) == GST_PAD_LINK_OK);
|
||||
+
|
||||
+ assert(gst_element_link(parser, stream->appsink));
|
||||
+
|
||||
+ gst_element_sync_state_with_parent(parser);
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ assert(gst_pad_link(stream->their_src, gst_element_get_static_pad(stream->appsink, "sink")) == GST_PAD_LINK_OK);
|
||||
+ }
|
||||
+
|
||||
+ stream->my_sink = gst_element_get_static_pad(parser ? parser : stream->appsink, "sink");
|
||||
+
|
||||
+ *stream_type = mf_media_type_from_caps(target_caps);
|
||||
+
|
||||
+ hr = S_OK;
|
||||
+
|
||||
+ done:
|
||||
+ if (source_caps)
|
||||
+ gst_caps_unref(source_caps);
|
||||
+ if (target_caps)
|
||||
+ gst_caps_unref(target_caps);
|
||||
+
|
||||
+ return hr;
|
||||
+}
|
||||
+
|
||||
static HRESULT media_stream_constructor(struct media_source *source, GstPad *pad, DWORD stream_id, struct media_stream **out_stream)
|
||||
{
|
||||
struct media_stream *object = heap_alloc_zero(sizeof(*object));
|
||||
IMFMediaTypeHandler *type_handler = NULL;
|
||||
IMFMediaType *stream_type = NULL;
|
||||
- GstCaps *caps = NULL;
|
||||
HRESULT hr;
|
||||
|
||||
TRACE("(%p %p)->(%p)\n", source, pad, out_stream);
|
||||
@@ -828,22 +914,9 @@ static HRESULT media_stream_constructor(struct media_source *source, GstPad *pad
|
||||
g_object_set(object->appsink, "async", FALSE, NULL); /* <- This allows us interact with the bin w/o prerolling */
|
||||
g_signal_connect(object->appsink, "new-sample", G_CALLBACK(stream_new_sample_wrapper), object);
|
||||
|
||||
- if (!(caps = gst_pad_query_caps(pad, NULL)))
|
||||
+ if (FAILED(hr = media_stream_align_with_mf(object, &stream_type)))
|
||||
goto fail;
|
||||
|
||||
- if (TRACE_ON(mfplat))
|
||||
- {
|
||||
- gchar *caps_str = gst_caps_to_string(caps);
|
||||
- TRACE("caps %s\n", debugstr_a(caps_str));
|
||||
- g_free(caps_str);
|
||||
- }
|
||||
-
|
||||
- if (!(stream_type = mf_media_type_from_caps(caps)))
|
||||
- goto fail;
|
||||
-
|
||||
- gst_caps_unref(caps);
|
||||
- caps = NULL;
|
||||
-
|
||||
if (FAILED(hr = MFCreateStreamDescriptor(stream_id, 1, &stream_type, &object->descriptor)))
|
||||
goto fail;
|
||||
|
||||
@@ -858,23 +931,18 @@ static HRESULT media_stream_constructor(struct media_source *source, GstPad *pad
|
||||
IMFMediaType_Release(stream_type);
|
||||
stream_type = NULL;
|
||||
|
||||
- object->my_sink = gst_element_get_static_pad(object->appsink, "sink");
|
||||
- gst_pad_set_element_private(pad, object);
|
||||
-
|
||||
- gst_pad_link(object->their_src, object->my_sink);
|
||||
+ gst_pad_set_element_private(object->their_src, object);
|
||||
|
||||
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);
|
||||
|
||||
- if (caps)
|
||||
- gst_caps_unref(caps);
|
||||
if (stream_type)
|
||||
IMFMediaType_Release(stream_type);
|
||||
if (type_handler)
|
||||
--
|
||||
2.28.0
|
||||
|
@ -1,7 +1,7 @@
|
||||
From ffaf4ac88336833aa64b83b9edcd0c23b3f1bdbb Mon Sep 17 00:00:00 2001
|
||||
From 625df79a05531671aeea9947ccd393372d32f6c1 Mon Sep 17 00:00:00 2001
|
||||
From: Derek Lesho <dlesho@codeweavers.com>
|
||||
Date: Tue, 31 Mar 2020 15:15:07 -0500
|
||||
Subject: [PATCH 22/54] winegstreamer: Implement
|
||||
Subject: [PATCH 21/52] winegstreamer: Implement
|
||||
IMFMediaSource::GetCharacteristics.
|
||||
|
||||
Signed-off-by: Derek Lesho <dlesho@codeweavers.com>
|
||||
@ -10,10 +10,10 @@ Signed-off-by: Derek Lesho <dlesho@codeweavers.com>
|
||||
1 file changed, 4 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/dlls/winegstreamer/media_source.c b/dlls/winegstreamer/media_source.c
|
||||
index b6f2fcc8fa..675ee9bd20 100644
|
||||
index 15ad1796563..b163472947b 100644
|
||||
--- a/dlls/winegstreamer/media_source.c
|
||||
+++ b/dlls/winegstreamer/media_source.c
|
||||
@@ -1160,12 +1160,14 @@ static HRESULT WINAPI media_source_GetCharacteristics(IMFMediaSource *iface, DWO
|
||||
@@ -1216,12 +1216,14 @@ static HRESULT WINAPI media_source_GetCharacteristics(IMFMediaSource *iface, DWO
|
||||
{
|
||||
struct media_source *source = impl_from_IMFMediaSource(iface);
|
||||
|
@ -1,8 +1,8 @@
|
||||
From 1d89dafdbc1c1d4df93121e41354d4607811a27b Mon Sep 17 00:00:00 2001
|
||||
From 516f67ab33c1b418fa621a059ce0a5576b92cac1 Mon Sep 17 00:00:00 2001
|
||||
From: Derek Lesho <dlesho@codeweavers.com>
|
||||
Date: Tue, 31 Mar 2020 15:15:50 -0500
|
||||
Subject: [PATCH] winegstreamer: Calculate the MF_PD_DURATION of the media
|
||||
source's PD.
|
||||
Subject: [PATCH 22/52] winegstreamer: Calculate the MF_PD_DURATION of the
|
||||
media source's PD.
|
||||
|
||||
Signed-off-by: Derek Lesho <dlesho@codeweavers.com>
|
||||
---
|
||||
@ -10,10 +10,10 @@ Signed-off-by: Derek Lesho <dlesho@codeweavers.com>
|
||||
1 file changed, 40 insertions(+)
|
||||
|
||||
diff --git a/dlls/winegstreamer/media_source.c b/dlls/winegstreamer/media_source.c
|
||||
index 230aa8a9f6..2039115dfe 100644
|
||||
index b163472947b..9c546bc4ac5 100644
|
||||
--- a/dlls/winegstreamer/media_source.c
|
||||
+++ b/dlls/winegstreamer/media_source.c
|
||||
@@ -1430,6 +1430,46 @@ static HRESULT media_source_constructor(IMFByteStream *bytestream, enum source_t
|
||||
@@ -1594,6 +1594,46 @@ static HRESULT media_source_constructor(IMFByteStream *bytestream, struct media_
|
||||
heap_free(descriptors);
|
||||
descriptors = NULL;
|
||||
|
||||
@ -34,7 +34,7 @@ index 230aa8a9f6..2039115dfe 100644
|
||||
+ IMFAttributes_Release(byte_stream_attributes);
|
||||
+ }
|
||||
+
|
||||
+ for (i = 0; i < object->stream_count; i++)
|
||||
+ for (unsigned int i = 0; i < object->stream_count; i++)
|
||||
+ {
|
||||
+ GstQuery *query = gst_query_new_duration(GST_FORMAT_TIME);
|
||||
+ if (gst_pad_query(object->streams[i]->their_src, query))
|
||||
@ -57,9 +57,9 @@ index 230aa8a9f6..2039115dfe 100644
|
||||
+ IMFPresentationDescriptor_SetUINT64(object->pres_desc, &MF_PD_DURATION, total_pres_time / 100);
|
||||
+ }
|
||||
+
|
||||
gst_element_set_state(object->container, GST_STATE_READY);
|
||||
|
||||
object->state = SOURCE_STOPPED;
|
||||
|
||||
*out_media_source = object;
|
||||
--
|
||||
2.28.0
|
||||
|
@ -1,7 +1,7 @@
|
||||
From 97507c173539685376d1cad7782529b8394d7cd0 Mon Sep 17 00:00:00 2001
|
||||
From 7824e15960e00ffb11adae1a1e683aa1487f6317 Mon Sep 17 00:00:00 2001
|
||||
From: Derek Lesho <dlesho@codeweavers.com>
|
||||
Date: Wed, 29 Jan 2020 15:37:39 -0600
|
||||
Subject: [PATCH 24/54] tools: Add support for multiple parent directories.
|
||||
Subject: [PATCH 23/52] tools: Add support for multiple parent directories.
|
||||
|
||||
Signed-off-by: Derek Lesho <dlesho@codeweavers.com>
|
||||
---
|
||||
@ -10,7 +10,7 @@ Signed-off-by: Derek Lesho <dlesho@codeweavers.com>
|
||||
2 files changed, 49 insertions(+), 26 deletions(-)
|
||||
|
||||
diff --git a/tools/make_makefiles b/tools/make_makefiles
|
||||
index c18fa90e2d..1e34a280a4 100755
|
||||
index c18fa90e2d3..1e34a280a40 100755
|
||||
--- a/tools/make_makefiles
|
||||
+++ b/tools/make_makefiles
|
||||
@@ -231,14 +231,14 @@ sub parse_makefile($)
|
||||
@ -91,17 +91,17 @@ index c18fa90e2d..1e34a280a4 100755
|
||||
}
|
||||
|
||||
diff --git a/tools/makedep.c b/tools/makedep.c
|
||||
index 825458156f..f76747e00a 100644
|
||||
index 4bd20d469d6..a67add38afa 100644
|
||||
--- a/tools/makedep.c
|
||||
+++ b/tools/makedep.c
|
||||
@@ -183,6 +183,7 @@ struct makefile
|
||||
struct strarray install_lib;
|
||||
@@ -184,6 +184,7 @@ struct makefile
|
||||
struct strarray install_dev;
|
||||
struct strarray extra_targets;
|
||||
+ struct strarray parent_dirs;
|
||||
struct strarray extra_imports;
|
||||
+ struct strarray parent_dirs;
|
||||
struct list sources;
|
||||
struct list includes;
|
||||
const char *base_dir;
|
||||
@@ -191,7 +192,6 @@ struct makefile
|
||||
const char *obj_dir;
|
||||
const char *top_src_dir;
|
||||
@ -140,7 +140,7 @@ index 825458156f..f76747e00a 100644
|
||||
}
|
||||
|
||||
if (ret) *filename = src_dir_path( make, path );
|
||||
@@ -4271,13 +4280,13 @@ static void load_sources( struct makefile *make )
|
||||
@@ -4275,13 +4284,13 @@ static void load_sources( struct makefile *make )
|
||||
strarray_set_value( &make->vars, "top_srcdir", top_src_dir_path( make, "" ));
|
||||
strarray_set_value( &make->vars, "srcdir", src_dir_path( make, "" ));
|
||||
|
||||
@ -155,7 +155,7 @@ index 825458156f..f76747e00a 100644
|
||||
make->programs = get_expanded_make_var_array( make, "PROGRAMS" );
|
||||
make->scripts = get_expanded_make_var_array( make, "SCRIPTS" );
|
||||
make->imports = get_expanded_make_var_array( make, "IMPORTS" );
|
||||
@@ -4322,8 +4331,11 @@ static void load_sources( struct makefile *make )
|
||||
@@ -4326,8 +4335,11 @@ static void load_sources( struct makefile *make )
|
||||
strarray_add( &make->include_args, strmake( "-I%s", obj_dir_path( make, "" )));
|
||||
if (make->src_dir)
|
||||
strarray_add( &make->include_args, strmake( "-I%s", make->src_dir ));
|
@ -1,7 +1,7 @@
|
||||
From e59d4b4a0867077b49e9172f2d27faeea54835d0 Mon Sep 17 00:00:00 2001
|
||||
From 8b0d448ce8e7c3698f7b77dd687fea0676c392c7 Mon Sep 17 00:00:00 2001
|
||||
From: Derek Lesho <dlesho@codeweavers.com>
|
||||
Date: Wed, 29 Jan 2020 15:30:49 -0600
|
||||
Subject: [PATCH 25/54] mf: Introduce handler helper.
|
||||
Subject: [PATCH 24/52] mf: Introduce handler helper.
|
||||
|
||||
Signed-off-by: Derek Lesho <dlesho@codeweavers.com>
|
||||
---
|
||||
@ -16,20 +16,20 @@ Signed-off-by: Derek Lesho <dlesho@codeweavers.com>
|
||||
create mode 100644 dlls/mf/handler.h
|
||||
|
||||
diff --git a/dlls/mf/Makefile.in b/dlls/mf/Makefile.in
|
||||
index b64cdb4a64..f5261e64cd 100644
|
||||
index b64cdb4a64d..c0a4a876e0b 100644
|
||||
--- a/dlls/mf/Makefile.in
|
||||
+++ b/dlls/mf/Makefile.in
|
||||
@@ -5,6 +5,7 @@ IMPORTS = advapi32 mfplat ole32 uuid mfuuid strmiids
|
||||
EXTRADLLFLAGS = -mno-cygwin
|
||||
@@ -6,6 +6,7 @@ EXTRADLLFLAGS = -mno-cygwin
|
||||
|
||||
C_SRCS = \
|
||||
+ handler.c \
|
||||
evr.c \
|
||||
+ handler.c \
|
||||
main.c \
|
||||
samplegrabber.c \
|
||||
sar.c \
|
||||
diff --git a/dlls/mf/handler.c b/dlls/mf/handler.c
|
||||
new file mode 100644
|
||||
index 0000000000..da40049377
|
||||
index 00000000000..da40049377e
|
||||
--- /dev/null
|
||||
+++ b/dlls/mf/handler.c
|
||||
@@ -0,0 +1,360 @@
|
||||
@ -396,7 +396,7 @@ index 0000000000..da40049377
|
||||
\ No newline at end of file
|
||||
diff --git a/dlls/mf/handler.h b/dlls/mf/handler.h
|
||||
new file mode 100644
|
||||
index 0000000000..fbebd26e8d
|
||||
index 00000000000..fbebd26e8d0
|
||||
--- /dev/null
|
||||
+++ b/dlls/mf/handler.h
|
||||
@@ -0,0 +1,30 @@
|
||||
@ -432,7 +432,7 @@ index 0000000000..fbebd26e8d
|
||||
+HRESULT handler_cancel_object_creation(struct handler *handler, IUnknown *cancel_cookie);
|
||||
\ No newline at end of file
|
||||
diff --git a/dlls/mf/main.c b/dlls/mf/main.c
|
||||
index 5326425813..ebcaef4cad 100644
|
||||
index 53264258137..ebcaef4cad3 100644
|
||||
--- a/dlls/mf/main.c
|
||||
+++ b/dlls/mf/main.c
|
||||
@@ -27,6 +27,7 @@
|
||||
@ -913,7 +913,7 @@ index 5326425813..ebcaef4cad 100644
|
||||
return hr;
|
||||
}
|
||||
diff --git a/dlls/winegstreamer/Makefile.in b/dlls/winegstreamer/Makefile.in
|
||||
index e578d194f7..f2e8749445 100644
|
||||
index e578d194f7f..f2e87494459 100644
|
||||
--- a/dlls/winegstreamer/Makefile.in
|
||||
+++ b/dlls/winegstreamer/Makefile.in
|
||||
@@ -3,12 +3,13 @@ IMPORTS = strmiids uuid ole32 mfuuid
|
||||
@ -932,10 +932,10 @@ index e578d194f7..f2e8749445 100644
|
||||
media_source.c \
|
||||
mediatype.c \
|
||||
diff --git a/dlls/winegstreamer/media_source.c b/dlls/winegstreamer/media_source.c
|
||||
index 5811baf0c0..c30b5e9ef0 100644
|
||||
index 9c546bc4ac5..ca799446ad8 100644
|
||||
--- a/dlls/winegstreamer/media_source.c
|
||||
+++ b/dlls/winegstreamer/media_source.c
|
||||
@@ -4,6 +4,7 @@
|
||||
@@ -23,6 +23,7 @@
|
||||
|
||||
#include "gst_private.h"
|
||||
#include "gst_cbs.h"
|
||||
@ -943,11 +943,11 @@ index 5811baf0c0..c30b5e9ef0 100644
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdarg.h>
|
||||
@@ -1485,22 +1486,12 @@ static HRESULT media_source_constructor(IMFByteStream *bytestream, enum source_t
|
||||
@@ -1648,21 +1649,11 @@ static HRESULT media_source_constructor(IMFByteStream *bytestream, struct media_
|
||||
return hr;
|
||||
}
|
||||
|
||||
/* IMFByteStreamHandler */
|
||||
|
||||
-struct container_stream_handler_result
|
||||
-struct winegstreamer_stream_handler_result
|
||||
-{
|
||||
- struct list entry;
|
||||
- IMFAsyncResult *result;
|
||||
@ -955,43 +955,42 @@ index 5811baf0c0..c30b5e9ef0 100644
|
||||
- IUnknown *object;
|
||||
-};
|
||||
-
|
||||
struct container_stream_handler
|
||||
struct winegstreamer_stream_handler
|
||||
{
|
||||
IMFByteStreamHandler IMFByteStreamHandler_iface;
|
||||
- IMFAsyncCallback IMFAsyncCallback_iface;
|
||||
LONG refcount;
|
||||
enum source_type type;
|
||||
- struct list results;
|
||||
- CRITICAL_SECTION cs;
|
||||
+ struct handler handler;
|
||||
};
|
||||
|
||||
static struct container_stream_handler *impl_from_IMFByteStreamHandler(IMFByteStreamHandler *iface)
|
||||
@@ -1508,11 +1499,6 @@ static struct container_stream_handler *impl_from_IMFByteStreamHandler(IMFByteSt
|
||||
return CONTAINING_RECORD(iface, struct container_stream_handler, IMFByteStreamHandler_iface);
|
||||
static struct winegstreamer_stream_handler *impl_from_IMFByteStreamHandler(IMFByteStreamHandler *iface)
|
||||
@@ -1670,11 +1661,6 @@ static struct winegstreamer_stream_handler *impl_from_IMFByteStreamHandler(IMFBy
|
||||
return CONTAINING_RECORD(iface, struct winegstreamer_stream_handler, IMFByteStreamHandler_iface);
|
||||
}
|
||||
|
||||
-static struct container_stream_handler *impl_from_IMFAsyncCallback(IMFAsyncCallback *iface)
|
||||
-static struct winegstreamer_stream_handler *impl_from_IMFAsyncCallback(IMFAsyncCallback *iface)
|
||||
-{
|
||||
- return CONTAINING_RECORD(iface, struct container_stream_handler, IMFAsyncCallback_iface);
|
||||
- return CONTAINING_RECORD(iface, struct winegstreamer_stream_handler, IMFAsyncCallback_iface);
|
||||
-}
|
||||
-
|
||||
static HRESULT WINAPI container_stream_handler_QueryInterface(IMFByteStreamHandler *iface, REFIID riid, void **obj)
|
||||
static HRESULT WINAPI winegstreamer_stream_handler_QueryInterface(IMFByteStreamHandler *iface, REFIID riid, void **obj)
|
||||
{
|
||||
TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), obj);
|
||||
@@ -1542,248 +1528,44 @@ static ULONG WINAPI container_stream_handler_AddRef(IMFByteStreamHandler *iface)
|
||||
@@ -1704,248 +1690,44 @@ static ULONG WINAPI winegstreamer_stream_handler_AddRef(IMFByteStreamHandler *if
|
||||
|
||||
static ULONG WINAPI container_stream_handler_Release(IMFByteStreamHandler *iface)
|
||||
static ULONG WINAPI winegstreamer_stream_handler_Release(IMFByteStreamHandler *iface)
|
||||
{
|
||||
- struct container_stream_handler *handler = impl_from_IMFByteStreamHandler(iface);
|
||||
- struct winegstreamer_stream_handler *handler = impl_from_IMFByteStreamHandler(iface);
|
||||
- ULONG refcount = InterlockedDecrement(&handler->refcount);
|
||||
- struct container_stream_handler_result *result, *next;
|
||||
- struct winegstreamer_stream_handler_result *result, *next;
|
||||
-
|
||||
- TRACE("%p, refcount %u.\n", iface, refcount);
|
||||
-
|
||||
- if (!refcount)
|
||||
- {
|
||||
- LIST_FOR_EACH_ENTRY_SAFE(result, next, &handler->results, struct container_stream_handler_result, entry)
|
||||
- LIST_FOR_EACH_ENTRY_SAFE(result, next, &handler->results, struct winegstreamer_stream_handler_result, entry)
|
||||
- {
|
||||
- list_remove(&result->entry);
|
||||
- IMFAsyncResult_Release(result->result);
|
||||
@ -1052,7 +1051,7 @@ index 5811baf0c0..c30b5e9ef0 100644
|
||||
-{
|
||||
- struct create_object_context *context = impl_from_IUnknown(iface);
|
||||
- ULONG refcount = InterlockedDecrement(&context->refcount);
|
||||
+ struct container_stream_handler *this = impl_from_IMFByteStreamHandler(iface);
|
||||
+ struct winegstreamer_stream_handler *this = impl_from_IMFByteStreamHandler(iface);
|
||||
+ ULONG refcount = InterlockedDecrement(&this->refcount);
|
||||
|
||||
TRACE("%p, refcount %u.\n", iface, refcount);
|
||||
@ -1097,10 +1096,10 @@ index 5811baf0c0..c30b5e9ef0 100644
|
||||
- return ret;
|
||||
-}
|
||||
-
|
||||
static HRESULT WINAPI container_stream_handler_BeginCreateObject(IMFByteStreamHandler *iface, IMFByteStream *stream, const WCHAR *url, DWORD flags,
|
||||
static HRESULT WINAPI winegstreamer_stream_handler_BeginCreateObject(IMFByteStreamHandler *iface, IMFByteStream *stream, const WCHAR *url, DWORD flags,
|
||||
IPropertyStore *props, IUnknown **cancel_cookie, IMFAsyncCallback *callback, IUnknown *state)
|
||||
{
|
||||
struct container_stream_handler *this = impl_from_IMFByteStreamHandler(iface);
|
||||
struct winegstreamer_stream_handler *this = impl_from_IMFByteStreamHandler(iface);
|
||||
- struct create_object_context *context;
|
||||
- IMFAsyncResult *caller, *item;
|
||||
- HRESULT hr;
|
||||
@ -1159,18 +1158,18 @@ index 5811baf0c0..c30b5e9ef0 100644
|
||||
+ return handler_begin_create_object(&this->handler, stream, url, flags, props, cancel_cookie, callback, state);
|
||||
}
|
||||
|
||||
static HRESULT WINAPI container_stream_handler_EndCreateObject(IMFByteStreamHandler *iface, IMFAsyncResult *result,
|
||||
static HRESULT WINAPI winegstreamer_stream_handler_EndCreateObject(IMFByteStreamHandler *iface, IMFAsyncResult *result,
|
||||
MF_OBJECT_TYPE *obj_type, IUnknown **object)
|
||||
{
|
||||
struct container_stream_handler *this = impl_from_IMFByteStreamHandler(iface);
|
||||
- struct container_stream_handler_result *found = NULL, *cur;
|
||||
struct winegstreamer_stream_handler *this = impl_from_IMFByteStreamHandler(iface);
|
||||
- struct winegstreamer_stream_handler_result *found = NULL, *cur;
|
||||
- HRESULT hr;
|
||||
|
||||
TRACE("%p, %p, %p, %p.\n", iface, result, obj_type, object);
|
||||
-
|
||||
- EnterCriticalSection(&this->cs);
|
||||
-
|
||||
- LIST_FOR_EACH_ENTRY(cur, &this->results, struct container_stream_handler_result, entry)
|
||||
- LIST_FOR_EACH_ENTRY(cur, &this->results, struct winegstreamer_stream_handler_result, entry)
|
||||
- {
|
||||
- if (result == cur->result)
|
||||
- {
|
||||
@ -1201,16 +1200,16 @@ index 5811baf0c0..c30b5e9ef0 100644
|
||||
+ return handler_end_create_object(&this->handler, result, obj_type, object);
|
||||
}
|
||||
|
||||
static HRESULT WINAPI container_stream_handler_CancelObjectCreation(IMFByteStreamHandler *iface, IUnknown *cancel_cookie)
|
||||
static HRESULT WINAPI winegstreamer_stream_handler_CancelObjectCreation(IMFByteStreamHandler *iface, IUnknown *cancel_cookie)
|
||||
{
|
||||
struct container_stream_handler *this = impl_from_IMFByteStreamHandler(iface);
|
||||
- struct container_stream_handler_result *found = NULL, *cur;
|
||||
struct winegstreamer_stream_handler *this = impl_from_IMFByteStreamHandler(iface);
|
||||
- struct winegstreamer_stream_handler_result *found = NULL, *cur;
|
||||
|
||||
TRACE("%p, %p.\n", iface, cancel_cookie);
|
||||
-
|
||||
- EnterCriticalSection(&this->cs);
|
||||
-
|
||||
- LIST_FOR_EACH_ENTRY(cur, &this->results, struct container_stream_handler_result, entry)
|
||||
- LIST_FOR_EACH_ENTRY(cur, &this->results, struct winegstreamer_stream_handler_result, entry)
|
||||
- {
|
||||
- if (cancel_cookie == (IUnknown *)cur->result)
|
||||
- {
|
||||
@ -1234,12 +1233,12 @@ index 5811baf0c0..c30b5e9ef0 100644
|
||||
+ return handler_cancel_object_creation(&this->handler, cancel_cookie);
|
||||
}
|
||||
|
||||
static HRESULT WINAPI container_stream_handler_GetMaxNumberOfBytesRequiredForResolution(IMFByteStreamHandler *iface, QWORD *bytes)
|
||||
@@ -1803,47 +1585,16 @@ static const IMFByteStreamHandlerVtbl container_stream_handler_vtbl =
|
||||
container_stream_handler_GetMaxNumberOfBytesRequiredForResolution,
|
||||
static HRESULT WINAPI winegstreamer_stream_handler_GetMaxNumberOfBytesRequiredForResolution(IMFByteStreamHandler *iface, QWORD *bytes)
|
||||
@@ -1965,47 +1747,16 @@ static const IMFByteStreamHandlerVtbl winegstreamer_stream_handler_vtbl =
|
||||
winegstreamer_stream_handler_GetMaxNumberOfBytesRequiredForResolution,
|
||||
};
|
||||
|
||||
-static HRESULT WINAPI container_stream_handler_callback_QueryInterface(IMFAsyncCallback *iface, REFIID riid, void **obj)
|
||||
-static HRESULT WINAPI winegstreamer_stream_handler_callback_QueryInterface(IMFAsyncCallback *iface, REFIID riid, void **obj)
|
||||
-{
|
||||
- if (IsEqualIID(riid, &IID_IMFAsyncCallback) ||
|
||||
- IsEqualIID(riid, &IID_IUnknown))
|
||||
@ -1254,25 +1253,25 @@ index 5811baf0c0..c30b5e9ef0 100644
|
||||
- return E_NOINTERFACE;
|
||||
-}
|
||||
-
|
||||
-static ULONG WINAPI container_stream_handler_callback_AddRef(IMFAsyncCallback *iface)
|
||||
-static ULONG WINAPI winegstreamer_stream_handler_callback_AddRef(IMFAsyncCallback *iface)
|
||||
-{
|
||||
- struct container_stream_handler *handler = impl_from_IMFAsyncCallback(iface);
|
||||
- struct winegstreamer_stream_handler *handler = impl_from_IMFAsyncCallback(iface);
|
||||
- return IMFByteStreamHandler_AddRef(&handler->IMFByteStreamHandler_iface);
|
||||
-}
|
||||
-
|
||||
-static ULONG WINAPI container_stream_handler_callback_Release(IMFAsyncCallback *iface)
|
||||
-static ULONG WINAPI winegstreamer_stream_handler_callback_Release(IMFAsyncCallback *iface)
|
||||
-{
|
||||
- struct container_stream_handler *handler = impl_from_IMFAsyncCallback(iface);
|
||||
- struct winegstreamer_stream_handler *handler = impl_from_IMFAsyncCallback(iface);
|
||||
- return IMFByteStreamHandler_Release(&handler->IMFByteStreamHandler_iface);
|
||||
-}
|
||||
-
|
||||
-static HRESULT WINAPI container_stream_handler_callback_GetParameters(IMFAsyncCallback *iface, DWORD *flags, DWORD *queue)
|
||||
-static HRESULT WINAPI winegstreamer_stream_handler_callback_GetParameters(IMFAsyncCallback *iface, DWORD *flags, DWORD *queue)
|
||||
-{
|
||||
- return E_NOTIMPL;
|
||||
-}
|
||||
-
|
||||
-static HRESULT container_stream_handler_create_object(struct container_stream_handler *This, WCHAR *url, IMFByteStream *stream, DWORD flags,
|
||||
+static HRESULT container_stream_handler_create_object(struct handler *handler, WCHAR *url, IMFByteStream *stream, DWORD flags,
|
||||
-static HRESULT winegstreamer_stream_handler_create_object(struct winegstreamer_stream_handler *This, WCHAR *url, IMFByteStream *stream, DWORD flags,
|
||||
+static HRESULT winegstreamer_stream_handler_create_object(struct handler *handler, WCHAR *url, IMFByteStream *stream, DWORD flags,
|
||||
IPropertyStore *props, IUnknown **out_object, MF_OBJECT_TYPE *out_obj_type)
|
||||
{
|
||||
- TRACE("(%p %s %p %u %p %p %p)\n", This, debugstr_w(url), stream, flags, props, out_object, out_obj_type);
|
||||
@ -1282,18 +1281,18 @@ index 5811baf0c0..c30b5e9ef0 100644
|
||||
{
|
||||
HRESULT hr;
|
||||
struct media_source *new_source;
|
||||
+ struct container_stream_handler *This = CONTAINING_RECORD(handler, struct container_stream_handler, handler);
|
||||
+ struct winegstreamer_stream_handler *This = CONTAINING_RECORD(handler, struct winegstreamer_stream_handler, handler);
|
||||
|
||||
if (FAILED(hr = media_source_constructor(stream, This->type, &new_source)))
|
||||
if (FAILED(hr = media_source_constructor(stream, &new_source)))
|
||||
return hr;
|
||||
@@ -1862,64 +1613,6 @@ static HRESULT container_stream_handler_create_object(struct container_stream_ha
|
||||
@@ -2024,64 +1775,6 @@ static HRESULT winegstreamer_stream_handler_create_object(struct winegstreamer_s
|
||||
}
|
||||
}
|
||||
|
||||
-static HRESULT WINAPI container_stream_handler_callback_Invoke(IMFAsyncCallback *iface, IMFAsyncResult *result)
|
||||
-static HRESULT WINAPI winegstreamer_stream_handler_callback_Invoke(IMFAsyncCallback *iface, IMFAsyncResult *result)
|
||||
-{
|
||||
- struct container_stream_handler *handler = impl_from_IMFAsyncCallback(iface);
|
||||
- struct container_stream_handler_result *handler_result;
|
||||
- struct winegstreamer_stream_handler *handler = impl_from_IMFAsyncCallback(iface);
|
||||
- struct winegstreamer_stream_handler_result *handler_result;
|
||||
- MF_OBJECT_TYPE obj_type = MF_OBJECT_INVALID;
|
||||
- IUnknown *object = NULL, *context_object;
|
||||
- struct create_object_context *context;
|
||||
@ -1310,7 +1309,7 @@ index 5811baf0c0..c30b5e9ef0 100644
|
||||
-
|
||||
- context = impl_from_IUnknown(context_object);
|
||||
-
|
||||
- hr = container_stream_handler_create_object(handler, context->url, context->stream, context->flags, context->props, &object, &obj_type);
|
||||
- hr = winegstreamer_stream_handler_create_object(handler, context->url, context->stream, context->flags, context->props, &object, &obj_type);
|
||||
-
|
||||
- handler_result = heap_alloc(sizeof(*handler_result));
|
||||
- if (handler_result)
|
||||
@ -1339,29 +1338,28 @@ index 5811baf0c0..c30b5e9ef0 100644
|
||||
- return S_OK;
|
||||
-}
|
||||
-
|
||||
-static const IMFAsyncCallbackVtbl container_stream_handler_callback_vtbl =
|
||||
-static const IMFAsyncCallbackVtbl winegstreamer_stream_handler_callback_vtbl =
|
||||
-{
|
||||
- container_stream_handler_callback_QueryInterface,
|
||||
- container_stream_handler_callback_AddRef,
|
||||
- container_stream_handler_callback_Release,
|
||||
- container_stream_handler_callback_GetParameters,
|
||||
- container_stream_handler_callback_Invoke,
|
||||
- winegstreamer_stream_handler_callback_QueryInterface,
|
||||
- winegstreamer_stream_handler_callback_AddRef,
|
||||
- winegstreamer_stream_handler_callback_Release,
|
||||
- winegstreamer_stream_handler_callback_GetParameters,
|
||||
- winegstreamer_stream_handler_callback_Invoke,
|
||||
-};
|
||||
-
|
||||
HRESULT container_stream_handler_construct(REFIID riid, void **obj, enum source_type type)
|
||||
HRESULT winegstreamer_stream_handler_create(REFIID riid, void **obj)
|
||||
{
|
||||
struct container_stream_handler *this;
|
||||
@@ -1931,12 +1624,10 @@ HRESULT container_stream_handler_construct(REFIID riid, void **obj, enum source_
|
||||
struct winegstreamer_stream_handler *this;
|
||||
@@ -2093,11 +1786,9 @@ HRESULT winegstreamer_stream_handler_create(REFIID riid, void **obj)
|
||||
if (!this)
|
||||
return E_OUTOFMEMORY;
|
||||
|
||||
- list_init(&this->results);
|
||||
- InitializeCriticalSection(&this->cs);
|
||||
+ handler_construct(&this->handler, container_stream_handler_create_object);
|
||||
+ handler_construct(&this->handler, winegstreamer_stream_handler_create_object);
|
||||
|
||||
this->type = type;
|
||||
this->IMFByteStreamHandler_iface.lpVtbl = &container_stream_handler_vtbl;
|
||||
- this->IMFAsyncCallback_iface.lpVtbl = &container_stream_handler_callback_vtbl;
|
||||
this->IMFByteStreamHandler_iface.lpVtbl = &winegstreamer_stream_handler_vtbl;
|
||||
- this->IMFAsyncCallback_iface.lpVtbl = &winegstreamer_stream_handler_callback_vtbl;
|
||||
this->refcount = 1;
|
||||
|
||||
hr = IMFByteStreamHandler_QueryInterface(&this->IMFByteStreamHandler_iface, riid, obj);
|
@ -1,35 +1,34 @@
|
||||
From e7f979743dec4e3753b7625a728c003625c24af2 Mon Sep 17 00:00:00 2001
|
||||
From bc33134566348dbd02788a8a203cd0b815056c06 Mon Sep 17 00:00:00 2001
|
||||
From: Derek Lesho <dlesho@codeweavers.com>
|
||||
Date: Wed, 25 Mar 2020 10:43:27 -0500
|
||||
Subject: [PATCH] Introduce IMFSample -> GstBuffer converter.
|
||||
Subject: [PATCH 25/52] Introduce IMFSample -> GstBuffer converter.
|
||||
|
||||
Signed-off-by: Derek Lesho <dlesho@codeweavers.com>
|
||||
---
|
||||
dlls/winegstreamer/gst_private.h | 1 +
|
||||
dlls/winegstreamer/mfplat.c | 75 ++++++++++++++++++++++++++++++++
|
||||
2 files changed, 76 insertions(+)
|
||||
dlls/winegstreamer/mfplat.c | 74 ++++++++++++++++++++++++++++++++
|
||||
2 files changed, 75 insertions(+)
|
||||
|
||||
diff --git a/dlls/winegstreamer/gst_private.h b/dlls/winegstreamer/gst_private.h
|
||||
index 20d3beef02..258df0d040 100644
|
||||
index 664733c74cd..d0737442cc3 100644
|
||||
--- a/dlls/winegstreamer/gst_private.h
|
||||
+++ b/dlls/winegstreamer/gst_private.h
|
||||
@@ -59,6 +59,7 @@ GstCaps *make_mf_compatible_caps(GstCaps *caps);
|
||||
@@ -60,6 +60,7 @@ GstCaps *make_mf_compatible_caps(GstCaps *caps);
|
||||
IMFMediaType *mf_media_type_from_caps(GstCaps *caps);
|
||||
GstCaps *caps_from_mf_media_type(IMFMediaType *type);
|
||||
IMFSample *mf_sample_from_gst_buffer(GstBuffer *in);
|
||||
+GstBuffer *gst_buffer_from_mf_sample(IMFSample *in);
|
||||
|
||||
enum source_type
|
||||
{
|
||||
HRESULT winegstreamer_stream_handler_create(REFIID riid, void **obj) DECLSPEC_HIDDEN;
|
||||
|
||||
diff --git a/dlls/winegstreamer/mfplat.c b/dlls/winegstreamer/mfplat.c
|
||||
index 8bffb6387e..fe8ba885e9 100644
|
||||
index 839f337538d..ae5dcc31825 100644
|
||||
--- a/dlls/winegstreamer/mfplat.c
|
||||
+++ b/dlls/winegstreamer/mfplat.c
|
||||
@@ -1299,4 +1299,79 @@ IMFSample* mf_sample_from_gst_buffer(GstBuffer *gst_buffer)
|
||||
ERR("Failed to copy IMFSample to GstBuffer, hr = %#x\n", hr);
|
||||
@@ -1337,3 +1337,77 @@ IMFSample* mf_sample_from_gst_buffer(GstBuffer *gst_buffer)
|
||||
IMFSample_Release(out);
|
||||
return NULL;
|
||||
+}
|
||||
}
|
||||
+
|
||||
+GstBuffer* gst_buffer_from_mf_sample(IMFSample *mf_sample)
|
||||
+{
|
||||
@ -38,7 +37,6 @@ index 8bffb6387e..fe8ba885e9 100644
|
||||
+ LONGLONG duration, time;
|
||||
+ DWORD buffer_count;
|
||||
+ HRESULT hr;
|
||||
+ unsigned int i;
|
||||
+
|
||||
+ if (FAILED(hr = IMFSample_GetSampleDuration(mf_sample, &duration)))
|
||||
+ goto fail;
|
||||
@ -52,7 +50,7 @@ index 8bffb6387e..fe8ba885e9 100644
|
||||
+ if (FAILED(hr = IMFSample_GetBufferCount(mf_sample, &buffer_count)))
|
||||
+ goto fail;
|
||||
+
|
||||
+ for (i = 0; i < buffer_count; i++)
|
||||
+ for (unsigned int i = 0; i < buffer_count; i++)
|
||||
+ {
|
||||
+ DWORD buffer_max_size, buffer_size;
|
||||
+ GstMapInfo map_info;
|
||||
@ -104,8 +102,7 @@ index 8bffb6387e..fe8ba885e9 100644
|
||||
+ IMFMediaBuffer_Release(mf_buffer);
|
||||
+ gst_buffer_unref(out);
|
||||
+ return NULL;
|
||||
}
|
||||
\ No newline at end of file
|
||||
+}
|
||||
--
|
||||
2.28.0
|
||||
|
@ -1,251 +1,212 @@
|
||||
From 8d1b452fa4bd1967187eb82e12b95f3289ab514b Mon Sep 17 00:00:00 2001
|
||||
From f01c8a6745cefd98198e0401a359302aba45ba57 Mon Sep 17 00:00:00 2001
|
||||
From: Derek Lesho <dlesho@codeweavers.com>
|
||||
Date: Mon, 16 Mar 2020 15:27:27 -0500
|
||||
Subject: [PATCH] Miscellaneous
|
||||
Date: Mon, 16 Mar 2020 12:09:39 -0500
|
||||
Subject: [PATCH 26/52] winegstreamer: Implement decoder MFT on gstreamer.
|
||||
|
||||
---
|
||||
dlls/mfreadwrite/reader.c | 12 +-
|
||||
dlls/winegstreamer/gst_cbs.c | 9 +
|
||||
dlls/winegstreamer/media_source.c | 114 ++-
|
||||
dlls/winegstreamer/mf_decode.c | 1324 +++++++++++++++++++++++++++++
|
||||
4 files changed, 1456 insertions(+), 3 deletions(-)
|
||||
dlls/winegstreamer/Makefile.in | 1 +
|
||||
dlls/winegstreamer/gst_cbs.c | 65 +
|
||||
dlls/winegstreamer/gst_cbs.h | 23 +
|
||||
dlls/winegstreamer/gst_private.h | 7 +
|
||||
dlls/winegstreamer/main.c | 3 +-
|
||||
dlls/winegstreamer/mf_decode.c | 1321 ++++++++++++++++++
|
||||
dlls/winegstreamer/mfplat.c | 118 +-
|
||||
dlls/winegstreamer/winegstreamer_classes.idl | 12 +
|
||||
include/mfidl.idl | 2 +
|
||||
9 files changed, 1550 insertions(+), 2 deletions(-)
|
||||
create mode 100644 dlls/winegstreamer/mf_decode.c
|
||||
|
||||
diff --git a/dlls/mfreadwrite/reader.c b/dlls/mfreadwrite/reader.c
|
||||
index 3b1dcbb963..f8c03e62d3 100644
|
||||
--- a/dlls/mfreadwrite/reader.c
|
||||
+++ b/dlls/mfreadwrite/reader.c
|
||||
@@ -1596,6 +1596,7 @@ static HRESULT source_reader_create_decoder_for_stream(struct source_reader *rea
|
||||
{
|
||||
MFT_REGISTER_TYPE_INFO in_type, out_type;
|
||||
CLSID *clsids, mft_clsid, category;
|
||||
+ BOOL decoder_found = FALSE;
|
||||
unsigned int i = 0, count;
|
||||
IMFMediaType *input_type;
|
||||
HRESULT hr;
|
||||
@@ -1642,12 +1643,21 @@ static HRESULT source_reader_create_decoder_for_stream(struct source_reader *rea
|
||||
}
|
||||
|
||||
}
|
||||
+ else if (!decoder_found)
|
||||
+ {
|
||||
+ /* see if there are other decoders for this stream */
|
||||
+ if (SUCCEEDED(MFTEnum(category, 0, &in_type, NULL, NULL, &clsids, &count)) && count)
|
||||
+ {
|
||||
+ decoder_found = TRUE;
|
||||
+ CoTaskMemFree(clsids);
|
||||
+ }
|
||||
+ }
|
||||
}
|
||||
|
||||
IMFMediaType_Release(input_type);
|
||||
}
|
||||
|
||||
- return MF_E_TOPO_CODEC_NOT_FOUND;
|
||||
+ return decoder_found ? MF_E_INVALIDREQUEST : MF_E_TOPO_CODEC_NOT_FOUND;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI src_reader_SetCurrentMediaType(IMFSourceReader *iface, DWORD index, DWORD *reserved,
|
||||
diff --git a/dlls/winegstreamer/Makefile.in b/dlls/winegstreamer/Makefile.in
|
||||
index f2e87494459..e2af4085827 100644
|
||||
--- a/dlls/winegstreamer/Makefile.in
|
||||
+++ b/dlls/winegstreamer/Makefile.in
|
||||
@@ -13,6 +13,7 @@ C_SRCS = \
|
||||
main.c \
|
||||
media_source.c \
|
||||
mediatype.c \
|
||||
+ mf_decode.c \
|
||||
mfplat.c \
|
||||
pin.c \
|
||||
qualitycontrol.c \
|
||||
diff --git a/dlls/winegstreamer/gst_cbs.c b/dlls/winegstreamer/gst_cbs.c
|
||||
index e392f4526f..598cd85c1e 100644
|
||||
index e56c987eb38..0c0d0a26100 100644
|
||||
--- a/dlls/winegstreamer/gst_cbs.c
|
||||
+++ b/dlls/winegstreamer/gst_cbs.c
|
||||
@@ -18,6 +18,9 @@
|
||||
|
||||
#include "config.h"
|
||||
|
||||
+#include <stdio.h>
|
||||
+#include <assert.h>
|
||||
+
|
||||
#include <gst/gst.h>
|
||||
|
||||
#include "objbase.h"
|
||||
@@ -53,6 +56,12 @@ static void CALLBACK perform_cb(TP_CALLBACK_INSTANCE *instance, void *user)
|
||||
@@ -51,6 +51,8 @@ static void CALLBACK perform_cb(TP_CALLBACK_INSTANCE *instance, void *user)
|
||||
perform_cb_gstdemux(cbdata);
|
||||
else if (cbdata->type < MEDIA_SOURCE_MAX)
|
||||
perform_cb_media_source(cbdata);
|
||||
else if (cbdata->type < MF_DECODE_MAX)
|
||||
perform_cb_mf_decode(cbdata);
|
||||
+ else
|
||||
+ {
|
||||
+ fprintf(stderr, "No handler registered for callback\n");
|
||||
+ assert(0);
|
||||
+ }
|
||||
+
|
||||
+ else if (cbdata->type < MF_DECODE_MAX)
|
||||
+ perform_cb_mf_decode(cbdata);
|
||||
|
||||
pthread_mutex_lock(&cbdata->lock);
|
||||
cbdata->finished = 1;
|
||||
diff --git a/dlls/winegstreamer/media_source.c b/dlls/winegstreamer/media_source.c
|
||||
index e0a1624951..40f7828e50 100644
|
||||
--- a/dlls/winegstreamer/media_source.c
|
||||
+++ b/dlls/winegstreamer/media_source.c
|
||||
@@ -84,6 +84,8 @@ struct source_async_command
|
||||
struct media_source
|
||||
{
|
||||
IMFMediaSource IMFMediaSource_iface;
|
||||
+ IMFGetService IMFGetService_iface;
|
||||
+ IMFSeekInfo IMFSeekInfo_iface;
|
||||
IMFAsyncCallback async_commands_callback;
|
||||
LONG ref;
|
||||
DWORD async_commands_queue;
|
||||
@@ -118,6 +120,16 @@ static inline struct media_source *impl_from_IMFMediaSource(IMFMediaSource *ifac
|
||||
return CONTAINING_RECORD(iface, struct media_source, IMFMediaSource_iface);
|
||||
}
|
||||
@@ -417,3 +419,66 @@ GstPadProbeReturn caps_listener_wrapper(GstPad *pad, GstPadProbeInfo *info, gpoi
|
||||
|
||||
+static inline struct media_source *impl_from_IMFGetService(IMFGetService *iface)
|
||||
return cbdata.u.pad_probe_data.ret;
|
||||
}
|
||||
+
|
||||
+gboolean activate_push_mode_wrapper(GstPad *pad, GstObject *parent, GstPadMode mode, gboolean activate)
|
||||
+{
|
||||
+ return CONTAINING_RECORD(iface, struct media_source, IMFGetService_iface);
|
||||
+ struct cb_data cbdata = { ACTIVATE_PUSH_MODE };
|
||||
+
|
||||
+ 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.query_function_data.ret;
|
||||
+}
|
||||
+
|
||||
+static inline struct media_source *impl_from_IMFSeekInfo(IMFSeekInfo *iface)
|
||||
+gboolean query_input_src_wrapper(GstPad *pad, GstObject *parent, GstQuery *query)
|
||||
+{
|
||||
+ return CONTAINING_RECORD(iface, struct media_source, IMFSeekInfo_iface);
|
||||
+ struct cb_data cbdata = { QUERY_INPUT_SRC };
|
||||
+
|
||||
+ 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;
|
||||
+}
|
||||
+
|
||||
static inline struct media_source *impl_from_async_commands_callback_IMFAsyncCallback(IMFAsyncCallback *iface)
|
||||
{
|
||||
return CONTAINING_RECORD(iface, struct media_source, async_commands_callback);
|
||||
@@ -1076,6 +1088,10 @@ static HRESULT WINAPI media_source_QueryInterface(IMFMediaSource *iface, REFIID
|
||||
{
|
||||
*out = &source->IMFMediaSource_iface;
|
||||
}
|
||||
+ else if(IsEqualIID(riid, &IID_IMFGetService))
|
||||
+ {
|
||||
+ *out = &source->IMFGetService_iface;
|
||||
+ }
|
||||
else
|
||||
{
|
||||
FIXME("(%s, %p)\n", debugstr_guid(riid), out);
|
||||
@@ -1170,7 +1186,7 @@ static HRESULT WINAPI media_source_GetCharacteristics(IMFMediaSource *iface, DWO
|
||||
if (source->state == SOURCE_SHUTDOWN)
|
||||
return MF_E_SHUTDOWN;
|
||||
|
||||
- *characteristics = MFMEDIASOURCE_CAN_SEEK;
|
||||
+ *characteristics = MFMEDIASOURCE_CAN_SEEK | MFMEDIASOURCE_CAN_PAUSE;
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
@@ -1312,6 +1328,99 @@ static const IMFMediaSourceVtbl IMFMediaSource_vtbl =
|
||||
media_source_Shutdown,
|
||||
+GstBusSyncReply watch_decoder_bus_wrapper(GstBus *bus, GstMessage *message, gpointer user)
|
||||
+{
|
||||
+ struct cb_data cbdata = { WATCH_DECODER_BUS };
|
||||
+
|
||||
+ 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 decoder_pad_added_wrapper(GstElement *element, GstPad *pad, gpointer user)
|
||||
+{
|
||||
+ struct cb_data cbdata = { DECODER_PAD_ADDED };
|
||||
+
|
||||
+ cbdata.u.pad_added_data.element = element;
|
||||
+ cbdata.u.pad_added_data.pad = pad;
|
||||
+ cbdata.u.pad_added_data.user = user;
|
||||
+
|
||||
+ call_cb(&cbdata);
|
||||
+}
|
||||
+
|
||||
+GstFlowReturn decoder_new_sample_wrapper(GstElement *appsink, gpointer user)
|
||||
+{
|
||||
+ struct cb_data cbdata = {DECODER_NEW_SAMPLE};
|
||||
+
|
||||
+ cbdata.u.new_sample_data.appsink = appsink;
|
||||
+ cbdata.u.new_sample_data.user = user;
|
||||
+
|
||||
+ call_cb(&cbdata);
|
||||
+
|
||||
+ return cbdata.u.new_sample_data.ret;
|
||||
+}
|
||||
diff --git a/dlls/winegstreamer/gst_cbs.h b/dlls/winegstreamer/gst_cbs.h
|
||||
index 7173c09746e..7dc60f961ba 100644
|
||||
--- a/dlls/winegstreamer/gst_cbs.h
|
||||
+++ b/dlls/winegstreamer/gst_cbs.h
|
||||
@@ -54,6 +54,12 @@ enum CB_TYPE {
|
||||
SOURCE_ALL_STREAMS,
|
||||
STREAM_PAD_EVENT,
|
||||
MEDIA_SOURCE_MAX,
|
||||
+ ACTIVATE_PUSH_MODE,
|
||||
+ QUERY_INPUT_SRC,
|
||||
+ DECODER_NEW_SAMPLE,
|
||||
+ WATCH_DECODER_BUS,
|
||||
+ DECODER_PAD_ADDED,
|
||||
+ MF_DECODE_MAX,
|
||||
};
|
||||
|
||||
+static HRESULT WINAPI source_get_service_QueryInterface(IMFGetService *iface, REFIID riid, void **obj)
|
||||
+{
|
||||
+ struct media_source *source = impl_from_IMFGetService(iface);
|
||||
+ return IMFMediaSource_QueryInterface(&source->IMFMediaSource_iface, riid, obj);
|
||||
+}
|
||||
+
|
||||
+static ULONG WINAPI source_get_service_AddRef(IMFGetService *iface)
|
||||
+{
|
||||
+ struct media_source *source = impl_from_IMFGetService(iface);
|
||||
+ return IMFMediaSource_AddRef(&source->IMFMediaSource_iface);
|
||||
+}
|
||||
+
|
||||
+static ULONG WINAPI source_get_service_Release(IMFGetService *iface)
|
||||
+{
|
||||
+ struct media_source *source = impl_from_IMFGetService(iface);
|
||||
+ return IMFMediaSource_Release(&source->IMFMediaSource_iface);
|
||||
+}
|
||||
+
|
||||
+static HRESULT WINAPI source_get_service_GetService(IMFGetService *iface, REFGUID service, REFIID riid, void **obj)
|
||||
+{
|
||||
+ struct media_source *source = impl_from_IMFGetService(iface);
|
||||
+
|
||||
+ TRACE("(%p)->(%s, %s, %p)\n", source, debugstr_guid(service), debugstr_guid(riid), obj);
|
||||
+
|
||||
+ if (source->state == SOURCE_SHUTDOWN)
|
||||
+ return MF_E_SHUTDOWN;
|
||||
+
|
||||
+ *obj = NULL;
|
||||
+
|
||||
+ if (IsEqualIID(service, &MF_SCRUBBING_SERVICE))
|
||||
+ {
|
||||
+ if (IsEqualIID(riid, &IID_IMFSeekInfo))
|
||||
+ {
|
||||
+ *obj = &source->IMFSeekInfo_iface;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (*obj)
|
||||
+ IUnknown_AddRef((IUnknown*) *obj);
|
||||
+
|
||||
+ return *obj ? S_OK : E_NOINTERFACE;
|
||||
+}
|
||||
+
|
||||
+static const IMFGetServiceVtbl IMFGetService_vtbl =
|
||||
+{
|
||||
+ source_get_service_QueryInterface,
|
||||
+ source_get_service_AddRef,
|
||||
+ source_get_service_Release,
|
||||
+ source_get_service_GetService,
|
||||
+};
|
||||
+
|
||||
+static HRESULT WINAPI source_seek_info_QueryInterface(IMFSeekInfo *iface, REFIID riid, void **obj)
|
||||
+{
|
||||
+ struct media_source *source = impl_from_IMFSeekInfo(iface);
|
||||
+ return IMFMediaSource_QueryInterface(&source->IMFMediaSource_iface, riid, obj);
|
||||
+}
|
||||
+
|
||||
+static ULONG WINAPI source_seek_info_AddRef(IMFSeekInfo *iface)
|
||||
+{
|
||||
+ struct media_source *source = impl_from_IMFSeekInfo(iface);
|
||||
+ return IMFMediaSource_AddRef(&source->IMFMediaSource_iface);
|
||||
+}
|
||||
+
|
||||
+static ULONG WINAPI source_seek_info_Release(IMFSeekInfo *iface)
|
||||
+{
|
||||
+ struct media_source *source = impl_from_IMFSeekInfo(iface);
|
||||
+ return IMFMediaSource_Release(&source->IMFMediaSource_iface);
|
||||
+}
|
||||
+
|
||||
+static HRESULT WINAPI source_seek_info_GetNearestKeyFrames(IMFSeekInfo *iface, const GUID *format,
|
||||
+ const PROPVARIANT *position, PROPVARIANT *prev_frame, PROPVARIANT *next_frame)
|
||||
+{
|
||||
+ struct media_source *source = impl_from_IMFSeekInfo(iface);
|
||||
+
|
||||
+ FIXME("(%p)->(%s, %p, %p, %p) - semi-stub\n", source, debugstr_guid(format), position, prev_frame, next_frame);
|
||||
+
|
||||
+ if (source->state == SOURCE_SHUTDOWN)
|
||||
+ return MF_E_SHUTDOWN;
|
||||
+
|
||||
+ PropVariantCopy(prev_frame, position);
|
||||
+ PropVariantCopy(next_frame, position);
|
||||
+
|
||||
+ return S_OK;
|
||||
+}
|
||||
+
|
||||
+static const IMFSeekInfoVtbl IMFSeekInfo_vtbl =
|
||||
+{
|
||||
+ source_seek_info_QueryInterface,
|
||||
+ source_seek_info_AddRef,
|
||||
+ source_seek_info_Release,
|
||||
+ source_seek_info_GetNearestKeyFrames,
|
||||
+};
|
||||
+
|
||||
static HRESULT media_source_constructor(IMFByteStream *bytestream, enum source_type type, struct media_source **out_media_source)
|
||||
{
|
||||
unsigned int i;
|
||||
@@ -1332,6 +1441,8 @@ static HRESULT media_source_constructor(IMFByteStream *bytestream, enum source_t
|
||||
return E_OUTOFMEMORY;
|
||||
struct cb_data {
|
||||
@@ -144,6 +150,17 @@ struct cb_data {
|
||||
gpointer user;
|
||||
GstPadProbeReturn ret;
|
||||
} pad_probe_data;
|
||||
+ struct chain_data {
|
||||
+ GstPad *pad;
|
||||
+ GstObject *parent;
|
||||
+ GstBuffer *buffer;
|
||||
+ GstFlowReturn ret;
|
||||
+ } chain_data;
|
||||
+ struct new_sample_data {
|
||||
+ GstElement *appsink;
|
||||
+ gpointer user;
|
||||
+ GstFlowReturn ret;
|
||||
+ } new_sample_data;
|
||||
} u;
|
||||
|
||||
object->IMFMediaSource_iface.lpVtbl = &IMFMediaSource_vtbl;
|
||||
+ object->IMFGetService_iface.lpVtbl = &IMFGetService_vtbl;
|
||||
+ object->IMFSeekInfo_iface.lpVtbl = &IMFSeekInfo_vtbl;
|
||||
object->async_commands_callback.lpVtbl = &source_async_commands_callback_vtbl;
|
||||
object->ref = 1;
|
||||
object->type = type;
|
||||
@@ -1431,7 +1542,6 @@ static HRESULT media_source_constructor(IMFByteStream *bytestream, enum source_t
|
||||
heap_free(descriptors);
|
||||
descriptors = NULL;
|
||||
int finished;
|
||||
@@ -155,6 +172,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;
|
||||
+void perform_cb_mf_decode(struct cb_data *data) DECLSPEC_HIDDEN;
|
||||
|
||||
- /* miscelaneous presentation descriptor setup */
|
||||
{
|
||||
IMFAttributes *byte_stream_attributes;
|
||||
gint64 total_pres_time = 0;
|
||||
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;
|
||||
@@ -180,5 +198,10 @@ void source_stream_added_wrapper(GstElement *bin, GstPad *pad, gpointer user) DE
|
||||
void source_stream_removed_wrapper(GstElement *element, GstPad *pad, gpointer user) DECLSPEC_HIDDEN;
|
||||
void source_all_streams_wrapper(GstElement *element, gpointer user) DECLSPEC_HIDDEN;
|
||||
GstPadProbeReturn caps_listener_wrapper(GstPad *pad, GstPadProbeInfo *info, gpointer user);
|
||||
+gboolean activate_push_mode_wrapper(GstPad *pad, GstObject *parent, GstPadMode mode, gboolean activate) DECLSPEC_HIDDEN;
|
||||
+gboolean query_input_src_wrapper(GstPad *pad, GstObject *parent, GstQuery *query) DECLSPEC_HIDDEN;
|
||||
+GstBusSyncReply watch_decoder_bus_wrapper(GstBus *bus, GstMessage *message, gpointer user) DECLSPEC_HIDDEN;
|
||||
+GstFlowReturn decoder_new_sample_wrapper(GstElement *appsink, gpointer user) DECLSPEC_HIDDEN;
|
||||
+void decoder_pad_added_wrapper(GstElement *element, GstPad *Pad, gpointer user) DECLSPEC_HIDDEN;
|
||||
|
||||
#endif
|
||||
diff --git a/dlls/winegstreamer/gst_private.h b/dlls/winegstreamer/gst_private.h
|
||||
index d0737442cc3..5ff412c8e47 100644
|
||||
--- a/dlls/winegstreamer/gst_private.h
|
||||
+++ b/dlls/winegstreamer/gst_private.h
|
||||
@@ -53,6 +53,7 @@ BOOL init_gstreamer(void) DECLSPEC_HIDDEN;
|
||||
|
||||
void start_dispatch_thread(void) DECLSPEC_HIDDEN;
|
||||
|
||||
+extern HRESULT mfplat_DllRegisterServer(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;
|
||||
@@ -62,6 +63,12 @@ GstCaps *caps_from_mf_media_type(IMFMediaType *type);
|
||||
IMFSample *mf_sample_from_gst_buffer(GstBuffer *in);
|
||||
GstBuffer *gst_buffer_from_mf_sample(IMFSample *in);
|
||||
|
||||
+enum decoder_type
|
||||
+{
|
||||
+ DECODER_TYPE_H264,
|
||||
+ DECODER_TYPE_AAC,
|
||||
+};
|
||||
+HRESULT generic_decoder_construct(REFIID riid, void **obj, enum decoder_type) DECLSPEC_HIDDEN;
|
||||
HRESULT winegstreamer_stream_handler_create(REFIID riid, void **obj) DECLSPEC_HIDDEN;
|
||||
|
||||
#endif /* __GST_PRIVATE_INCLUDED__ */
|
||||
diff --git a/dlls/winegstreamer/main.c b/dlls/winegstreamer/main.c
|
||||
index 4ca371d58bd..385c5550235 100644
|
||||
--- a/dlls/winegstreamer/main.c
|
||||
+++ b/dlls/winegstreamer/main.c
|
||||
@@ -368,7 +368,8 @@ HRESULT WINAPI DllRegisterServer(void)
|
||||
IFilterMapper2_RegisterFilter(mapper, &CLSID_WAVEParser, wave_parserW, NULL, NULL, NULL, ®_wave_parser);
|
||||
|
||||
IFilterMapper2_Release(mapper);
|
||||
- return S_OK;
|
||||
+
|
||||
+ return mfplat_DllRegisterServer();
|
||||
}
|
||||
|
||||
HRESULT WINAPI DllUnregisterServer(void)
|
||||
diff --git a/dlls/winegstreamer/mf_decode.c b/dlls/winegstreamer/mf_decode.c
|
||||
new file mode 100644
|
||||
index 0000000000..60ec6fc20b
|
||||
index 00000000000..025af7b91ae
|
||||
--- /dev/null
|
||||
+++ b/dlls/winegstreamer/mf_decode.c
|
||||
@@ -0,0 +1,1324 @@
|
||||
@@ -0,0 +1,1321 @@
|
||||
+#include "config.h"
|
||||
+
|
||||
+#include <gst/gst.h>
|
||||
@ -271,7 +232,8 @@ index 0000000000..60ec6fc20b
|
||||
+/* keep in sync with mfplat.c's mft registrations */
|
||||
+
|
||||
+const GUID *h264_input_types[] = {&MFVideoFormat_H264};
|
||||
+const GUID *h264_output_types[] = {&MFVideoFormat_I420, &MFVideoFormat_IYUV, &MFVideoFormat_NV12, &MFVideoFormat_YUY2, &MFVideoFormat_YV12};
|
||||
+/* NV12 comes first https://docs.microsoft.com/en-us/windows/win32/medfound/mft-decoder-expose-output-types-in-native-order. thanks to @vitorhnn */
|
||||
+const GUID *h264_output_types[] = {&MFVideoFormat_NV12, &MFVideoFormat_I420, &MFVideoFormat_IYUV, &MFVideoFormat_YUY2, &MFVideoFormat_YV12};
|
||||
+
|
||||
+const GUID *aac_input_types[] = {&MFAudioFormat_AAC};
|
||||
+const GUID *aac_output_types[] = {&MFAudioFormat_Float};
|
||||
@ -897,7 +859,6 @@ index 0000000000..60ec6fc20b
|
||||
+ {
|
||||
+ GUID major_type, subtype;
|
||||
+ UINT64 unused;
|
||||
+ unsigned int i;
|
||||
+
|
||||
+ if (FAILED(hr = IMFMediaType_GetGUID(type, &MF_MT_MAJOR_TYPE, &major_type)))
|
||||
+ return hr;
|
||||
@ -913,7 +874,7 @@ index 0000000000..60ec6fc20b
|
||||
+ return hr;
|
||||
+ }
|
||||
+
|
||||
+ for (i = 0; i < decoder_descs[decoder->type].input_types_count; i++)
|
||||
+ for (unsigned int i = 0; i < decoder_descs[decoder->type].input_types_count; i++)
|
||||
+ {
|
||||
+ if (IsEqualGUID(&subtype, decoder_descs[decoder->type].input_types[i]))
|
||||
+ break;
|
||||
@ -966,7 +927,6 @@ index 0000000000..60ec6fc20b
|
||||
+ {
|
||||
+ GUID major_type, subtype;
|
||||
+ UINT64 unused;
|
||||
+ unsigned int i;
|
||||
+
|
||||
+ /* validate the type */
|
||||
+ if (FAILED(hr = IMFMediaType_GetGUID(type, &MF_MT_MAJOR_TYPE, &major_type)))
|
||||
@ -983,7 +943,7 @@ index 0000000000..60ec6fc20b
|
||||
+ return MF_E_INVALIDTYPE;
|
||||
+ }
|
||||
+
|
||||
+ for (i = 0; i < decoder_descs[decoder->type].output_types_count; i++)
|
||||
+ for (unsigned int i = 0; i < decoder_descs[decoder->type].output_types_count; i++)
|
||||
+ {
|
||||
+ if (IsEqualGUID(&subtype, decoder_descs[decoder->type].output_types[i]))
|
||||
+ break;
|
||||
@ -1230,7 +1190,7 @@ index 0000000000..60ec6fc20b
|
||||
+ }
|
||||
+ default:
|
||||
+ {
|
||||
+ ERR("Unhandled message type %x.\n", message);
|
||||
+ WARN("Unhandled message type %x.\n", message);
|
||||
+ hr = E_FAIL;
|
||||
+ break;
|
||||
+ }
|
||||
@ -1263,7 +1223,6 @@ index 0000000000..60ec6fc20b
|
||||
+
|
||||
+ drain = gst_query_new_drain();
|
||||
+ gst_pad_peer_query(decoder->input_src, drain);
|
||||
+ gst_query_unref(drain);
|
||||
+
|
||||
+ if (decoder->output_counter || decoder->draining)
|
||||
+ {
|
||||
@ -1296,7 +1255,6 @@ index 0000000000..60ec6fc20b
|
||||
+ struct mf_decoder *decoder = impl_mf_decoder_from_IMFTransform(iface);
|
||||
+ MFT_OUTPUT_DATA_BUFFER *relevant_buffer = NULL;
|
||||
+ GstSample *buffer;
|
||||
+ unsigned int i;
|
||||
+
|
||||
+ TRACE("%p, %#x, %u, %p, %p,\n", iface, flags, count, samples, status);
|
||||
+
|
||||
@ -1306,7 +1264,7 @@ index 0000000000..60ec6fc20b
|
||||
+ if (!decoder->valid_state)
|
||||
+ return MF_E_TRANSFORM_TYPE_NOT_SET;
|
||||
+
|
||||
+ for (i = 0; i < count; i++)
|
||||
+ for (unsigned int i = 0; i < count; i++)
|
||||
+ {
|
||||
+ MFT_OUTPUT_DATA_BUFFER *out_buffer = &samples[i];
|
||||
+
|
||||
@ -1570,6 +1528,186 @@ index 0000000000..60ec6fc20b
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
diff --git a/dlls/winegstreamer/mfplat.c b/dlls/winegstreamer/mfplat.c
|
||||
index ae5dcc31825..167f2a185be 100644
|
||||
--- a/dlls/winegstreamer/mfplat.c
|
||||
+++ b/dlls/winegstreamer/mfplat.c
|
||||
@@ -406,6 +406,16 @@ failed:
|
||||
|
||||
static const GUID CLSID_GStreamerByteStreamHandler = {0x317df618, 0x5e5a, 0x468a, {0x9f, 0x15, 0xd8, 0x27, 0xa9, 0xa0, 0x81, 0x62}};
|
||||
|
||||
+static HRESULT h264_decoder_create(REFIID riid, void **ret)
|
||||
+{
|
||||
+ return generic_decoder_construct(riid, ret, DECODER_TYPE_H264);
|
||||
+}
|
||||
+
|
||||
+static HRESULT aac_decoder_create(REFIID riid, void **ret)
|
||||
+{
|
||||
+ return generic_decoder_construct(riid, ret, DECODER_TYPE_AAC);
|
||||
+}
|
||||
+
|
||||
static const struct class_object
|
||||
{
|
||||
const GUID *clsid;
|
||||
@@ -415,6 +425,8 @@ class_objects[] =
|
||||
{
|
||||
{ &CLSID_VideoProcessorMFT, &video_processor_create },
|
||||
{ &CLSID_GStreamerByteStreamHandler, &winegstreamer_stream_handler_create },
|
||||
+ { &CLSID_CMSH264DecoderMFT, &h264_decoder_create },
|
||||
+ { &CLSID_CMSAACDecMFT, &aac_decoder_create },
|
||||
};
|
||||
|
||||
HRESULT mfplat_get_class_object(REFCLSID rclsid, REFIID riid, void **obj)
|
||||
@@ -443,6 +455,111 @@ HRESULT mfplat_get_class_object(REFCLSID rclsid, REFIID riid, void **obj)
|
||||
return CLASS_E_CLASSNOTAVAILABLE;
|
||||
}
|
||||
|
||||
+
|
||||
+static WCHAR h264decoderW[] = {'H','.','2','6','4',' ','D','e','c','o','d','e','r',0};
|
||||
+const GUID *h264_decoder_input_types[] =
|
||||
+{
|
||||
+ &MFVideoFormat_H264,
|
||||
+};
|
||||
+const GUID *h264_decoder_output_types[] =
|
||||
+{
|
||||
+ &MFVideoFormat_NV12,
|
||||
+ &MFVideoFormat_I420,
|
||||
+ &MFVideoFormat_IYUV,
|
||||
+ &MFVideoFormat_YUY2,
|
||||
+ &MFVideoFormat_YV12,
|
||||
+};
|
||||
+
|
||||
+static WCHAR aacdecoderW[] = {'A','A','C',' ','D','e','c','o','d','e','r',0};
|
||||
+const GUID *aac_decoder_input_types[] =
|
||||
+{
|
||||
+ &MFAudioFormat_AAC,
|
||||
+};
|
||||
+
|
||||
+const GUID *aac_decoder_output_types[] =
|
||||
+{
|
||||
+ &MFAudioFormat_Float,
|
||||
+ &MFAudioFormat_PCM,
|
||||
+};
|
||||
+
|
||||
+static const struct mft
|
||||
+{
|
||||
+ const GUID *clsid;
|
||||
+ const GUID *category;
|
||||
+ LPWSTR name;
|
||||
+ const UINT32 flags;
|
||||
+ const GUID *major_type;
|
||||
+ const UINT32 input_types_count;
|
||||
+ const GUID **input_types;
|
||||
+ const UINT32 output_types_count;
|
||||
+ const GUID **output_types;
|
||||
+ IMFAttributes *attributes;
|
||||
+}
|
||||
+mfts[] =
|
||||
+{
|
||||
+ {
|
||||
+ &CLSID_CMSH264DecoderMFT,
|
||||
+ &MFT_CATEGORY_VIDEO_DECODER,
|
||||
+ h264decoderW,
|
||||
+ MFT_ENUM_FLAG_SYNCMFT,
|
||||
+ &MFMediaType_Video,
|
||||
+ ARRAY_SIZE(h264_decoder_input_types),
|
||||
+ h264_decoder_input_types,
|
||||
+ ARRAY_SIZE(h264_decoder_output_types),
|
||||
+ h264_decoder_output_types,
|
||||
+ NULL
|
||||
+ },
|
||||
+ {
|
||||
+ &CLSID_CMSAACDecMFT,
|
||||
+ &MFT_CATEGORY_AUDIO_DECODER,
|
||||
+ aacdecoderW,
|
||||
+ MFT_ENUM_FLAG_SYNCMFT,
|
||||
+ &MFMediaType_Audio,
|
||||
+ ARRAY_SIZE(aac_decoder_input_types),
|
||||
+ aac_decoder_input_types,
|
||||
+ ARRAY_SIZE(aac_decoder_output_types),
|
||||
+ aac_decoder_output_types,
|
||||
+ NULL
|
||||
+ }
|
||||
+};
|
||||
+
|
||||
+HRESULT mfplat_DllRegisterServer(void)
|
||||
+{
|
||||
+ HRESULT hr;
|
||||
+
|
||||
+ for (unsigned int i = 0; i < ARRAY_SIZE(mfts); i++)
|
||||
+ {
|
||||
+ const struct mft *cur = &mfts[i];
|
||||
+
|
||||
+ MFT_REGISTER_TYPE_INFO *input_types, *output_types;
|
||||
+ input_types = heap_alloc(cur->input_types_count * sizeof(input_types[0]));
|
||||
+ output_types = heap_alloc(cur->output_types_count * sizeof(output_types[0]));
|
||||
+ for (unsigned int i = 0; i < cur->input_types_count; i++)
|
||||
+ {
|
||||
+ input_types[i].guidMajorType = *(cur->major_type);
|
||||
+ input_types[i].guidSubtype = *(cur->input_types[i]);
|
||||
+ }
|
||||
+ for (unsigned int i = 0; i < cur->output_types_count; i++)
|
||||
+ {
|
||||
+ output_types[i].guidMajorType = *(cur->major_type);
|
||||
+ output_types[i].guidSubtype = *(cur->output_types[i]);
|
||||
+ }
|
||||
+
|
||||
+ hr = MFTRegister(*(cur->clsid), *(cur->category), cur->name, cur->flags, cur->input_types_count,
|
||||
+ input_types, cur->output_types_count, output_types, cur->attributes);
|
||||
+
|
||||
+ heap_free(input_types);
|
||||
+ heap_free(output_types);
|
||||
+
|
||||
+ if (FAILED(hr))
|
||||
+ {
|
||||
+ FIXME("Failed to register MFT, hr %#x\n", hr);
|
||||
+ return hr;
|
||||
+ }
|
||||
+ }
|
||||
+ return S_OK;
|
||||
+}
|
||||
+
|
||||
const static struct
|
||||
{
|
||||
const GUID *subtype;
|
||||
@@ -461,7 +578,6 @@ struct aac_user_data
|
||||
{
|
||||
WORD payload_type;
|
||||
WORD profile_level_indication;
|
||||
- WORD struct_type;
|
||||
WORD reserved;
|
||||
/* audio-specific-config is stored here */
|
||||
};
|
||||
diff --git a/dlls/winegstreamer/winegstreamer_classes.idl b/dlls/winegstreamer/winegstreamer_classes.idl
|
||||
index 1dc4ba9a10b..3f28b4ddec4 100644
|
||||
--- a/dlls/winegstreamer/winegstreamer_classes.idl
|
||||
+++ b/dlls/winegstreamer/winegstreamer_classes.idl
|
||||
@@ -61,3 +61,15 @@ coclass VideoProcessorMFT {}
|
||||
uuid(317df618-5e5a-468a-9f15-d827a9a08162)
|
||||
]
|
||||
coclass GStreamerByteStreamHandler {}
|
||||
+
|
||||
+[
|
||||
+ threading(both),
|
||||
+ uuid(62ce7e72-4c71-4d20-b15d-452831a87d9d)
|
||||
+]
|
||||
+coclass CMSH264DecoderMFT { }
|
||||
+
|
||||
+[
|
||||
+ threading(both),
|
||||
+ uuid(32d186a7-218f-4c75-8876-dd77273a8999)
|
||||
+]
|
||||
+coclass CMSAACDecMFT { }
|
||||
diff --git a/include/mfidl.idl b/include/mfidl.idl
|
||||
index 4ceeb707bd0..61c9a565415 100644
|
||||
--- a/include/mfidl.idl
|
||||
+++ b/include/mfidl.idl
|
||||
@@ -1241,3 +1241,5 @@ cpp_quote("EXTERN_GUID(MF_ACTIVATE_CUSTOM_VIDEO_PRESENTER_ACTIVATE, 0xba491365,
|
||||
cpp_quote("EXTERN_GUID(MF_ACTIVATE_CUSTOM_VIDEO_PRESENTER_FLAGS, 0xba491366, 0xbe50, 0x451e, 0x95, 0xab, 0x6d, 0x4a, 0xcc, 0xc7, 0xda, 0xd8);")
|
||||
|
||||
cpp_quote("EXTERN_GUID(CLSID_VideoProcessorMFT, 0x88753b26, 0x5b24, 0x49bd, 0xb2, 0xe7, 0xc, 0x44, 0x5c, 0x78, 0xc9, 0x82);")
|
||||
+cpp_quote("EXTERN_GUID(CLSID_CMSH264DecoderMFT, 0x62ce7e72, 0x4c71, 0x4d20, 0xb1, 0x5d, 0x45, 0x28, 0x31, 0xa8, 0x7d, 0x9d);")
|
||||
+cpp_quote("EXTERN_GUID(CLSID_CMSAACDecMFT, 0x32d186a7, 0x218f, 0x4c75, 0x88, 0x76, 0xdd, 0x77, 0x27, 0x3a, 0x89, 0x99);")
|
||||
--
|
||||
2.28.0
|
||||
|
@ -1,7 +1,7 @@
|
||||
From 5b5fb65ee4d8f7e8932076b4d8ee0eb1722f0058 Mon Sep 17 00:00:00 2001
|
||||
From 3f8659c74c63e1793000e82fa2a51e377bbc5f5e Mon Sep 17 00:00:00 2001
|
||||
From: Derek Lesho <dlesho@codeweavers.com>
|
||||
Date: Mon, 23 Mar 2020 11:55:41 -0500
|
||||
Subject: [PATCH 34/54] mfreadwrite: Select all streams when creating a source
|
||||
Subject: [PATCH 27/52] mfreadwrite: Select all streams when creating a source
|
||||
reader.
|
||||
|
||||
---
|
||||
@ -9,7 +9,7 @@ Subject: [PATCH 34/54] mfreadwrite: Select all streams when creating a source
|
||||
1 file changed, 4 insertions(+)
|
||||
|
||||
diff --git a/dlls/mfreadwrite/reader.c b/dlls/mfreadwrite/reader.c
|
||||
index 96a82b798a..3b1dcbb963 100644
|
||||
index 96a82b798ab..3b1dcbb9636 100644
|
||||
--- a/dlls/mfreadwrite/reader.c
|
||||
+++ b/dlls/mfreadwrite/reader.c
|
||||
@@ -2120,6 +2120,10 @@ static HRESULT create_source_reader_from_source(IMFMediaSource *source, IMFAttri
|
317
patches/mfplat-streaming-support/0028-Miscellaneous.patch
Normal file
317
patches/mfplat-streaming-support/0028-Miscellaneous.patch
Normal file
@ -0,0 +1,317 @@
|
||||
From d37c836567ce0d6a280b265c6748a072e0e8814f Mon Sep 17 00:00:00 2001
|
||||
From: Derek Lesho <dlesho@codeweavers.com>
|
||||
Date: Mon, 16 Mar 2020 15:27:27 -0500
|
||||
Subject: [PATCH 28/52] Miscellaneous
|
||||
|
||||
---
|
||||
dlls/mfreadwrite/reader.c | 12 ++-
|
||||
dlls/winegstreamer/gst_cbs.c | 20 ++---
|
||||
dlls/winegstreamer/gst_cbs.h | 1 -
|
||||
dlls/winegstreamer/media_source.c | 137 +++++++++++++++++++++++++++++-
|
||||
4 files changed, 155 insertions(+), 15 deletions(-)
|
||||
|
||||
diff --git a/dlls/mfreadwrite/reader.c b/dlls/mfreadwrite/reader.c
|
||||
index 3b1dcbb9636..f8c03e62d35 100644
|
||||
--- a/dlls/mfreadwrite/reader.c
|
||||
+++ b/dlls/mfreadwrite/reader.c
|
||||
@@ -1596,6 +1596,7 @@ static HRESULT source_reader_create_decoder_for_stream(struct source_reader *rea
|
||||
{
|
||||
MFT_REGISTER_TYPE_INFO in_type, out_type;
|
||||
CLSID *clsids, mft_clsid, category;
|
||||
+ BOOL decoder_found = FALSE;
|
||||
unsigned int i = 0, count;
|
||||
IMFMediaType *input_type;
|
||||
HRESULT hr;
|
||||
@@ -1642,12 +1643,21 @@ static HRESULT source_reader_create_decoder_for_stream(struct source_reader *rea
|
||||
}
|
||||
|
||||
}
|
||||
+ else if (!decoder_found)
|
||||
+ {
|
||||
+ /* see if there are other decoders for this stream */
|
||||
+ if (SUCCEEDED(MFTEnum(category, 0, &in_type, NULL, NULL, &clsids, &count)) && count)
|
||||
+ {
|
||||
+ decoder_found = TRUE;
|
||||
+ CoTaskMemFree(clsids);
|
||||
+ }
|
||||
+ }
|
||||
}
|
||||
|
||||
IMFMediaType_Release(input_type);
|
||||
}
|
||||
|
||||
- return MF_E_TOPO_CODEC_NOT_FOUND;
|
||||
+ return decoder_found ? MF_E_INVALIDREQUEST : MF_E_TOPO_CODEC_NOT_FOUND;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI src_reader_SetCurrentMediaType(IMFSourceReader *iface, DWORD index, DWORD *reserved,
|
||||
diff --git a/dlls/winegstreamer/gst_cbs.c b/dlls/winegstreamer/gst_cbs.c
|
||||
index 0c0d0a26100..cf8f33a0272 100644
|
||||
--- a/dlls/winegstreamer/gst_cbs.c
|
||||
+++ b/dlls/winegstreamer/gst_cbs.c
|
||||
@@ -18,6 +18,9 @@
|
||||
|
||||
#include "config.h"
|
||||
|
||||
+#include <stdio.h>
|
||||
+#include <assert.h>
|
||||
+
|
||||
#include <gst/gst.h>
|
||||
|
||||
#include "objbase.h"
|
||||
@@ -53,6 +56,12 @@ static void CALLBACK perform_cb(TP_CALLBACK_INSTANCE *instance, void *user)
|
||||
perform_cb_media_source(cbdata);
|
||||
else if (cbdata->type < MF_DECODE_MAX)
|
||||
perform_cb_mf_decode(cbdata);
|
||||
+ else
|
||||
+ {
|
||||
+ fprintf(stderr, "No handler registered for callback\n");
|
||||
+ assert(0);
|
||||
+ }
|
||||
+
|
||||
|
||||
pthread_mutex_lock(&cbdata->lock);
|
||||
cbdata->finished = 1;
|
||||
@@ -460,17 +469,6 @@ GstBusSyncReply watch_decoder_bus_wrapper(GstBus *bus, GstMessage *message, gpoi
|
||||
return cbdata.u.watch_bus_data.ret;
|
||||
}
|
||||
|
||||
-void decoder_pad_added_wrapper(GstElement *element, GstPad *pad, gpointer user)
|
||||
-{
|
||||
- struct cb_data cbdata = { DECODER_PAD_ADDED };
|
||||
-
|
||||
- cbdata.u.pad_added_data.element = element;
|
||||
- cbdata.u.pad_added_data.pad = pad;
|
||||
- cbdata.u.pad_added_data.user = user;
|
||||
-
|
||||
- call_cb(&cbdata);
|
||||
-}
|
||||
-
|
||||
GstFlowReturn decoder_new_sample_wrapper(GstElement *appsink, gpointer user)
|
||||
{
|
||||
struct cb_data cbdata = {DECODER_NEW_SAMPLE};
|
||||
diff --git a/dlls/winegstreamer/gst_cbs.h b/dlls/winegstreamer/gst_cbs.h
|
||||
index 7dc60f961ba..c6aa94d1632 100644
|
||||
--- a/dlls/winegstreamer/gst_cbs.h
|
||||
+++ b/dlls/winegstreamer/gst_cbs.h
|
||||
@@ -202,6 +202,5 @@ gboolean activate_push_mode_wrapper(GstPad *pad, GstObject *parent, GstPadMode m
|
||||
gboolean query_input_src_wrapper(GstPad *pad, GstObject *parent, GstQuery *query) DECLSPEC_HIDDEN;
|
||||
GstBusSyncReply watch_decoder_bus_wrapper(GstBus *bus, GstMessage *message, gpointer user) DECLSPEC_HIDDEN;
|
||||
GstFlowReturn decoder_new_sample_wrapper(GstElement *appsink, gpointer user) DECLSPEC_HIDDEN;
|
||||
-void decoder_pad_added_wrapper(GstElement *element, GstPad *Pad, gpointer user) DECLSPEC_HIDDEN;
|
||||
|
||||
#endif
|
||||
diff --git a/dlls/winegstreamer/media_source.c b/dlls/winegstreamer/media_source.c
|
||||
index ca799446ad8..919f46fd714 100644
|
||||
--- a/dlls/winegstreamer/media_source.c
|
||||
+++ b/dlls/winegstreamer/media_source.c
|
||||
@@ -95,6 +95,8 @@ struct source_async_command
|
||||
struct media_source
|
||||
{
|
||||
IMFMediaSource IMFMediaSource_iface;
|
||||
+ IMFGetService IMFGetService_iface;
|
||||
+ IMFSeekInfo IMFSeekInfo_iface;
|
||||
IMFAsyncCallback async_commands_callback;
|
||||
LONG ref;
|
||||
DWORD async_commands_queue;
|
||||
@@ -127,6 +129,16 @@ static inline struct media_source *impl_from_IMFMediaSource(IMFMediaSource *ifac
|
||||
return CONTAINING_RECORD(iface, struct media_source, IMFMediaSource_iface);
|
||||
}
|
||||
|
||||
+static inline struct media_source *impl_from_IMFGetService(IMFGetService *iface)
|
||||
+{
|
||||
+ return CONTAINING_RECORD(iface, struct media_source, IMFGetService_iface);
|
||||
+}
|
||||
+
|
||||
+static inline struct media_source *impl_from_IMFSeekInfo(IMFSeekInfo *iface)
|
||||
+{
|
||||
+ return CONTAINING_RECORD(iface, struct media_source, IMFSeekInfo_iface);
|
||||
+}
|
||||
+
|
||||
static inline struct media_source *impl_from_async_commands_callback_IMFAsyncCallback(IMFAsyncCallback *iface)
|
||||
{
|
||||
return CONTAINING_RECORD(iface, struct media_source, async_commands_callback);
|
||||
@@ -564,6 +576,11 @@ static gboolean query_bytestream(GstPad *pad, GstObject *parent, GstQuery *query
|
||||
gst_caps_unref(caps);
|
||||
return TRUE;
|
||||
}
|
||||
+ case GST_QUERY_LATENCY:
|
||||
+ {
|
||||
+ gst_query_set_latency(query, FALSE, 0, 0);
|
||||
+ return TRUE;
|
||||
+ }
|
||||
default:
|
||||
{
|
||||
WARN("Unhandled query type %s\n", GST_QUERY_TYPE_NAME(query));
|
||||
@@ -632,6 +649,23 @@ GstBusSyncReply watch_source_bus(GstBus *bus, GstMessage *message, gpointer user
|
||||
g_error_free(err);
|
||||
g_free(dbg_info);
|
||||
break;
|
||||
+ case GST_MESSAGE_TAG:
|
||||
+ {
|
||||
+ GstTagList *tag_list;
|
||||
+ gchar *printable;
|
||||
+ gst_message_parse_tag(message, &tag_list);
|
||||
+ if (tag_list)
|
||||
+ {
|
||||
+ printable = gst_tag_list_to_string(tag_list);
|
||||
+ if (printable)
|
||||
+ {
|
||||
+ TRACE("tag test: %s\n", debugstr_a(printable));
|
||||
+ g_free(printable);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ break;
|
||||
+ }
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -1138,6 +1172,10 @@ static HRESULT WINAPI media_source_QueryInterface(IMFMediaSource *iface, REFIID
|
||||
{
|
||||
*out = &source->IMFMediaSource_iface;
|
||||
}
|
||||
+ else if(IsEqualIID(riid, &IID_IMFGetService))
|
||||
+ {
|
||||
+ *out = &source->IMFGetService_iface;
|
||||
+ }
|
||||
else
|
||||
{
|
||||
FIXME("(%s, %p)\n", debugstr_guid(riid), out);
|
||||
@@ -1222,7 +1260,7 @@ static HRESULT WINAPI media_source_GetCharacteristics(IMFMediaSource *iface, DWO
|
||||
if (source->state == SOURCE_SHUTDOWN)
|
||||
return MF_E_SHUTDOWN;
|
||||
|
||||
- *characteristics = MFMEDIASOURCE_CAN_SEEK;
|
||||
+ *characteristics = MFMEDIASOURCE_CAN_SEEK | MFMEDIASOURCE_CAN_PAUSE;
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
@@ -1363,6 +1401,99 @@ static const IMFMediaSourceVtbl IMFMediaSource_vtbl =
|
||||
media_source_Shutdown,
|
||||
};
|
||||
|
||||
+static HRESULT WINAPI source_get_service_QueryInterface(IMFGetService *iface, REFIID riid, void **obj)
|
||||
+{
|
||||
+ struct media_source *source = impl_from_IMFGetService(iface);
|
||||
+ return IMFMediaSource_QueryInterface(&source->IMFMediaSource_iface, riid, obj);
|
||||
+}
|
||||
+
|
||||
+static ULONG WINAPI source_get_service_AddRef(IMFGetService *iface)
|
||||
+{
|
||||
+ struct media_source *source = impl_from_IMFGetService(iface);
|
||||
+ return IMFMediaSource_AddRef(&source->IMFMediaSource_iface);
|
||||
+}
|
||||
+
|
||||
+static ULONG WINAPI source_get_service_Release(IMFGetService *iface)
|
||||
+{
|
||||
+ struct media_source *source = impl_from_IMFGetService(iface);
|
||||
+ return IMFMediaSource_Release(&source->IMFMediaSource_iface);
|
||||
+}
|
||||
+
|
||||
+static HRESULT WINAPI source_get_service_GetService(IMFGetService *iface, REFGUID service, REFIID riid, void **obj)
|
||||
+{
|
||||
+ struct media_source *source = impl_from_IMFGetService(iface);
|
||||
+
|
||||
+ TRACE("(%p)->(%s, %s, %p)\n", source, debugstr_guid(service), debugstr_guid(riid), obj);
|
||||
+
|
||||
+ if (source->state == SOURCE_SHUTDOWN)
|
||||
+ return MF_E_SHUTDOWN;
|
||||
+
|
||||
+ *obj = NULL;
|
||||
+
|
||||
+ if (IsEqualIID(service, &MF_SCRUBBING_SERVICE))
|
||||
+ {
|
||||
+ if (IsEqualIID(riid, &IID_IMFSeekInfo))
|
||||
+ {
|
||||
+ *obj = &source->IMFSeekInfo_iface;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (*obj)
|
||||
+ IUnknown_AddRef((IUnknown*) *obj);
|
||||
+
|
||||
+ return *obj ? S_OK : E_NOINTERFACE;
|
||||
+}
|
||||
+
|
||||
+static const IMFGetServiceVtbl IMFGetService_vtbl =
|
||||
+{
|
||||
+ source_get_service_QueryInterface,
|
||||
+ source_get_service_AddRef,
|
||||
+ source_get_service_Release,
|
||||
+ source_get_service_GetService,
|
||||
+};
|
||||
+
|
||||
+static HRESULT WINAPI source_seek_info_QueryInterface(IMFSeekInfo *iface, REFIID riid, void **obj)
|
||||
+{
|
||||
+ struct media_source *source = impl_from_IMFSeekInfo(iface);
|
||||
+ return IMFMediaSource_QueryInterface(&source->IMFMediaSource_iface, riid, obj);
|
||||
+}
|
||||
+
|
||||
+static ULONG WINAPI source_seek_info_AddRef(IMFSeekInfo *iface)
|
||||
+{
|
||||
+ struct media_source *source = impl_from_IMFSeekInfo(iface);
|
||||
+ return IMFMediaSource_AddRef(&source->IMFMediaSource_iface);
|
||||
+}
|
||||
+
|
||||
+static ULONG WINAPI source_seek_info_Release(IMFSeekInfo *iface)
|
||||
+{
|
||||
+ struct media_source *source = impl_from_IMFSeekInfo(iface);
|
||||
+ return IMFMediaSource_Release(&source->IMFMediaSource_iface);
|
||||
+}
|
||||
+
|
||||
+static HRESULT WINAPI source_seek_info_GetNearestKeyFrames(IMFSeekInfo *iface, const GUID *format,
|
||||
+ const PROPVARIANT *position, PROPVARIANT *prev_frame, PROPVARIANT *next_frame)
|
||||
+{
|
||||
+ struct media_source *source = impl_from_IMFSeekInfo(iface);
|
||||
+
|
||||
+ FIXME("(%p)->(%s, %p, %p, %p) - semi-stub\n", source, debugstr_guid(format), position, prev_frame, next_frame);
|
||||
+
|
||||
+ if (source->state == SOURCE_SHUTDOWN)
|
||||
+ return MF_E_SHUTDOWN;
|
||||
+
|
||||
+ PropVariantCopy(prev_frame, position);
|
||||
+ PropVariantCopy(next_frame, position);
|
||||
+
|
||||
+ return S_OK;
|
||||
+}
|
||||
+
|
||||
+static const IMFSeekInfoVtbl IMFSeekInfo_vtbl =
|
||||
+{
|
||||
+ source_seek_info_QueryInterface,
|
||||
+ source_seek_info_AddRef,
|
||||
+ source_seek_info_Release,
|
||||
+ source_seek_info_GetNearestKeyFrames,
|
||||
+};
|
||||
+
|
||||
/* If this callback is extended to use any significant win32 APIs, a wrapper function
|
||||
should be added */
|
||||
gboolean stream_found(GstElement *bin, GstPad *pad, GstCaps *caps, gpointer user)
|
||||
@@ -1504,6 +1635,8 @@ static HRESULT media_source_constructor(IMFByteStream *bytestream, struct media_
|
||||
return E_OUTOFMEMORY;
|
||||
|
||||
object->IMFMediaSource_iface.lpVtbl = &IMFMediaSource_vtbl;
|
||||
+ object->IMFGetService_iface.lpVtbl = &IMFGetService_vtbl;
|
||||
+ object->IMFSeekInfo_iface.lpVtbl = &IMFSeekInfo_vtbl;
|
||||
object->async_commands_callback.lpVtbl = &source_async_commands_callback_vtbl;
|
||||
object->ref = 1;
|
||||
object->byte_stream = bytestream;
|
||||
@@ -1595,7 +1728,6 @@ static HRESULT media_source_constructor(IMFByteStream *bytestream, struct media_
|
||||
heap_free(descriptors);
|
||||
descriptors = NULL;
|
||||
|
||||
- /* miscelaneous presentation descriptor setup */
|
||||
{
|
||||
IMFAttributes *byte_stream_attributes;
|
||||
gint64 total_pres_time = 0;
|
||||
@@ -1612,6 +1744,7 @@ static HRESULT media_source_constructor(IMFByteStream *bytestream, struct media_
|
||||
IMFAttributes_Release(byte_stream_attributes);
|
||||
}
|
||||
|
||||
+ /* TODO: consider streams which don't start at T=0 */
|
||||
for (unsigned int i = 0; i < object->stream_count; i++)
|
||||
{
|
||||
GstQuery *query = gst_query_new_duration(GST_FORMAT_TIME);
|
||||
--
|
||||
2.28.0
|
||||
|
@ -1,55 +1,33 @@
|
||||
From 9a72ebab1d3dd0fdbe06a61ba473f019695477fe Mon Sep 17 00:00:00 2001
|
||||
From 827be0fc103c7439b64429e0063c57be4c1f3616 Mon Sep 17 00:00:00 2001
|
||||
From: Derek Lesho <dlesho@codeweavers.com>
|
||||
Date: Wed, 25 Mar 2020 19:07:11 -0500
|
||||
Subject: [PATCH 36/54] WMV
|
||||
Subject: [PATCH 29/52] WMV
|
||||
|
||||
---
|
||||
dlls/winegstreamer/gst_private.h | 2 +
|
||||
dlls/winegstreamer/media_source.c | 3 ++
|
||||
dlls/winegstreamer/gst_private.h | 1 +
|
||||
dlls/winegstreamer/mf_decode.c | 10 +++++
|
||||
dlls/winegstreamer/mfplat.c | 47 ++++++++++++++++++++
|
||||
dlls/winegstreamer/winegstreamer.rgs | 12 +++++
|
||||
dlls/winegstreamer/winegstreamer_classes.idl | 12 +++++
|
||||
dlls/winegstreamer/mfplat.c | 40 ++++++++++++++++++++
|
||||
dlls/winegstreamer/winegstreamer_classes.idl | 6 +++
|
||||
include/mfidl.idl | 2 +
|
||||
7 files changed, 88 insertions(+)
|
||||
5 files changed, 59 insertions(+)
|
||||
|
||||
diff --git a/dlls/winegstreamer/gst_private.h b/dlls/winegstreamer/gst_private.h
|
||||
index 6e25b895ff..0b61bc9e3c 100644
|
||||
index 5ff412c8e47..8651e3440e4 100644
|
||||
--- a/dlls/winegstreamer/gst_private.h
|
||||
+++ b/dlls/winegstreamer/gst_private.h
|
||||
@@ -66,11 +66,13 @@ enum decoder_type
|
||||
@@ -67,6 +67,7 @@ enum decoder_type
|
||||
{
|
||||
DECODER_TYPE_H264,
|
||||
DECODER_TYPE_AAC,
|
||||
+ DECODER_TYPE_WMV,
|
||||
};
|
||||
HRESULT generic_decoder_construct(REFIID riid, void **obj, enum decoder_type);
|
||||
enum source_type
|
||||
{
|
||||
SOURCE_TYPE_MPEG_4,
|
||||
+ SOURCE_TYPE_ASF,
|
||||
};
|
||||
HRESULT container_stream_handler_construct(REFIID riid, void **obj, enum source_type);
|
||||
|
||||
diff --git a/dlls/winegstreamer/media_source.c b/dlls/winegstreamer/media_source.c
|
||||
index 308b98c5e6..c66e211faf 100644
|
||||
--- a/dlls/winegstreamer/media_source.c
|
||||
+++ b/dlls/winegstreamer/media_source.c
|
||||
@@ -30,6 +30,9 @@ static struct source_desc
|
||||
{
|
||||
{/*SOURCE_TYPE_MPEG_4*/
|
||||
GST_STATIC_CAPS("video/quicktime"),
|
||||
+ },
|
||||
+ {/*SOURCE_TYPE_ASF*/
|
||||
+ GST_STATIC_CAPS("video/x-ms-asf"),
|
||||
}
|
||||
};
|
||||
|
||||
HRESULT generic_decoder_construct(REFIID riid, void **obj, enum decoder_type) DECLSPEC_HIDDEN;
|
||||
HRESULT winegstreamer_stream_handler_create(REFIID riid, void **obj) DECLSPEC_HIDDEN;
|
||||
diff --git a/dlls/winegstreamer/mf_decode.c b/dlls/winegstreamer/mf_decode.c
|
||||
index f5d9a83cd4..21b310a996 100644
|
||||
index 025af7b91ae..7f2dfc8f292 100644
|
||||
--- a/dlls/winegstreamer/mf_decode.c
|
||||
+++ b/dlls/winegstreamer/mf_decode.c
|
||||
@@ -28,6 +28,9 @@ const GUID *h264_output_types[] = {&MFVideoFormat_I420, &MFVideoFormat_IYUV, &MF
|
||||
@@ -29,6 +29,9 @@ const GUID *h264_output_types[] = {&MFVideoFormat_NV12, &MFVideoFormat_I420, &MF
|
||||
const GUID *aac_input_types[] = {&MFAudioFormat_AAC};
|
||||
const GUID *aac_output_types[] = {&MFAudioFormat_Float};
|
||||
|
||||
@ -59,7 +37,7 @@ index f5d9a83cd4..21b310a996 100644
|
||||
static struct decoder_desc
|
||||
{
|
||||
const GUID *major_type;
|
||||
@@ -50,6 +53,13 @@ static struct decoder_desc
|
||||
@@ -51,6 +54,13 @@ static struct decoder_desc
|
||||
ARRAY_SIZE(aac_input_types),
|
||||
aac_output_types,
|
||||
ARRAY_SIZE(aac_output_types),
|
||||
@ -74,10 +52,10 @@ index f5d9a83cd4..21b310a996 100644
|
||||
};
|
||||
|
||||
diff --git a/dlls/winegstreamer/mfplat.c b/dlls/winegstreamer/mfplat.c
|
||||
index aaef966a5b..e1735a5f82 100644
|
||||
index 167f2a185be..3e5925e32d2 100644
|
||||
--- a/dlls/winegstreamer/mfplat.c
|
||||
+++ b/dlls/winegstreamer/mfplat.c
|
||||
@@ -414,11 +414,21 @@ static HRESULT aac_decoder_create(REFIID riid, void **ret)
|
||||
@@ -416,6 +416,10 @@ static HRESULT aac_decoder_create(REFIID riid, void **ret)
|
||||
return generic_decoder_construct(riid, ret, DECODER_TYPE_AAC);
|
||||
}
|
||||
|
||||
@ -85,31 +63,18 @@ index aaef966a5b..e1735a5f82 100644
|
||||
+{
|
||||
+ return generic_decoder_construct(riid, ret, DECODER_TYPE_WMV);
|
||||
+}
|
||||
+
|
||||
static HRESULT mp4_stream_handler_create(REFIID riid, void **ret)
|
||||
{
|
||||
return container_stream_handler_construct(riid, ret, SOURCE_TYPE_MPEG_4);
|
||||
}
|
||||
|
||||
+static HRESULT asf_stream_handler_create(REFIID riid, void **ret)
|
||||
+{
|
||||
+ return container_stream_handler_construct(riid, ret, SOURCE_TYPE_ASF);
|
||||
+}
|
||||
+
|
||||
static const struct class_object
|
||||
{
|
||||
const GUID *clsid;
|
||||
@@ -429,7 +439,9 @@ class_objects[] =
|
||||
{ &CLSID_VideoProcessorMFT, &video_processor_create },
|
||||
@@ -427,6 +431,7 @@ class_objects[] =
|
||||
{ &CLSID_GStreamerByteStreamHandler, &winegstreamer_stream_handler_create },
|
||||
{ &CLSID_CMSH264DecoderMFT, &h264_decoder_create },
|
||||
{ &CLSID_CMSAACDecMFT, &aac_decoder_create },
|
||||
+ { &CLSID_CWMVDecMediaObject, &wmv_decoder_create },
|
||||
{ &CLSID_MPEG4ByteStreamHandler, &mp4_stream_handler_create },
|
||||
+ { &CLSID_ASFByteStreamHandler, &asf_stream_handler_create },
|
||||
};
|
||||
|
||||
HRESULT mfplat_get_class_object(REFCLSID rclsid, REFIID riid, void **obj)
|
||||
@@ -488,6 +500,29 @@ const GUID *aac_decoder_output_types[] =
|
||||
@@ -482,6 +487,29 @@ const GUID *aac_decoder_output_types[] =
|
||||
&MFAudioFormat_PCM,
|
||||
};
|
||||
|
||||
@ -139,7 +104,7 @@ index aaef966a5b..e1735a5f82 100644
|
||||
static const struct mft
|
||||
{
|
||||
const GUID *clsid;
|
||||
@@ -526,6 +561,18 @@ mfts[] =
|
||||
@@ -520,6 +548,18 @@ mfts[] =
|
||||
ARRAY_SIZE(aac_decoder_output_types),
|
||||
aac_decoder_output_types,
|
||||
NULL
|
||||
@ -158,63 +123,26 @@ index aaef966a5b..e1735a5f82 100644
|
||||
}
|
||||
};
|
||||
|
||||
diff --git a/dlls/winegstreamer/winegstreamer.rgs b/dlls/winegstreamer/winegstreamer.rgs
|
||||
index 0bc26761e9..9dbbca1c80 100644
|
||||
--- a/dlls/winegstreamer/winegstreamer.rgs
|
||||
+++ b/dlls/winegstreamer/winegstreamer.rgs
|
||||
@@ -23,6 +23,10 @@ HKLM
|
||||
{
|
||||
NoRemove 'ByteStreamHandlers'
|
||||
{
|
||||
+ '.asf'
|
||||
+ {
|
||||
+ val '{41457294-644C-4298-A28A-BD69F2C0CF3B}' = s 'ASF Byte Stream Handler'
|
||||
+ }
|
||||
'.m4v'
|
||||
{
|
||||
val '{271C3902-6095-4c45-A22F-20091816EE9E}' = s 'MPEG4 Byte Stream Handler'
|
||||
@@ -31,6 +35,14 @@ HKLM
|
||||
{
|
||||
val '{271C3902-6095-4c45-A22F-20091816EE9E}' = s 'MPEG4 Byte Stream Handler'
|
||||
}
|
||||
+ '.wma'
|
||||
+ {
|
||||
+ val '{41457294-644C-4298-A28A-BD69F2C0CF3B}' = s 'ASF Byte Stream Handler'
|
||||
+ }
|
||||
+ '.wmv'
|
||||
+ {
|
||||
+ val '{41457294-644C-4298-A28A-BD69F2C0CF3B}' = s 'ASF Byte Stream Handler'
|
||||
+ }
|
||||
'video/m4v'
|
||||
{
|
||||
val '{271C3902-6095-4c45-A22F-20091816EE9E}' = s 'MPEG4 Byte Stream Handler'
|
||||
diff --git a/dlls/winegstreamer/winegstreamer_classes.idl b/dlls/winegstreamer/winegstreamer_classes.idl
|
||||
index ee8090cf4a..376e08c418 100644
|
||||
index 3f28b4ddec4..f9b0158fa6a 100644
|
||||
--- a/dlls/winegstreamer/winegstreamer_classes.idl
|
||||
+++ b/dlls/winegstreamer/winegstreamer_classes.idl
|
||||
@@ -73,3 +73,15 @@ coclass CMSH264DecoderMFT { }
|
||||
@@ -73,3 +73,9 @@ coclass CMSH264DecoderMFT { }
|
||||
uuid(32d186a7-218f-4c75-8876-dd77273a8999)
|
||||
]
|
||||
coclass CMSAACDecMFT { }
|
||||
+
|
||||
+[
|
||||
+ threading(both),
|
||||
+ uuid(41457294-644c-4298-a28a-BD69F2C0CF3B)
|
||||
+]
|
||||
+coclass ASFByteStreamHandler {}
|
||||
+
|
||||
+[
|
||||
+ threading(both),
|
||||
+ uuid(82d353df-90bd-4382-8bc2-3f6192b76e34)
|
||||
+]
|
||||
+coclass CLSID_CWMVDecMediaObject {}
|
||||
\ No newline at end of file
|
||||
diff --git a/include/mfidl.idl b/include/mfidl.idl
|
||||
index f7092dfa6c..ce3707ba50 100644
|
||||
index 61c9a565415..0885e4e3007 100644
|
||||
--- a/include/mfidl.idl
|
||||
+++ b/include/mfidl.idl
|
||||
@@ -1244,3 +1244,5 @@ cpp_quote("EXTERN_GUID(CLSID_VideoProcessorMFT, 0x88753b26, 0x5b24, 0x49bd, 0xb2
|
||||
cpp_quote("EXTERN_GUID(CLSID_MPEG4ByteStreamHandler, 0x271c3902, 0x6095, 0x4c45, 0xa2, 0x2f, 0x20, 0x09, 0x18, 0x16, 0xee, 0x9e);")
|
||||
@@ -1243,3 +1243,5 @@ cpp_quote("EXTERN_GUID(MF_ACTIVATE_CUSTOM_VIDEO_PRESENTER_FLAGS, 0xba491366, 0xb
|
||||
cpp_quote("EXTERN_GUID(CLSID_VideoProcessorMFT, 0x88753b26, 0x5b24, 0x49bd, 0xb2, 0xe7, 0xc, 0x44, 0x5c, 0x78, 0xc9, 0x82);")
|
||||
cpp_quote("EXTERN_GUID(CLSID_CMSH264DecoderMFT, 0x62ce7e72, 0x4c71, 0x4d20, 0xb1, 0x5d, 0x45, 0x28, 0x31, 0xa8, 0x7d, 0x9d);")
|
||||
cpp_quote("EXTERN_GUID(CLSID_CMSAACDecMFT, 0x32d186a7, 0x218f, 0x4c75, 0x88, 0x76, 0xdd, 0x77, 0x27, 0x3a, 0x89, 0x99);")
|
||||
+cpp_quote("EXTERN_GUID(CLSID_ASFByteStreamHandler, 0x41457294, 0x644c, 0x4298, 0xa2, 0x8a, 0xbd, 0x69, 0xf2, 0xc0, 0xcf, 0x3b);")
|
@ -1,7 +1,7 @@
|
||||
From 478ac7d5e467e93a7a71ce1c8b2ebb227d89e034 Mon Sep 17 00:00:00 2001
|
||||
From 399609086d4527338991fae58e915da26c35ab7b Mon Sep 17 00:00:00 2001
|
||||
From: Derek Lesho <dlesho@codeweavers.com>
|
||||
Date: Thu, 2 Apr 2020 15:42:18 -0500
|
||||
Subject: [PATCH 37/54] mf: Ask for more samples from upstream node when upon
|
||||
Subject: [PATCH 30/52] mf: Ask for more samples from upstream node when upon
|
||||
MF_E_TRANSFORM_NEED_MORE_INPUT
|
||||
|
||||
---
|
||||
@ -9,10 +9,10 @@ Subject: [PATCH 37/54] mf: Ask for more samples from upstream node when upon
|
||||
1 file changed, 10 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/dlls/mf/session.c b/dlls/mf/session.c
|
||||
index e2a6b868ca..748df396d7 100644
|
||||
index a1b54b7080e..5bbbfe7d43e 100644
|
||||
--- a/dlls/mf/session.c
|
||||
+++ b/dlls/mf/session.c
|
||||
@@ -2451,6 +2451,8 @@ static HRESULT transform_node_pull_samples(struct topo_node *node)
|
||||
@@ -2503,6 +2503,8 @@ static HRESULT transform_node_pull_samples(struct topo_node *node)
|
||||
return hr;
|
||||
}
|
||||
|
||||
@ -21,7 +21,7 @@ index e2a6b868ca..748df396d7 100644
|
||||
static void session_deliver_sample_to_node(struct media_session *session, IMFTopologyNode *node, unsigned int input,
|
||||
IMFSample *sample)
|
||||
{
|
||||
@@ -2523,7 +2525,14 @@ static void session_deliver_sample_to_node(struct media_session *session, IMFTop
|
||||
@@ -2575,7 +2577,14 @@ static void session_deliver_sample_to_node(struct media_session *session, IMFTop
|
||||
WARN("Drain command failed for transform, hr %#x.\n", hr);
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
From 47d4811b9feead9bd1f4acbba67170d30561aa89 Mon Sep 17 00:00:00 2001
|
||||
From 5f2a5bce733fbe36f776d4bf4d823f6c7bc804ad Mon Sep 17 00:00:00 2001
|
||||
From: Derek Lesho <dlesho@codeweavers.com>
|
||||
Date: Thu, 2 Apr 2020 15:46:25 -0500
|
||||
Subject: [PATCH 40/54] winegstreamer: Implement
|
||||
Subject: [PATCH 31/52] winegstreamer: Implement
|
||||
IMFMedisStream::GetMediaSource.
|
||||
|
||||
---
|
||||
@ -9,10 +9,10 @@ Subject: [PATCH 40/54] winegstreamer: Implement
|
||||
1 file changed, 5 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/dlls/winegstreamer/media_source.c b/dlls/winegstreamer/media_source.c
|
||||
index c66e211faf..11b28176fd 100644
|
||||
index 919f46fd714..f0a654d1fa4 100644
|
||||
--- a/dlls/winegstreamer/media_source.c
|
||||
+++ b/dlls/winegstreamer/media_source.c
|
||||
@@ -842,12 +842,15 @@ static HRESULT WINAPI media_stream_GetMediaSource(IMFMediaStream *iface, IMFMedi
|
||||
@@ -784,12 +784,15 @@ static HRESULT WINAPI media_stream_GetMediaSource(IMFMediaStream *iface, IMFMedi
|
||||
{
|
||||
struct media_stream *stream = impl_from_IMFMediaStream(iface);
|
||||
|
@ -1,18 +1,18 @@
|
||||
From a88773344facfd8e308f5feb6f69e12c334690e6 Mon Sep 17 00:00:00 2001
|
||||
From 5c4b42745f37fbe626bdc540eca0e3fbe03fa9b2 Mon Sep 17 00:00:00 2001
|
||||
From: Derek Lesho <dlesho@codeweavers.com>
|
||||
Date: Fri, 3 Apr 2020 11:12:33 -0500
|
||||
Subject: [PATCH 41/54] Expose PCM output type on AAC decoder.
|
||||
Subject: [PATCH 32/52] Expose PCM output type on AAC decoder.
|
||||
|
||||
---
|
||||
dlls/winegstreamer/mf_decode.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/dlls/winegstreamer/mf_decode.c b/dlls/winegstreamer/mf_decode.c
|
||||
index 21b310a996..7fe216d67d 100644
|
||||
index 7f2dfc8f292..34bcde27a91 100644
|
||||
--- a/dlls/winegstreamer/mf_decode.c
|
||||
+++ b/dlls/winegstreamer/mf_decode.c
|
||||
@@ -26,7 +26,7 @@ const GUID *h264_input_types[] = {&MFVideoFormat_H264};
|
||||
const GUID *h264_output_types[] = {&MFVideoFormat_I420, &MFVideoFormat_IYUV, &MFVideoFormat_NV12, &MFVideoFormat_YUY2, &MFVideoFormat_YV12};
|
||||
@@ -27,7 +27,7 @@ const GUID *h264_input_types[] = {&MFVideoFormat_H264};
|
||||
const GUID *h264_output_types[] = {&MFVideoFormat_NV12, &MFVideoFormat_I420, &MFVideoFormat_IYUV, &MFVideoFormat_YUY2, &MFVideoFormat_YV12};
|
||||
|
||||
const GUID *aac_input_types[] = {&MFAudioFormat_AAC};
|
||||
-const GUID *aac_output_types[] = {&MFAudioFormat_Float};
|
@ -1,7 +1,7 @@
|
||||
From ba51cc01a42eb3cca95495afc42c68b7ec726ad8 Mon Sep 17 00:00:00 2001
|
||||
From 6e418d70ca7aa8e5e9468a1bdbcfc1ebec510f26 Mon Sep 17 00:00:00 2001
|
||||
From: Derek Lesho <dlesho@codeweavers.com>
|
||||
Date: Fri, 1 May 2020 11:46:26 -0500
|
||||
Subject: [PATCH 43/54] mfplat: Add I420 format information.
|
||||
Subject: [PATCH 33/52] mfplat: Add I420 format information.
|
||||
|
||||
Signed-off-by: Derek Lesho <dlesho@codeweavers.com>
|
||||
---
|
||||
@ -9,7 +9,7 @@ Signed-off-by: Derek Lesho <dlesho@codeweavers.com>
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
diff --git a/dlls/mfplat/mediatype.c b/dlls/mfplat/mediatype.c
|
||||
index 5eaa4fdd08..db789c4f8e 100644
|
||||
index 5eaa4fdd08d..db789c4f8e0 100644
|
||||
--- a/dlls/mfplat/mediatype.c
|
||||
+++ b/dlls/mfplat/mediatype.c
|
||||
@@ -2238,6 +2238,7 @@ static const struct uncompressed_video_format video_formats[] =
|
@ -1,387 +0,0 @@
|
||||
From 57240613380e0ea13b3adb0d2beada6e6528a0d5 Mon Sep 17 00:00:00 2001
|
||||
From: Derek Lesho <dlesho@codeweavers.com>
|
||||
Date: Mon, 16 Mar 2020 12:09:39 -0500
|
||||
Subject: [PATCH] winegstreamer: Implement decoder MFT on gstreamer.
|
||||
|
||||
---
|
||||
dlls/winegstreamer/Makefile.in | 1 +
|
||||
dlls/winegstreamer/gst_cbs.c | 65 ++++++++++
|
||||
dlls/winegstreamer/gst_cbs.h | 18 +++
|
||||
dlls/winegstreamer/gst_private.h | 7 ++
|
||||
dlls/winegstreamer/main.c | 3 +-
|
||||
dlls/winegstreamer/mfplat.c | 120 ++++++++++++++++++-
|
||||
dlls/winegstreamer/winegstreamer_classes.idl | 12 ++
|
||||
include/mfidl.idl | 4 +-
|
||||
8 files changed, 227 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/dlls/winegstreamer/Makefile.in b/dlls/winegstreamer/Makefile.in
|
||||
index f2e8749445..e2af408582 100644
|
||||
--- a/dlls/winegstreamer/Makefile.in
|
||||
+++ b/dlls/winegstreamer/Makefile.in
|
||||
@@ -13,6 +13,7 @@ C_SRCS = \
|
||||
main.c \
|
||||
media_source.c \
|
||||
mediatype.c \
|
||||
+ mf_decode.c \
|
||||
mfplat.c \
|
||||
pin.c \
|
||||
qualitycontrol.c \
|
||||
diff --git a/dlls/winegstreamer/gst_cbs.c b/dlls/winegstreamer/gst_cbs.c
|
||||
index d2d36aeb86..e392f4526f 100644
|
||||
--- a/dlls/winegstreamer/gst_cbs.c
|
||||
+++ b/dlls/winegstreamer/gst_cbs.c
|
||||
@@ -51,6 +51,8 @@ static void CALLBACK perform_cb(TP_CALLBACK_INSTANCE *instance, void *user)
|
||||
perform_cb_gstdemux(cbdata);
|
||||
else if (cbdata->type < MEDIA_SOURCE_MAX)
|
||||
perform_cb_media_source(cbdata);
|
||||
+ else if (cbdata->type < MF_DECODE_MAX)
|
||||
+ perform_cb_mf_decode(cbdata);
|
||||
|
||||
pthread_mutex_lock(&cbdata->lock);
|
||||
cbdata->finished = 1;
|
||||
@@ -414,5 +416,68 @@ GstFlowReturn stream_new_sample_wrapper(GstElement *appsink, gpointer user)
|
||||
|
||||
call_cb(&cbdata);
|
||||
|
||||
+ return cbdata.u.new_sample_data.ret;
|
||||
+}
|
||||
+
|
||||
+gboolean activate_push_mode_wrapper(GstPad *pad, GstObject *parent, GstPadMode mode, gboolean activate)
|
||||
+{
|
||||
+ struct cb_data cbdata = { ACTIVATE_PUSH_MODE };
|
||||
+
|
||||
+ 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.query_function_data.ret;
|
||||
+}
|
||||
+
|
||||
+gboolean query_input_src_wrapper(GstPad *pad, GstObject *parent, GstQuery *query)
|
||||
+{
|
||||
+ struct cb_data cbdata = { QUERY_INPUT_SRC };
|
||||
+
|
||||
+ 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;
|
||||
+}
|
||||
+
|
||||
+GstBusSyncReply watch_decoder_bus_wrapper(GstBus *bus, GstMessage *message, gpointer user)
|
||||
+{
|
||||
+ struct cb_data cbdata = { WATCH_DECODER_BUS };
|
||||
+
|
||||
+ 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 decoder_pad_added_wrapper(GstElement *element, GstPad *pad, gpointer user)
|
||||
+{
|
||||
+ struct cb_data cbdata = { DECODER_PAD_ADDED };
|
||||
+
|
||||
+ cbdata.u.pad_added_data.element = element;
|
||||
+ cbdata.u.pad_added_data.pad = pad;
|
||||
+ cbdata.u.pad_added_data.user = user;
|
||||
+
|
||||
+ call_cb(&cbdata);
|
||||
+}
|
||||
+
|
||||
+GstFlowReturn decoder_new_sample_wrapper(GstElement *appsink, gpointer user)
|
||||
+{
|
||||
+ struct cb_data cbdata = {DECODER_NEW_SAMPLE};
|
||||
+
|
||||
+ cbdata.u.new_sample_data.appsink = appsink;
|
||||
+ cbdata.u.new_sample_data.user = user;
|
||||
+
|
||||
+ call_cb(&cbdata);
|
||||
+
|
||||
return cbdata.u.new_sample_data.ret;
|
||||
}
|
||||
\ No newline at end of file
|
||||
diff --git a/dlls/winegstreamer/gst_cbs.h b/dlls/winegstreamer/gst_cbs.h
|
||||
index 106368a064..a35d6d8830 100644
|
||||
--- a/dlls/winegstreamer/gst_cbs.h
|
||||
+++ b/dlls/winegstreamer/gst_cbs.h
|
||||
@@ -54,6 +54,12 @@ enum CB_TYPE {
|
||||
SOURCE_ALL_STREAMS,
|
||||
STREAM_NEW_SAMPLE,
|
||||
MEDIA_SOURCE_MAX,
|
||||
+ ACTIVATE_PUSH_MODE,
|
||||
+ QUERY_INPUT_SRC,
|
||||
+ DECODER_NEW_SAMPLE,
|
||||
+ WATCH_DECODER_BUS,
|
||||
+ DECODER_PAD_ADDED,
|
||||
+ MF_DECODE_MAX,
|
||||
};
|
||||
|
||||
struct cb_data {
|
||||
@@ -143,6 +149,12 @@ struct cb_data {
|
||||
gpointer user;
|
||||
GstFlowReturn ret;
|
||||
} new_sample_data;
|
||||
+ struct chain_data {
|
||||
+ GstPad *pad;
|
||||
+ GstObject *parent;
|
||||
+ GstBuffer *buffer;
|
||||
+ GstFlowReturn ret;
|
||||
+ } chain_data;
|
||||
} u;
|
||||
|
||||
int finished;
|
||||
@@ -154,6 +166,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;
|
||||
+void perform_cb_mf_decode(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;
|
||||
@@ -179,5 +192,10 @@ void source_stream_added_wrapper(GstElement *bin, GstPad *pad, gpointer user) DE
|
||||
void source_stream_removed_wrapper(GstElement *element, GstPad *pad, gpointer user) DECLSPEC_HIDDEN;
|
||||
void source_all_streams_wrapper(GstElement *element, gpointer user) DECLSPEC_HIDDEN;
|
||||
GstFlowReturn stream_new_sample_wrapper(GstElement *appsink, gpointer user) DECLSPEC_HIDDEN;
|
||||
+gboolean activate_push_mode_wrapper(GstPad *pad, GstObject *parent, GstPadMode mode, gboolean activate) DECLSPEC_HIDDEN;
|
||||
+gboolean query_input_src_wrapper(GstPad *pad, GstObject *parent, GstQuery *query) DECLSPEC_HIDDEN;
|
||||
+GstBusSyncReply watch_decoder_bus_wrapper(GstBus *bus, GstMessage *message, gpointer user) DECLSPEC_HIDDEN;
|
||||
+GstFlowReturn decoder_new_sample_wrapper(GstElement *appsink, gpointer user) DECLSPEC_HIDDEN;
|
||||
+void decoder_pad_added_wrapper(GstElement *element, GstPad *Pad, gpointer user) DECLSPEC_HIDDEN;
|
||||
|
||||
#endif
|
||||
diff --git a/dlls/winegstreamer/gst_private.h b/dlls/winegstreamer/gst_private.h
|
||||
index 258df0d040..6e25b895ff 100644
|
||||
--- a/dlls/winegstreamer/gst_private.h
|
||||
+++ b/dlls/winegstreamer/gst_private.h
|
||||
@@ -53,6 +53,7 @@ BOOL init_gstreamer(void) DECLSPEC_HIDDEN;
|
||||
|
||||
void start_dispatch_thread(void) DECLSPEC_HIDDEN;
|
||||
|
||||
+extern HRESULT mfplat_DllRegisterServer(void) DECLSPEC_HIDDEN;
|
||||
extern HRESULT mfplat_get_class_object(REFCLSID rclsid, REFIID riid, void **obj) DECLSPEC_HIDDEN;
|
||||
|
||||
GstCaps *make_mf_compatible_caps(GstCaps *caps);
|
||||
@@ -61,6 +62,12 @@ GstCaps *caps_from_mf_media_type(IMFMediaType *type);
|
||||
IMFSample *mf_sample_from_gst_buffer(GstBuffer *in);
|
||||
GstBuffer *gst_buffer_from_mf_sample(IMFSample *in);
|
||||
|
||||
+enum decoder_type
|
||||
+{
|
||||
+ DECODER_TYPE_H264,
|
||||
+ DECODER_TYPE_AAC,
|
||||
+};
|
||||
+HRESULT generic_decoder_construct(REFIID riid, void **obj, enum decoder_type);
|
||||
enum source_type
|
||||
{
|
||||
SOURCE_TYPE_MPEG_4,
|
||||
diff --git a/dlls/winegstreamer/main.c b/dlls/winegstreamer/main.c
|
||||
index 2872710b3e..12ca11fa6c 100644
|
||||
--- a/dlls/winegstreamer/main.c
|
||||
+++ b/dlls/winegstreamer/main.c
|
||||
@@ -365,7 +365,8 @@ HRESULT WINAPI DllRegisterServer(void)
|
||||
IFilterMapper2_RegisterFilter(mapper, &CLSID_WAVEParser, wave_parserW, NULL, NULL, NULL, ®_wave_parser);
|
||||
|
||||
IFilterMapper2_Release(mapper);
|
||||
- return S_OK;
|
||||
+
|
||||
+ return mfplat_DllRegisterServer();
|
||||
}
|
||||
|
||||
HRESULT WINAPI DllUnregisterServer(void)
|
||||
diff --git a/dlls/winegstreamer/mfplat.c b/dlls/winegstreamer/mfplat.c
|
||||
index fe8ba885e9..31881399a9 100644
|
||||
--- a/dlls/winegstreamer/mfplat.c
|
||||
+++ b/dlls/winegstreamer/mfplat.c
|
||||
@@ -404,6 +404,16 @@ failed:
|
||||
return hr;
|
||||
}
|
||||
|
||||
+static HRESULT h264_decoder_create(REFIID riid, void **ret)
|
||||
+{
|
||||
+ return generic_decoder_construct(riid, ret, DECODER_TYPE_H264);
|
||||
+}
|
||||
+
|
||||
+static HRESULT aac_decoder_create(REFIID riid, void **ret)
|
||||
+{
|
||||
+ return generic_decoder_construct(riid, ret, DECODER_TYPE_AAC);
|
||||
+}
|
||||
+
|
||||
static HRESULT mp4_stream_handler_create(REFIID riid, void **ret)
|
||||
{
|
||||
return container_stream_handler_construct(riid, ret, SOURCE_TYPE_MPEG_4);
|
||||
@@ -417,6 +427,8 @@ static const struct class_object
|
||||
class_objects[] =
|
||||
{
|
||||
{ &CLSID_VideoProcessorMFT, &video_processor_create },
|
||||
+ { &CLSID_CMSH264DecoderMFT, &h264_decoder_create },
|
||||
+ { &CLSID_CMSAACDecMFT, &aac_decoder_create },
|
||||
{ &CLSID_MPEG4ByteStreamHandler, &mp4_stream_handler_create },
|
||||
};
|
||||
|
||||
@@ -449,6 +461,113 @@ HRESULT mfplat_get_class_object(REFCLSID rclsid, REFIID riid, void **obj)
|
||||
return CLASS_E_CLASSNOTAVAILABLE;
|
||||
}
|
||||
|
||||
+
|
||||
+static WCHAR h264decoderW[] = {'H','.','2','6','4',' ','D','e','c','o','d','e','r',0};
|
||||
+const GUID *h264_decoder_input_types[] =
|
||||
+{
|
||||
+ &MFVideoFormat_H264,
|
||||
+};
|
||||
+const GUID *h264_decoder_output_types[] =
|
||||
+{
|
||||
+ &MFVideoFormat_I420,
|
||||
+ &MFVideoFormat_IYUV,
|
||||
+ &MFVideoFormat_NV12,
|
||||
+ &MFVideoFormat_YUY2,
|
||||
+ &MFVideoFormat_YV12,
|
||||
+};
|
||||
+
|
||||
+static WCHAR aacdecoderW[] = {'A','A','C',' ','D','e','c','o','d','e','r',0};
|
||||
+const GUID *aac_decoder_input_types[] =
|
||||
+{
|
||||
+ &MFAudioFormat_AAC,
|
||||
+};
|
||||
+
|
||||
+const GUID *aac_decoder_output_types[] =
|
||||
+{
|
||||
+ &MFAudioFormat_Float,
|
||||
+ &MFAudioFormat_PCM,
|
||||
+};
|
||||
+
|
||||
+static const struct mft
|
||||
+{
|
||||
+ const GUID *clsid;
|
||||
+ const GUID *category;
|
||||
+ LPWSTR name;
|
||||
+ const UINT32 flags;
|
||||
+ const GUID *major_type;
|
||||
+ const UINT32 input_types_count;
|
||||
+ const GUID **input_types;
|
||||
+ const UINT32 output_types_count;
|
||||
+ const GUID **output_types;
|
||||
+ IMFAttributes *attributes;
|
||||
+}
|
||||
+mfts[] =
|
||||
+{
|
||||
+ {
|
||||
+ &CLSID_CMSH264DecoderMFT,
|
||||
+ &MFT_CATEGORY_VIDEO_DECODER,
|
||||
+ h264decoderW,
|
||||
+ MFT_ENUM_FLAG_SYNCMFT,
|
||||
+ &MFMediaType_Video,
|
||||
+ ARRAY_SIZE(h264_decoder_input_types),
|
||||
+ h264_decoder_input_types,
|
||||
+ ARRAY_SIZE(h264_decoder_output_types),
|
||||
+ h264_decoder_output_types,
|
||||
+ NULL
|
||||
+ },
|
||||
+ {
|
||||
+ &CLSID_CMSAACDecMFT,
|
||||
+ &MFT_CATEGORY_AUDIO_DECODER,
|
||||
+ aacdecoderW,
|
||||
+ MFT_ENUM_FLAG_SYNCMFT,
|
||||
+ &MFMediaType_Audio,
|
||||
+ ARRAY_SIZE(aac_decoder_input_types),
|
||||
+ aac_decoder_input_types,
|
||||
+ ARRAY_SIZE(aac_decoder_output_types),
|
||||
+ aac_decoder_output_types,
|
||||
+ NULL
|
||||
+ }
|
||||
+};
|
||||
+
|
||||
+HRESULT mfplat_DllRegisterServer(void)
|
||||
+{
|
||||
+ HRESULT hr;
|
||||
+ unsigned int i;
|
||||
+
|
||||
+ for (i = 0; i < ARRAY_SIZE(mfts); i++)
|
||||
+ {
|
||||
+ const struct mft *cur = &mfts[i];
|
||||
+ unsigned int j, k;
|
||||
+
|
||||
+ MFT_REGISTER_TYPE_INFO *input_types, *output_types;
|
||||
+ input_types = heap_alloc(cur->input_types_count * sizeof(input_types[0]));
|
||||
+ output_types = heap_alloc(cur->output_types_count * sizeof(output_types[0]));
|
||||
+ for (j = 0; j < cur->input_types_count; j++)
|
||||
+ {
|
||||
+ input_types[j].guidMajorType = *(cur->major_type);
|
||||
+ input_types[j].guidSubtype = *(cur->input_types[j]);
|
||||
+ }
|
||||
+ for (k = 0; k < cur->output_types_count; k++)
|
||||
+ {
|
||||
+ output_types[k].guidMajorType = *(cur->major_type);
|
||||
+ output_types[k].guidSubtype = *(cur->output_types[k]);
|
||||
+ }
|
||||
+
|
||||
+ hr = MFTRegister(*(cur->clsid), *(cur->category), cur->name, cur->flags, cur->input_types_count,
|
||||
+ input_types, cur->output_types_count, output_types, cur->attributes);
|
||||
+
|
||||
+ heap_free(input_types);
|
||||
+ heap_free(output_types);
|
||||
+
|
||||
+ if (FAILED(hr))
|
||||
+ {
|
||||
+ FIXME("Failed to register MFT, hr %#x\n", hr);
|
||||
+ return hr;
|
||||
+ }
|
||||
+ }
|
||||
+ return S_OK;
|
||||
+}
|
||||
+
|
||||
const static struct
|
||||
{
|
||||
const GUID *subtype;
|
||||
@@ -467,7 +586,6 @@ struct aac_user_data
|
||||
{
|
||||
WORD payload_type;
|
||||
WORD profile_level_indication;
|
||||
- WORD struct_type;
|
||||
WORD reserved;
|
||||
/* audio-specific-config is stored here */
|
||||
};
|
||||
diff --git a/dlls/winegstreamer/winegstreamer_classes.idl b/dlls/winegstreamer/winegstreamer_classes.idl
|
||||
index 997a28b052..ee8090cf4a 100644
|
||||
--- a/dlls/winegstreamer/winegstreamer_classes.idl
|
||||
+++ b/dlls/winegstreamer/winegstreamer_classes.idl
|
||||
@@ -61,3 +61,15 @@ coclass VideoProcessorMFT {}
|
||||
uuid(271c3902-6095-4c45-a22f-20091816ee9e)
|
||||
]
|
||||
coclass MPEG4ByteStreamHandler {}
|
||||
+
|
||||
+[
|
||||
+ threading(both),
|
||||
+ uuid(62ce7e72-4c71-4d20-b15d-452831a87d9d)
|
||||
+]
|
||||
+coclass CMSH264DecoderMFT { }
|
||||
+
|
||||
+[
|
||||
+ threading(both),
|
||||
+ uuid(32d186a7-218f-4c75-8876-dd77273a8999)
|
||||
+]
|
||||
+coclass CMSAACDecMFT { }
|
||||
diff --git a/include/mfidl.idl b/include/mfidl.idl
|
||||
index fc13dfba7a..f7092dfa6c 100644
|
||||
--- a/include/mfidl.idl
|
||||
+++ b/include/mfidl.idl
|
||||
@@ -1241,4 +1241,6 @@ cpp_quote("EXTERN_GUID(MF_ACTIVATE_CUSTOM_VIDEO_PRESENTER_ACTIVATE, 0xba491365,
|
||||
cpp_quote("EXTERN_GUID(MF_ACTIVATE_CUSTOM_VIDEO_PRESENTER_FLAGS, 0xba491366, 0xbe50, 0x451e, 0x95, 0xab, 0x6d, 0x4a, 0xcc, 0xc7, 0xda, 0xd8);")
|
||||
|
||||
cpp_quote("EXTERN_GUID(CLSID_VideoProcessorMFT, 0x88753b26, 0x5b24, 0x49bd, 0xb2, 0xe7, 0xc, 0x44, 0x5c, 0x78, 0xc9, 0x82);")
|
||||
-cpp_quote("EXTERN_GUID(CLSID_MPEG4ByteStreamHandler, 0x271c3902, 0x6095, 0x4c45, 0xa2, 0x2f, 0x20, 0x09, 0x18, 0x16, 0xee, 0x9e);")
|
||||
\ No newline at end of file
|
||||
+cpp_quote("EXTERN_GUID(CLSID_MPEG4ByteStreamHandler, 0x271c3902, 0x6095, 0x4c45, 0xa2, 0x2f, 0x20, 0x09, 0x18, 0x16, 0xee, 0x9e);")
|
||||
+cpp_quote("EXTERN_GUID(CLSID_CMSH264DecoderMFT, 0x62ce7e72, 0x4c71, 0x4d20, 0xb1, 0x5d, 0x45, 0x28, 0x31, 0xa8, 0x7d, 0x9d);")
|
||||
+cpp_quote("EXTERN_GUID(CLSID_CMSAACDecMFT, 0x32d186a7, 0x218f, 0x4c75, 0x88, 0x76, 0xdd, 0x77, 0x27, 0x3a, 0x89, 0x99);")
|
||||
--
|
||||
2.28.0
|
||||
|
@ -1,20 +1,20 @@
|
||||
From 532b311a83c2796e3014c11fe45f9f60e39736ee Mon Sep 17 00:00:00 2001
|
||||
From e37aca973f33356cbf1a4098d70a5ba4277be059 Mon Sep 17 00:00:00 2001
|
||||
From: Derek Lesho <dlesho@codeweavers.com>
|
||||
Date: Fri, 1 May 2020 13:20:49 -0500
|
||||
Subject: [PATCH] winegstreamer: Implement Color Converter MFT.
|
||||
Subject: [PATCH 34/52] winegstreamer: Implement Color Converter MFT.
|
||||
|
||||
Signed-off-by: Derek Lesho <dlesho@codeweavers.com>
|
||||
---
|
||||
dlls/winegstreamer/Makefile.in | 1 +
|
||||
dlls/winegstreamer/colorconvert.c | 707 +++++++++++++++++++
|
||||
dlls/winegstreamer/colorconvert.c | 704 +++++++++++++++++++
|
||||
dlls/winegstreamer/gst_private.h | 2 +
|
||||
dlls/winegstreamer/mfplat.c | 35 +
|
||||
dlls/winegstreamer/winegstreamer_classes.idl | 8 +-
|
||||
5 files changed, 752 insertions(+), 1 deletion(-)
|
||||
dlls/winegstreamer/mfplat.c | 36 +
|
||||
dlls/winegstreamer/winegstreamer_classes.idl | 6 +
|
||||
5 files changed, 749 insertions(+)
|
||||
create mode 100644 dlls/winegstreamer/colorconvert.c
|
||||
|
||||
diff --git a/dlls/winegstreamer/Makefile.in b/dlls/winegstreamer/Makefile.in
|
||||
index e2af408582..a266b0a95e 100644
|
||||
index e2af4085827..a266b0a95e4 100644
|
||||
--- a/dlls/winegstreamer/Makefile.in
|
||||
+++ b/dlls/winegstreamer/Makefile.in
|
||||
@@ -6,6 +6,7 @@ EXTRALIBS = $(GSTREAMER_LIBS) $(PTHREAD_LIBS)
|
||||
@ -27,10 +27,10 @@ index e2af408582..a266b0a95e 100644
|
||||
gstdemux.c \
|
||||
diff --git a/dlls/winegstreamer/colorconvert.c b/dlls/winegstreamer/colorconvert.c
|
||||
new file mode 100644
|
||||
index 0000000000..502ff52e56
|
||||
index 00000000000..f01373907ee
|
||||
--- /dev/null
|
||||
+++ b/dlls/winegstreamer/colorconvert.c
|
||||
@@ -0,0 +1,707 @@
|
||||
@@ -0,0 +1,704 @@
|
||||
+#include "config.h"
|
||||
+#include <gst/gst.h>
|
||||
+
|
||||
@ -46,7 +46,7 @@ index 0000000000..502ff52e56
|
||||
+
|
||||
+WINE_DEFAULT_DEBUG_CHANNEL(mfplat);
|
||||
+
|
||||
+const GUID *raw_types[] = {
|
||||
+static const GUID *raw_types[] = {
|
||||
+ &MFVideoFormat_RGB24,
|
||||
+ &MFVideoFormat_RGB32,
|
||||
+ &MFVideoFormat_RGB555,
|
||||
@ -349,7 +349,6 @@ index 0000000000..502ff52e56
|
||||
+ {
|
||||
+ GUID major_type, subtype;
|
||||
+ BOOL found = FALSE;
|
||||
+ unsigned int i;
|
||||
+
|
||||
+ if (FAILED(IMFMediaType_GetGUID(type, &MF_MT_MAJOR_TYPE, &major_type)))
|
||||
+ return MF_E_INVALIDTYPE;
|
||||
@ -359,7 +358,7 @@ index 0000000000..502ff52e56
|
||||
+ if (!(IsEqualGUID(&major_type, &MFMediaType_Video)))
|
||||
+ return MF_E_INVALIDTYPE;
|
||||
+
|
||||
+ for (i = 0; i < ARRAY_SIZE(raw_types); i++)
|
||||
+ for (unsigned int i = 0; i < ARRAY_SIZE(raw_types); i++)
|
||||
+ {
|
||||
+ UINT64 unused;
|
||||
+
|
||||
@ -422,7 +421,6 @@ index 0000000000..502ff52e56
|
||||
+
|
||||
+ if (type)
|
||||
+ {
|
||||
+ unsigned int i;
|
||||
+ /* validate the type */
|
||||
+
|
||||
+ if (FAILED(IMFMediaType_GetGUID(type, &MF_MT_MAJOR_TYPE, &major_type)))
|
||||
@ -435,7 +433,7 @@ index 0000000000..502ff52e56
|
||||
+ if (!(IsEqualGUID(&major_type, &MFMediaType_Video)))
|
||||
+ return MF_E_INVALIDTYPE;
|
||||
+
|
||||
+ for (i = 0; i < ARRAY_SIZE(raw_types); i++)
|
||||
+ for (unsigned int i = 0; i < ARRAY_SIZE(raw_types); i++)
|
||||
+ {
|
||||
+ if (IsEqualGUID(&subtype, raw_types[i]))
|
||||
+ break;
|
||||
@ -522,7 +520,7 @@ index 0000000000..502ff52e56
|
||||
+{
|
||||
+ FIXME("%p, %u.\n", iface, message);
|
||||
+
|
||||
+ return E_NOTIMPL;
|
||||
+ return S_OK;
|
||||
+}
|
||||
+
|
||||
+static HRESULT WINAPI color_converter_ProcessInput(IMFTransform *iface, DWORD id, IMFSample *sample, DWORD flags)
|
||||
@ -584,14 +582,13 @@ index 0000000000..502ff52e56
|
||||
+ MFT_OUTPUT_DATA_BUFFER *relevant_buffer = NULL;
|
||||
+ GstSample *sample;
|
||||
+ HRESULT hr = S_OK;
|
||||
+ unsigned int i;
|
||||
+
|
||||
+ TRACE("%p, %#x, %u, %p, %p.\n", iface, flags, count, samples, status);
|
||||
+
|
||||
+ if (flags)
|
||||
+ WARN("Unsupported flags %#x\n", flags);
|
||||
+
|
||||
+ for (i = 0; i < count; i++)
|
||||
+ for (unsigned int i = 0; i < count; i++)
|
||||
+ {
|
||||
+ MFT_OUTPUT_DATA_BUFFER *out_buffer = &samples[i];
|
||||
+
|
||||
@ -740,38 +737,39 @@ index 0000000000..502ff52e56
|
||||
+}
|
||||
\ No newline at end of file
|
||||
diff --git a/dlls/winegstreamer/gst_private.h b/dlls/winegstreamer/gst_private.h
|
||||
index 0b61bc9e3c..b855d650dc 100644
|
||||
index 8651e3440e4..c41f231f35f 100644
|
||||
--- a/dlls/winegstreamer/gst_private.h
|
||||
+++ b/dlls/winegstreamer/gst_private.h
|
||||
@@ -76,4 +76,6 @@ enum source_type
|
||||
};
|
||||
HRESULT container_stream_handler_construct(REFIID riid, void **obj, enum source_type);
|
||||
@@ -72,4 +72,6 @@ enum decoder_type
|
||||
HRESULT generic_decoder_construct(REFIID riid, void **obj, enum decoder_type) DECLSPEC_HIDDEN;
|
||||
HRESULT winegstreamer_stream_handler_create(REFIID riid, void **obj) DECLSPEC_HIDDEN;
|
||||
|
||||
+HRESULT color_converter_create(REFIID riid, void **ret);
|
||||
+
|
||||
#endif /* __GST_PRIVATE_INCLUDED__ */
|
||||
diff --git a/dlls/winegstreamer/mfplat.c b/dlls/winegstreamer/mfplat.c
|
||||
index 68071fccf9..e63b4dcb2f 100644
|
||||
index 3e5925e32d2..429a2cfda1c 100644
|
||||
--- a/dlls/winegstreamer/mfplat.c
|
||||
+++ b/dlls/winegstreamer/mfplat.c
|
||||
@@ -429,6 +429,8 @@ static HRESULT asf_stream_handler_create(REFIID riid, void **ret)
|
||||
return container_stream_handler_construct(riid, ret, SOURCE_TYPE_ASF);
|
||||
@@ -420,6 +420,9 @@ static HRESULT wmv_decoder_create(REFIID riid, void **ret)
|
||||
{
|
||||
return generic_decoder_construct(riid, ret, DECODER_TYPE_WMV);
|
||||
}
|
||||
|
||||
+
|
||||
+static GUID CLSID_CColorConvertDMO = {0x98230571,0x0087,0x4204,{0xb0,0x20,0x32,0x82,0x53,0x8e,0x57,0xd3}};
|
||||
+
|
||||
static const struct class_object
|
||||
{
|
||||
const GUID *clsid;
|
||||
@@ -442,6 +444,7 @@ class_objects[] =
|
||||
@@ -432,6 +435,7 @@ class_objects[] =
|
||||
{ &CLSID_CMSH264DecoderMFT, &h264_decoder_create },
|
||||
{ &CLSID_CMSAACDecMFT, &aac_decoder_create },
|
||||
{ &CLSID_CWMVDecMediaObject, &wmv_decoder_create },
|
||||
{ &CLSID_MPEG4ByteStreamHandler, &mp4_stream_handler_create },
|
||||
{ &CLSID_ASFByteStreamHandler, &asf_stream_handler_create },
|
||||
+ { &CLSID_CColorConvertDMO, &color_converter_create },
|
||||
};
|
||||
|
||||
HRESULT mfplat_get_class_object(REFCLSID rclsid, REFIID riid, void **obj)
|
||||
@@ -473,6 +476,26 @@ HRESULT mfplat_get_class_object(REFCLSID rclsid, REFIID riid, void **obj)
|
||||
@@ -460,6 +464,26 @@ HRESULT mfplat_get_class_object(REFCLSID rclsid, REFIID riid, void **obj)
|
||||
return CLASS_E_CLASSNOTAVAILABLE;
|
||||
}
|
||||
|
||||
@ -798,7 +796,7 @@ index 68071fccf9..e63b4dcb2f 100644
|
||||
|
||||
static WCHAR h264decoderW[] = {'H','.','2','6','4',' ','D','e','c','o','d','e','r',0};
|
||||
const GUID *h264_decoder_input_types[] =
|
||||
@@ -538,6 +561,18 @@ static const struct mft
|
||||
@@ -525,6 +549,18 @@ static const struct mft
|
||||
}
|
||||
mfts[] =
|
||||
{
|
||||
@ -818,23 +816,19 @@ index 68071fccf9..e63b4dcb2f 100644
|
||||
&CLSID_CMSH264DecoderMFT,
|
||||
&MFT_CATEGORY_VIDEO_DECODER,
|
||||
diff --git a/dlls/winegstreamer/winegstreamer_classes.idl b/dlls/winegstreamer/winegstreamer_classes.idl
|
||||
index 376e08c418..d933d40cfd 100644
|
||||
index f9b0158fa6a..1556b6cff9f 100644
|
||||
--- a/dlls/winegstreamer/winegstreamer_classes.idl
|
||||
+++ b/dlls/winegstreamer/winegstreamer_classes.idl
|
||||
@@ -84,4 +84,10 @@ coclass ASFByteStreamHandler {}
|
||||
threading(both),
|
||||
@@ -79,3 +79,9 @@ coclass CMSAACDecMFT { }
|
||||
uuid(82d353df-90bd-4382-8bc2-3f6192b76e34)
|
||||
]
|
||||
-coclass CLSID_CWMVDecMediaObject {}
|
||||
\ No newline at end of file
|
||||
+coclass CLSID_CWMVDecMediaObject {}
|
||||
coclass CLSID_CWMVDecMediaObject {}
|
||||
+
|
||||
+[
|
||||
+ threading(both),
|
||||
+ uuid(98230571-0087-4204-b020-3282538e57d3)
|
||||
+]
|
||||
+coclass CColorConvertDMO { }
|
||||
\ No newline at end of file
|
||||
--
|
||||
2.28.0
|
||||
|
@ -1,17 +1,17 @@
|
||||
From 97211ce51e21d1b1fd7f6fe1bf442f0ce5152f7b Mon Sep 17 00:00:00 2001
|
||||
From b4985eaef1d9feb4c67b2b468a67bd550b68c545 Mon Sep 17 00:00:00 2001
|
||||
From: Derek Lesho <dlesho@codeweavers.com>
|
||||
Date: Fri, 1 May 2020 22:36:02 -0500
|
||||
Subject: [PATCH 45/54] HACK: Set BPS to 16 for output template.
|
||||
Subject: [PATCH 35/52] HACK: Set BPS to 16 for output template.
|
||||
|
||||
---
|
||||
dlls/winegstreamer/mf_decode.c | 5 +++++
|
||||
1 file changed, 5 insertions(+)
|
||||
|
||||
diff --git a/dlls/winegstreamer/mf_decode.c b/dlls/winegstreamer/mf_decode.c
|
||||
index 7fe216d67d..c7e1bfb1a9 100644
|
||||
index 34bcde27a91..a86e9db410e 100644
|
||||
--- a/dlls/winegstreamer/mf_decode.c
|
||||
+++ b/dlls/winegstreamer/mf_decode.c
|
||||
@@ -321,6 +321,11 @@ static HRESULT WINAPI mf_decoder_GetOutputAvailableType(IMFTransform *iface, DWO
|
||||
@@ -322,6 +322,11 @@ static HRESULT WINAPI mf_decoder_GetOutputAvailableType(IMFTransform *iface, DWO
|
||||
return hr;
|
||||
}
|
||||
|
5270
patches/mfplat-streaming-support/0036-Improve-tests.patch
Normal file
5270
patches/mfplat-streaming-support/0036-Improve-tests.patch
Normal file
File diff suppressed because it is too large
Load Diff
5271
patches/mfplat-streaming-support/0037-Revert-Improve-tests.patch
Normal file
5271
patches/mfplat-streaming-support/0037-Revert-Improve-tests.patch
Normal file
File diff suppressed because it is too large
Load Diff
@ -1,28 +1,28 @@
|
||||
From cffa1c6ab7784bc9a7d7c411e204d2abb7bbb501 Mon Sep 17 00:00:00 2001
|
||||
From 7d34ffde0e719704327c261443d0e8dbead7d79f Mon Sep 17 00:00:00 2001
|
||||
From: Derek Lesho <dlesho@codeweavers.com>
|
||||
Date: Tue, 5 May 2020 15:35:16 -0500
|
||||
Subject: [PATCH] Report streams backwards and only select one of each stream
|
||||
type.
|
||||
Subject: [PATCH 38/52] Report streams backwards and only select one of each
|
||||
stream type.
|
||||
|
||||
---
|
||||
dlls/winegstreamer/media_source.c | 24 ++++++++++++++++++++++--
|
||||
1 file changed, 22 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/dlls/winegstreamer/media_source.c b/dlls/winegstreamer/media_source.c
|
||||
index 0165ea1570..3807a37555 100644
|
||||
index f0a654d1fa4..14b7571b80a 100644
|
||||
--- a/dlls/winegstreamer/media_source.c
|
||||
+++ b/dlls/winegstreamer/media_source.c
|
||||
@@ -1438,6 +1438,7 @@ static HRESULT media_source_constructor(IMFByteStream *bytestream, enum source_t
|
||||
source_descs[type].bytestream_caps);
|
||||
@@ -1630,6 +1630,7 @@ static HRESULT media_source_constructor(IMFByteStream *bytestream, struct media_
|
||||
GST_STATIC_CAPS_ANY);
|
||||
|
||||
struct media_source *object = heap_alloc_zero(sizeof(*object));
|
||||
+ BOOL video_selected = FALSE, audio_selected = FALSE;
|
||||
GList *demuxer_list_one, *demuxer_list_two;
|
||||
GstElementFactory *demuxer_factory = NULL;
|
||||
IMFStreamDescriptor **descriptors = NULL;
|
||||
@@ -1535,15 +1536,34 @@ static HRESULT media_source_constructor(IMFByteStream *bytestream, enum source_t
|
||||
HRESULT hr;
|
||||
int ret;
|
||||
@@ -1717,15 +1718,34 @@ static HRESULT media_source_constructor(IMFByteStream *bytestream, struct media_
|
||||
descriptors = heap_alloc(object->stream_count * sizeof(IMFStreamDescriptor*));
|
||||
for (i = 0; i < object->stream_count; i++)
|
||||
for (unsigned int i = 0; i < object->stream_count; i++)
|
||||
{
|
||||
- IMFMediaStream_GetStreamDescriptor(&object->streams[i]->IMFMediaStream_iface, &descriptors[i]);
|
||||
+ IMFMediaStream_GetStreamDescriptor(&object->streams[i]->IMFMediaStream_iface, &descriptors[object->stream_count - 1 - i]);
|
||||
@ -32,7 +32,7 @@ index 0165ea1570..3807a37555 100644
|
||||
goto fail;
|
||||
|
||||
+ /* Select one of each major type. */
|
||||
for (i = 0; i < object->stream_count; i++)
|
||||
for (unsigned int i = 0; i < object->stream_count; i++)
|
||||
{
|
||||
- IMFPresentationDescriptor_SelectStream(object->pres_desc, i);
|
||||
+ IMFMediaTypeHandler *handler;
|
@ -1,18 +1,18 @@
|
||||
From fac27f9bb91686dddfc85d367514b21db135b6a8 Mon Sep 17 00:00:00 2001
|
||||
From 0ccd1eb9ac722329ed137b49a260a0458ca86a0c Mon Sep 17 00:00:00 2001
|
||||
From: Derek Lesho <dlesho@codeweavers.com>
|
||||
Date: Thu, 7 May 2020 13:09:47 -0500
|
||||
Subject: [PATCH] winegstreamer: Implement IMFMediaSource::Stop.
|
||||
Subject: [PATCH 39/52] winegstreamer: Implement IMFMediaSource::Stop.
|
||||
|
||||
Signed-off-by: Derek Lesho <dlesho@codeweavers.com>
|
||||
---
|
||||
dlls/winegstreamer/media_source.c | 32 +++++++++++++++++++++++++++++--
|
||||
1 file changed, 30 insertions(+), 2 deletions(-)
|
||||
dlls/winegstreamer/media_source.c | 30 ++++++++++++++++++++++++++++--
|
||||
1 file changed, 28 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/dlls/winegstreamer/media_source.c b/dlls/winegstreamer/media_source.c
|
||||
index 3807a37555..517e5ee677 100644
|
||||
index 14b7571b80a..a162bad99d8 100644
|
||||
--- a/dlls/winegstreamer/media_source.c
|
||||
+++ b/dlls/winegstreamer/media_source.c
|
||||
@@ -60,6 +60,7 @@ struct media_stream
|
||||
@@ -68,6 +68,7 @@ struct media_stream
|
||||
enum source_async_op
|
||||
{
|
||||
SOURCE_ASYNC_START,
|
||||
@ -20,15 +20,16 @@ index 3807a37555..517e5ee677 100644
|
||||
SOURCE_ASYNC_REQUEST_SAMPLE,
|
||||
};
|
||||
|
||||
@@ -328,6 +329,25 @@ static HRESULT start_pipeline(struct media_source *source, struct source_async_c
|
||||
@@ -360,6 +361,23 @@ static HRESULT start_pipeline(struct media_source *source, struct source_async_c
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
+static void stop_pipeline(struct media_source *source)
|
||||
+{
|
||||
+ unsigned int i;
|
||||
+ /* TODO: seek to beginning */
|
||||
+ gst_element_set_state(source->container, GST_STATE_PAUSED);
|
||||
+
|
||||
+ for (i = 0; i < source->stream_count; i++)
|
||||
+ for (unsigned int i = 0; i < source->stream_count; i++)
|
||||
+ {
|
||||
+ struct media_stream *stream = source->streams[i];
|
||||
+ if (stream->state != STREAM_INACTIVE)
|
||||
@ -38,15 +39,12 @@ index 3807a37555..517e5ee677 100644
|
||||
+ IMFMediaEventQueue_QueueEventParamVar(source->event_queue, MESourceStopped, &GUID_NULL, S_OK, NULL);
|
||||
+
|
||||
+ source->state = SOURCE_STOPPED;
|
||||
+
|
||||
+ gst_element_set_state(source->container, GST_STATE_READY);
|
||||
+ gst_element_get_state(source->container, NULL, NULL, -1);
|
||||
+}
|
||||
+
|
||||
static void dispatch_end_of_presentation(struct media_source *source)
|
||||
{
|
||||
PROPVARIANT empty = {.vt = VT_EMPTY};
|
||||
@@ -419,6 +439,9 @@ static HRESULT WINAPI source_async_commands_Invoke(IMFAsyncCallback *iface, IMFA
|
||||
@@ -451,6 +469,9 @@ static HRESULT WINAPI source_async_commands_Invoke(IMFAsyncCallback *iface, IMFA
|
||||
case SOURCE_ASYNC_START:
|
||||
start_pipeline(source, command);
|
||||
break;
|
||||
@ -56,7 +54,7 @@ index 3807a37555..517e5ee677 100644
|
||||
case SOURCE_ASYNC_REQUEST_SAMPLE:
|
||||
wait_on_sample(command->u.request_sample.stream, command->u.request_sample.token);
|
||||
break;
|
||||
@@ -1249,13 +1272,18 @@ static HRESULT WINAPI media_source_Start(IMFMediaSource *iface, IMFPresentationD
|
||||
@@ -1319,13 +1340,18 @@ static HRESULT WINAPI media_source_Start(IMFMediaSource *iface, IMFPresentationD
|
||||
static HRESULT WINAPI media_source_Stop(IMFMediaSource *iface)
|
||||
{
|
||||
struct media_source *source = impl_from_IMFMediaSource(iface);
|
@ -1,7 +1,7 @@
|
||||
From 6f5d0e6c4694d6dab828318998ed6f5c1c33b27a Mon Sep 17 00:00:00 2001
|
||||
From aa97104ccc89cd65593354eb51c480454f17e2dd Mon Sep 17 00:00:00 2001
|
||||
From: Derek Lesho <dlesho@codeweavers.com>
|
||||
Date: Mon, 11 May 2020 16:05:50 -0500
|
||||
Subject: [PATCH 49/54] winegstreamer: Introduce MPEG-4 Section-2 video
|
||||
Subject: [PATCH 40/52] winegstreamer: Introduce MPEG-4 Section-2 video
|
||||
decoder.
|
||||
|
||||
Signed-off-by: Derek Lesho <dlesho@codeweavers.com>
|
||||
@ -14,22 +14,22 @@ Signed-off-by: Derek Lesho <dlesho@codeweavers.com>
|
||||
5 files changed, 52 insertions(+)
|
||||
|
||||
diff --git a/dlls/winegstreamer/gst_private.h b/dlls/winegstreamer/gst_private.h
|
||||
index b855d650dc..6dc90e2881 100644
|
||||
index c41f231f35f..b609afa555d 100644
|
||||
--- a/dlls/winegstreamer/gst_private.h
|
||||
+++ b/dlls/winegstreamer/gst_private.h
|
||||
@@ -67,6 +67,7 @@ enum decoder_type
|
||||
@@ -68,6 +68,7 @@ enum decoder_type
|
||||
DECODER_TYPE_H264,
|
||||
DECODER_TYPE_AAC,
|
||||
DECODER_TYPE_WMV,
|
||||
+ DECODER_TYPE_M4S2,
|
||||
};
|
||||
HRESULT generic_decoder_construct(REFIID riid, void **obj, enum decoder_type);
|
||||
enum source_type
|
||||
HRESULT generic_decoder_construct(REFIID riid, void **obj, enum decoder_type) DECLSPEC_HIDDEN;
|
||||
HRESULT winegstreamer_stream_handler_create(REFIID riid, void **obj) DECLSPEC_HIDDEN;
|
||||
diff --git a/dlls/winegstreamer/mf_decode.c b/dlls/winegstreamer/mf_decode.c
|
||||
index c7e1bfb1a9..633a468ed3 100644
|
||||
index a86e9db410e..c5d9cbad392 100644
|
||||
--- a/dlls/winegstreamer/mf_decode.c
|
||||
+++ b/dlls/winegstreamer/mf_decode.c
|
||||
@@ -31,6 +31,9 @@ const GUID *aac_output_types[] = {&MFAudioFormat_Float, &MFAudioFormat_PCM};
|
||||
@@ -32,6 +32,9 @@ const GUID *aac_output_types[] = {&MFAudioFormat_Float, &MFAudioFormat_PCM};
|
||||
const GUID *wmv_input_types[] = {&MFVideoFormat_WMV3, &MFVideoFormat_WVC1};
|
||||
const GUID *wmv_output_types[] = {&MFVideoFormat_NV12, &MFVideoFormat_YV12, &MFVideoFormat_YUY2, &MFVideoFormat_UYVY, &MFVideoFormat_YVYU, &MFVideoFormat_NV11, &MFVideoFormat_RGB32, &MFVideoFormat_RGB24, &MFVideoFormat_RGB555, &MFVideoFormat_RGB8};
|
||||
|
||||
@ -39,7 +39,7 @@ index c7e1bfb1a9..633a468ed3 100644
|
||||
static struct decoder_desc
|
||||
{
|
||||
const GUID *major_type;
|
||||
@@ -60,6 +63,13 @@ static struct decoder_desc
|
||||
@@ -61,6 +64,13 @@ static struct decoder_desc
|
||||
ARRAY_SIZE(wmv_input_types),
|
||||
wmv_output_types,
|
||||
ARRAY_SIZE(wmv_output_types),
|
||||
@ -54,10 +54,10 @@ index c7e1bfb1a9..633a468ed3 100644
|
||||
};
|
||||
|
||||
diff --git a/dlls/winegstreamer/mfplat.c b/dlls/winegstreamer/mfplat.c
|
||||
index 161c8032a7..e0da02074e 100644
|
||||
index 429a2cfda1c..5fe7ac4d354 100644
|
||||
--- a/dlls/winegstreamer/mfplat.c
|
||||
+++ b/dlls/winegstreamer/mfplat.c
|
||||
@@ -419,6 +419,11 @@ static HRESULT wmv_decoder_create(REFIID riid, void **ret)
|
||||
@@ -421,6 +421,11 @@ static HRESULT wmv_decoder_create(REFIID riid, void **ret)
|
||||
return generic_decoder_construct(riid, ret, DECODER_TYPE_WMV);
|
||||
}
|
||||
|
||||
@ -66,18 +66,18 @@ index 161c8032a7..e0da02074e 100644
|
||||
+ return generic_decoder_construct(riid, ret, DECODER_TYPE_M4S2);
|
||||
+}
|
||||
+
|
||||
static HRESULT mp4_stream_handler_create(REFIID riid, void **ret)
|
||||
{
|
||||
return container_stream_handler_construct(riid, ret, SOURCE_TYPE_MPEG_4);
|
||||
@@ -442,6 +447,7 @@ class_objects[] =
|
||||
static GUID CLSID_CColorConvertDMO = {0x98230571,0x0087,0x4204,{0xb0,0x20,0x32,0x82,0x53,0x8e,0x57,0xd3}};
|
||||
|
||||
static const struct class_object
|
||||
@@ -435,6 +440,7 @@ class_objects[] =
|
||||
{ &CLSID_CMSH264DecoderMFT, &h264_decoder_create },
|
||||
{ &CLSID_CMSAACDecMFT, &aac_decoder_create },
|
||||
{ &CLSID_CWMVDecMediaObject, &wmv_decoder_create },
|
||||
+ { &CLSID_CMpeg4sDecMFT, m4s2_decoder_create },
|
||||
{ &CLSID_MPEG4ByteStreamHandler, &mp4_stream_handler_create },
|
||||
{ &CLSID_ASFByteStreamHandler, &asf_stream_handler_create },
|
||||
{ &CLSID_CColorConvertDMO, &color_converter_create },
|
||||
@@ -546,6 +552,22 @@ const GUID *wmv_decoder_output_types[] =
|
||||
};
|
||||
|
||||
@@ -534,6 +540,22 @@ const GUID *wmv_decoder_output_types[] =
|
||||
&MFVideoFormat_RGB8,
|
||||
};
|
||||
|
||||
@ -100,7 +100,7 @@ index 161c8032a7..e0da02074e 100644
|
||||
static const struct mft
|
||||
{
|
||||
const GUID *clsid;
|
||||
@@ -608,6 +630,18 @@ mfts[] =
|
||||
@@ -596,6 +618,18 @@ mfts[] =
|
||||
ARRAY_SIZE(wmv_decoder_output_types),
|
||||
wmv_decoder_output_types,
|
||||
NULL
|
||||
@ -120,7 +120,7 @@ index 161c8032a7..e0da02074e 100644
|
||||
};
|
||||
|
||||
diff --git a/dlls/winegstreamer/winegstreamer_classes.idl b/dlls/winegstreamer/winegstreamer_classes.idl
|
||||
index d933d40cfd..3a3daad3ab 100644
|
||||
index 1556b6cff9f..5969eaa591a 100644
|
||||
--- a/dlls/winegstreamer/winegstreamer_classes.idl
|
||||
+++ b/dlls/winegstreamer/winegstreamer_classes.idl
|
||||
@@ -74,6 +74,12 @@ coclass CMSH264DecoderMFT { }
|
||||
@ -135,13 +135,13 @@ index d933d40cfd..3a3daad3ab 100644
|
||||
+
|
||||
[
|
||||
threading(both),
|
||||
uuid(41457294-644c-4298-a28a-BD69F2C0CF3B)
|
||||
uuid(82d353df-90bd-4382-8bc2-3f6192b76e34)
|
||||
diff --git a/include/mfidl.idl b/include/mfidl.idl
|
||||
index ce3707ba50..35dd4c2f96 100644
|
||||
index 0885e4e3007..a344986a7aa 100644
|
||||
--- a/include/mfidl.idl
|
||||
+++ b/include/mfidl.idl
|
||||
@@ -1244,5 +1244,6 @@ cpp_quote("EXTERN_GUID(CLSID_VideoProcessorMFT, 0x88753b26, 0x5b24, 0x49bd, 0xb2
|
||||
cpp_quote("EXTERN_GUID(CLSID_MPEG4ByteStreamHandler, 0x271c3902, 0x6095, 0x4c45, 0xa2, 0x2f, 0x20, 0x09, 0x18, 0x16, 0xee, 0x9e);")
|
||||
@@ -1243,5 +1243,6 @@ cpp_quote("EXTERN_GUID(MF_ACTIVATE_CUSTOM_VIDEO_PRESENTER_FLAGS, 0xba491366, 0xb
|
||||
cpp_quote("EXTERN_GUID(CLSID_VideoProcessorMFT, 0x88753b26, 0x5b24, 0x49bd, 0xb2, 0xe7, 0xc, 0x44, 0x5c, 0x78, 0xc9, 0x82);")
|
||||
cpp_quote("EXTERN_GUID(CLSID_CMSH264DecoderMFT, 0x62ce7e72, 0x4c71, 0x4d20, 0xb1, 0x5d, 0x45, 0x28, 0x31, 0xa8, 0x7d, 0x9d);")
|
||||
cpp_quote("EXTERN_GUID(CLSID_CMSAACDecMFT, 0x32d186a7, 0x218f, 0x4c75, 0x88, 0x76, 0xdd, 0x77, 0x27, 0x3a, 0x89, 0x99);")
|
||||
+cpp_quote("EXTERN_GUID(CLSID_CMpeg4sDecMFT, 0x5686a0d9, 0xfe39, 0x409f, 0x9d, 0xff, 0x3f, 0xdb, 0xc8, 0x49, 0xf9, 0xf5);")
|
@ -1,7 +1,7 @@
|
||||
From 3450bedc5c9b3e80be234b30191e3e604d24495d Mon Sep 17 00:00:00 2001
|
||||
From 3babfd1eb77488359a9882eee9619689198c84de Mon Sep 17 00:00:00 2001
|
||||
From: Derek Lesho <dlesho@codeweavers.com>
|
||||
Date: Tue, 12 May 2020 16:48:52 -0500
|
||||
Subject: [PATCH 50/54] HACK: Switch between all selection streams on
|
||||
Subject: [PATCH 41/52] HACK: Switch between all selection streams on
|
||||
MF_SOURCE_READER_ANY_STREAM.
|
||||
|
||||
---
|
||||
@ -9,7 +9,7 @@ Subject: [PATCH 50/54] HACK: Switch between all selection streams on
|
||||
1 file changed, 23 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/dlls/mfreadwrite/reader.c b/dlls/mfreadwrite/reader.c
|
||||
index f8c03e62d3..423250e3cb 100644
|
||||
index f8c03e62d35..423250e3cb7 100644
|
||||
--- a/dlls/mfreadwrite/reader.c
|
||||
+++ b/dlls/mfreadwrite/reader.c
|
||||
@@ -1045,7 +1045,29 @@ static HRESULT source_reader_get_stream_read_index(struct source_reader *reader,
|
@ -1,24 +0,0 @@
|
||||
From 6e87e29160026d27f950fce99f3a5a044add84af Mon Sep 17 00:00:00 2001
|
||||
From: Derek Lesho <dlesho@codeweavers.com>
|
||||
Date: Fri, 3 Apr 2020 13:09:30 -0500
|
||||
Subject: [PATCH 42/54] Set BPS on AAC.
|
||||
|
||||
---
|
||||
dlls/winegstreamer/mfplat.c | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
diff --git a/dlls/winegstreamer/mfplat.c b/dlls/winegstreamer/mfplat.c
|
||||
index e1735a5f82..780008face 100644
|
||||
--- a/dlls/winegstreamer/mfplat.c
|
||||
+++ b/dlls/winegstreamer/mfplat.c
|
||||
@@ -916,6 +916,7 @@ static IMFMediaType* transform_to_media_type(GstCaps *caps)
|
||||
struct aac_user_data *user_data = NULL;
|
||||
|
||||
IMFMediaType_SetGUID(media_type, &MF_MT_SUBTYPE, &MFAudioFormat_AAC);
|
||||
+ IMFMediaType_SetUINT32(media_type, &MF_MT_AUDIO_BITS_PER_SAMPLE, 16);
|
||||
|
||||
codec_data = gst_structure_get_value(info, "codec_data");
|
||||
if (codec_data)
|
||||
--
|
||||
2.28.0
|
||||
|
@ -1,7 +1,7 @@
|
||||
From 39e3081768b545c0c4f3f16f4b7d3219d0b249b1 Mon Sep 17 00:00:00 2001
|
||||
From 311f686ac23db13323f18fa18b8e8c2b9b9143cd Mon Sep 17 00:00:00 2001
|
||||
From: Derek Lesho <dlesho@codeweavers.com>
|
||||
Date: Tue, 12 May 2020 16:50:41 -0500
|
||||
Subject: [PATCH 51/54] winegstreamer: Introduce WMA audio decoder.
|
||||
Subject: [PATCH 42/52] winegstreamer: Introduce WMA audio decoder.
|
||||
|
||||
Signed-off-by: Derek Lesho <dlesho@codeweavers.com>
|
||||
---
|
||||
@ -13,22 +13,22 @@ Signed-off-by: Derek Lesho <dlesho@codeweavers.com>
|
||||
5 files changed, 51 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/dlls/winegstreamer/gst_private.h b/dlls/winegstreamer/gst_private.h
|
||||
index 6dc90e2881..af2134078a 100644
|
||||
index b609afa555d..8e75beb82dd 100644
|
||||
--- a/dlls/winegstreamer/gst_private.h
|
||||
+++ b/dlls/winegstreamer/gst_private.h
|
||||
@@ -67,6 +67,7 @@ enum decoder_type
|
||||
@@ -68,6 +68,7 @@ enum decoder_type
|
||||
DECODER_TYPE_H264,
|
||||
DECODER_TYPE_AAC,
|
||||
DECODER_TYPE_WMV,
|
||||
+ DECODER_TYPE_WMA,
|
||||
DECODER_TYPE_M4S2,
|
||||
};
|
||||
HRESULT generic_decoder_construct(REFIID riid, void **obj, enum decoder_type);
|
||||
HRESULT generic_decoder_construct(REFIID riid, void **obj, enum decoder_type) DECLSPEC_HIDDEN;
|
||||
diff --git a/dlls/winegstreamer/mf_decode.c b/dlls/winegstreamer/mf_decode.c
|
||||
index 633a468ed3..3d314eaab4 100644
|
||||
index c5d9cbad392..7ce72a9a6a3 100644
|
||||
--- a/dlls/winegstreamer/mf_decode.c
|
||||
+++ b/dlls/winegstreamer/mf_decode.c
|
||||
@@ -31,6 +31,9 @@ const GUID *aac_output_types[] = {&MFAudioFormat_Float, &MFAudioFormat_PCM};
|
||||
@@ -32,6 +32,9 @@ const GUID *aac_output_types[] = {&MFAudioFormat_Float, &MFAudioFormat_PCM};
|
||||
const GUID *wmv_input_types[] = {&MFVideoFormat_WMV3, &MFVideoFormat_WVC1};
|
||||
const GUID *wmv_output_types[] = {&MFVideoFormat_NV12, &MFVideoFormat_YV12, &MFVideoFormat_YUY2, &MFVideoFormat_UYVY, &MFVideoFormat_YVYU, &MFVideoFormat_NV11, &MFVideoFormat_RGB32, &MFVideoFormat_RGB24, &MFVideoFormat_RGB555, &MFVideoFormat_RGB8};
|
||||
|
||||
@ -38,7 +38,7 @@ index 633a468ed3..3d314eaab4 100644
|
||||
const GUID *m4s2_input_types[] = {&MFVideoFormat_MPEG2};
|
||||
const GUID *m4s2_output_types[] = {&MFVideoFormat_I420, &MFVideoFormat_IYUV, &MFVideoFormat_NV12, &MFVideoFormat_YUY2, &MFVideoFormat_YV12};
|
||||
|
||||
@@ -64,6 +67,13 @@ static struct decoder_desc
|
||||
@@ -65,6 +68,13 @@ static struct decoder_desc
|
||||
wmv_output_types,
|
||||
ARRAY_SIZE(wmv_output_types),
|
||||
},
|
||||
@ -53,10 +53,10 @@ index 633a468ed3..3d314eaab4 100644
|
||||
&MFMediaType_Video,
|
||||
m4s2_input_types,
|
||||
diff --git a/dlls/winegstreamer/mfplat.c b/dlls/winegstreamer/mfplat.c
|
||||
index e0da02074e..bcfcd398ec 100644
|
||||
index 5fe7ac4d354..28c9beb4649 100644
|
||||
--- a/dlls/winegstreamer/mfplat.c
|
||||
+++ b/dlls/winegstreamer/mfplat.c
|
||||
@@ -419,6 +419,11 @@ static HRESULT wmv_decoder_create(REFIID riid, void **ret)
|
||||
@@ -421,6 +421,11 @@ static HRESULT wmv_decoder_create(REFIID riid, void **ret)
|
||||
return generic_decoder_construct(riid, ret, DECODER_TYPE_WMV);
|
||||
}
|
||||
|
||||
@ -68,15 +68,15 @@ index e0da02074e..bcfcd398ec 100644
|
||||
static HRESULT m4s2_decoder_create(REFIID riid, void **ret)
|
||||
{
|
||||
return generic_decoder_construct(riid, ret, DECODER_TYPE_M4S2);
|
||||
@@ -447,6 +452,7 @@ class_objects[] =
|
||||
@@ -440,6 +445,7 @@ class_objects[] =
|
||||
{ &CLSID_CMSH264DecoderMFT, &h264_decoder_create },
|
||||
{ &CLSID_CMSAACDecMFT, &aac_decoder_create },
|
||||
{ &CLSID_CWMVDecMediaObject, &wmv_decoder_create },
|
||||
+ { &CLSID_CWMADecMediaObject, &wma_decoder_create },
|
||||
{ &CLSID_CMpeg4sDecMFT, m4s2_decoder_create },
|
||||
{ &CLSID_MPEG4ByteStreamHandler, &mp4_stream_handler_create },
|
||||
{ &CLSID_ASFByteStreamHandler, &asf_stream_handler_create },
|
||||
@@ -552,6 +558,20 @@ const GUID *wmv_decoder_output_types[] =
|
||||
{ &CLSID_CColorConvertDMO, &color_converter_create },
|
||||
};
|
||||
@@ -540,6 +546,20 @@ const GUID *wmv_decoder_output_types[] =
|
||||
&MFVideoFormat_RGB8,
|
||||
};
|
||||
|
||||
@ -97,7 +97,7 @@ index e0da02074e..bcfcd398ec 100644
|
||||
static WCHAR m4s2decoderW[] = {'M','p','e','g','4','s',' ','D','e','c','o','d','e','r',' ','M','F','T',0};
|
||||
|
||||
const GUID *m4s2_decoder_input_types[] =
|
||||
@@ -631,6 +651,18 @@ mfts[] =
|
||||
@@ -619,6 +639,18 @@ mfts[] =
|
||||
wmv_decoder_output_types,
|
||||
NULL
|
||||
},
|
||||
@ -117,10 +117,10 @@ index e0da02074e..bcfcd398ec 100644
|
||||
&CLSID_CMpeg4sDecMFT,
|
||||
&MFT_CATEGORY_VIDEO_DECODER,
|
||||
diff --git a/dlls/winegstreamer/winegstreamer_classes.idl b/dlls/winegstreamer/winegstreamer_classes.idl
|
||||
index 3a3daad3ab..9f210fbbf7 100644
|
||||
index 5969eaa591a..c014d359a39 100644
|
||||
--- a/dlls/winegstreamer/winegstreamer_classes.idl
|
||||
+++ b/dlls/winegstreamer/winegstreamer_classes.idl
|
||||
@@ -92,6 +92,12 @@ coclass ASFByteStreamHandler {}
|
||||
@@ -86,6 +86,12 @@ coclass CMpeg4sDecMFT { }
|
||||
]
|
||||
coclass CLSID_CWMVDecMediaObject {}
|
||||
|
||||
@ -134,10 +134,10 @@ index 3a3daad3ab..9f210fbbf7 100644
|
||||
threading(both),
|
||||
uuid(98230571-0087-4204-b020-3282538e57d3)
|
||||
diff --git a/include/mfidl.idl b/include/mfidl.idl
|
||||
index 35dd4c2f96..3c11402931 100644
|
||||
index a344986a7aa..5154b798dfb 100644
|
||||
--- a/include/mfidl.idl
|
||||
+++ b/include/mfidl.idl
|
||||
@@ -1246,4 +1246,5 @@ cpp_quote("EXTERN_GUID(CLSID_CMSH264DecoderMFT, 0x62ce7e72, 0x4c71, 0x4d20, 0xb1
|
||||
@@ -1245,4 +1245,5 @@ cpp_quote("EXTERN_GUID(CLSID_CMSH264DecoderMFT, 0x62ce7e72, 0x4c71, 0x4d20, 0xb1
|
||||
cpp_quote("EXTERN_GUID(CLSID_CMSAACDecMFT, 0x32d186a7, 0x218f, 0x4c75, 0x88, 0x76, 0xdd, 0x77, 0x27, 0x3a, 0x89, 0x99);")
|
||||
cpp_quote("EXTERN_GUID(CLSID_CMpeg4sDecMFT, 0x5686a0d9, 0xfe39, 0x409f, 0x9d, 0xff, 0x3f, 0xdb, 0xc8, 0x49, 0xf9, 0xf5);")
|
||||
cpp_quote("EXTERN_GUID(CLSID_ASFByteStreamHandler, 0x41457294, 0x644c, 0x4298, 0xa2, 0x8a, 0xbd, 0x69, 0xf2, 0xc0, 0xcf, 0x3b);")
|
@ -0,0 +1,29 @@
|
||||
From f72479c9e576a766f38bcd9c8c377ee53adbdfe2 Mon Sep 17 00:00:00 2001
|
||||
From: Derek Lesho <dlesho@codeweavers.com>
|
||||
Date: Wed, 13 May 2020 12:32:42 -0500
|
||||
Subject: [PATCH 43/52] Support stereo down folding.
|
||||
|
||||
---
|
||||
dlls/winegstreamer/mf_decode.c | 4 +++-
|
||||
1 file changed, 3 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/dlls/winegstreamer/mf_decode.c b/dlls/winegstreamer/mf_decode.c
|
||||
index 7ce72a9a6a3..00f69aa76cc 100644
|
||||
--- a/dlls/winegstreamer/mf_decode.c
|
||||
+++ b/dlls/winegstreamer/mf_decode.c
|
||||
@@ -327,9 +327,11 @@ static HRESULT WINAPI mf_decoder_GetOutputAvailableType(IMFTransform *iface, DWO
|
||||
|
||||
copy_attr(output_type, decoder->input_type, &MF_MT_FRAME_SIZE);
|
||||
copy_attr(output_type, decoder->input_type, &MF_MT_FRAME_RATE);
|
||||
- copy_attr(output_type, decoder->input_type, &MF_MT_AUDIO_NUM_CHANNELS);
|
||||
copy_attr(output_type, decoder->input_type, &MF_MT_AUDIO_SAMPLES_PER_SECOND);
|
||||
|
||||
+ /* TODO: support both stereo folding and matching channels */
|
||||
+ IMFMediaType_SetUINT32(output_type, &MF_MT_AUDIO_NUM_CHANNELS, 2);
|
||||
+
|
||||
if (FAILED(hr = IMFMediaType_SetGUID(output_type, &MF_MT_MAJOR_TYPE, decoder_descs[decoder->type].major_type)))
|
||||
{
|
||||
IMFMediaType_Release(output_type);
|
||||
--
|
||||
2.28.0
|
||||
|
@ -0,0 +1,64 @@
|
||||
From ada0cb5f81f858b27b3c52f6c10097a7444b8793 Mon Sep 17 00:00:00 2001
|
||||
From: Derek Lesho <dlesho@codeweavers.com>
|
||||
Date: Tue, 11 Aug 2020 13:41:15 -0500
|
||||
Subject: [PATCH 44/52] winegstreamer: Implement MF_SD_LANGUAGE.
|
||||
|
||||
Signed-off-by: Derek Lesho <dlesho@codeweavers.com>
|
||||
---
|
||||
dlls/winegstreamer/media_source.c | 33 +++++++++++++++++++++++++++++--
|
||||
1 file changed, 31 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/dlls/winegstreamer/media_source.c b/dlls/winegstreamer/media_source.c
|
||||
index a162bad99d8..07c16ac8a07 100644
|
||||
--- a/dlls/winegstreamer/media_source.c
|
||||
+++ b/dlls/winegstreamer/media_source.c
|
||||
@@ -1796,8 +1796,12 @@ static HRESULT media_source_constructor(IMFByteStream *bytestream, struct media_
|
||||
/* TODO: consider streams which don't start at T=0 */
|
||||
for (unsigned int i = 0; i < object->stream_count; i++)
|
||||
{
|
||||
- GstQuery *query = gst_query_new_duration(GST_FORMAT_TIME);
|
||||
- if (gst_pad_query(object->streams[i]->their_src, query))
|
||||
+ struct media_stream *stream = object->streams[i];
|
||||
+ GstEvent *tag_event;
|
||||
+ GstQuery *query;
|
||||
+
|
||||
+ query = gst_query_new_duration(GST_FORMAT_TIME);
|
||||
+ if (gst_pad_query(stream->their_src, query))
|
||||
{
|
||||
gint64 stream_pres_time;
|
||||
gst_query_parse_duration(query, NULL, &stream_pres_time);
|
||||
@@ -1811,6 +1815,31 @@ static HRESULT media_source_constructor(IMFByteStream *bytestream, struct media_
|
||||
{
|
||||
WARN("Unable to get presentation time of stream %u\n", i);
|
||||
}
|
||||
+
|
||||
+ tag_event = gst_pad_get_sticky_event(stream->their_src, GST_EVENT_TAG, 0);
|
||||
+ if (tag_event)
|
||||
+ {
|
||||
+ GstTagList *tag_list;
|
||||
+ gchar *language_code = NULL;
|
||||
+
|
||||
+ gst_event_parse_tag(tag_event, &tag_list);
|
||||
+
|
||||
+ gst_tag_list_get_string(tag_list, "language-code", &language_code);
|
||||
+ if (language_code)
|
||||
+ {
|
||||
+ DWORD char_count = MultiByteToWideChar(CP_UTF8, 0, language_code, -1, NULL, 0);
|
||||
+ if (char_count)
|
||||
+ {
|
||||
+ WCHAR *language_codeW = heap_alloc(char_count * sizeof(WCHAR));
|
||||
+ MultiByteToWideChar(CP_UTF8, 0, language_code, -1, language_codeW, char_count);
|
||||
+ IMFStreamDescriptor_SetString(stream->descriptor, &MF_SD_LANGUAGE, language_codeW);
|
||||
+ heap_free(language_codeW);
|
||||
+ }
|
||||
+ g_free(language_code);
|
||||
+ }
|
||||
+
|
||||
+ gst_event_unref(tag_event);
|
||||
+ }
|
||||
}
|
||||
|
||||
if (object->stream_count)
|
||||
--
|
||||
2.28.0
|
||||
|
@ -1,7 +1,7 @@
|
||||
From ac9dd9bf46de1056dd26a3230bfd885d2962c8aa Mon Sep 17 00:00:00 2001
|
||||
From: Alistair Leslie-Hughes <leslie_alistair@hotmail.com>
|
||||
Date: Tue, 11 Aug 2020 09:26:57 +1000
|
||||
Subject: [PATCH 01/54] Revert "mf/topoloader: Add a structure for iterative
|
||||
From dfa7779e8abad5caf9beeac2c459e074bc05dbe2 Mon Sep 17 00:00:00 2001
|
||||
From: Derek Lesho <dlesho@codeweavers.com>
|
||||
Date: Tue, 11 Aug 2020 15:58:42 -0500
|
||||
Subject: [PATCH 45/52] Revert "mf/topoloader: Add a structure for iterative
|
||||
branch resolution."
|
||||
|
||||
This reverts commit e308d81a617632fe0fedd243952f79e8d9ec05b4.
|
||||
@ -11,7 +11,7 @@ This reverts commit e308d81a617632fe0fedd243952f79e8d9ec05b4.
|
||||
2 files changed, 4 insertions(+), 143 deletions(-)
|
||||
|
||||
diff --git a/dlls/mf/tests/mf.c b/dlls/mf/tests/mf.c
|
||||
index f01385cc46..aa2c5199b9 100644
|
||||
index f01385cc46c..aa2c5199b95 100644
|
||||
--- a/dlls/mf/tests/mf.c
|
||||
+++ b/dlls/mf/tests/mf.c
|
||||
@@ -1400,7 +1400,6 @@ static void test_topology_loader(void)
|
||||
@ -45,7 +45,7 @@ index f01385cc46..aa2c5199b9 100644
|
||||
ok(full_topology != topology, "Unexpected instance.\n");
|
||||
|
||||
diff --git a/dlls/mf/topology.c b/dlls/mf/topology.c
|
||||
index 8032e438b7..840f1bd25f 100644
|
||||
index 8032e438b73..840f1bd25f4 100644
|
||||
--- a/dlls/mf/topology.c
|
||||
+++ b/dlls/mf/topology.c
|
||||
@@ -1935,41 +1935,17 @@ static ULONG WINAPI topology_loader_Release(IMFTopoLoader *iface)
|
@ -1,7 +1,7 @@
|
||||
From f02867e2a1129f7aef4488db827fc52a6131b3d4 Mon Sep 17 00:00:00 2001
|
||||
From: Alistair Leslie-Hughes <leslie_alistair@hotmail.com>
|
||||
Date: Tue, 11 Aug 2020 09:26:59 +1000
|
||||
Subject: [PATCH 02/54] Revert "mf/topoloader: Clone source nodes as a first
|
||||
From 536cc47d3eaa127969d6a3137e28c7a388e54a58 Mon Sep 17 00:00:00 2001
|
||||
From: Derek Lesho <dlesho@codeweavers.com>
|
||||
Date: Tue, 11 Aug 2020 15:59:04 -0500
|
||||
Subject: [PATCH 46/52] Revert "mf/topoloader: Clone source nodes as a first
|
||||
layer of resulting topology."
|
||||
|
||||
This reverts commit 16d44b61d15193905ef40661bc1547cb45e7b019.
|
||||
@ -10,7 +10,7 @@ This reverts commit 16d44b61d15193905ef40661bc1547cb45e7b019.
|
||||
1 file changed, 4 insertions(+), 57 deletions(-)
|
||||
|
||||
diff --git a/dlls/mf/topology.c b/dlls/mf/topology.c
|
||||
index 840f1bd25f..8522f56969 100644
|
||||
index 840f1bd25f4..8522f569691 100644
|
||||
--- a/dlls/mf/topology.c
|
||||
+++ b/dlls/mf/topology.c
|
||||
@@ -1933,40 +1933,9 @@ static ULONG WINAPI topology_loader_Release(IMFTopoLoader *iface)
|
@ -1,25 +0,0 @@
|
||||
From c68cf22e60e000f279ab7f2cc8c707447d9795f3 Mon Sep 17 00:00:00 2001
|
||||
From: Derek Lesho <dlesho@codeweavers.com>
|
||||
Date: Mon, 4 May 2020 12:40:56 -0500
|
||||
Subject: [PATCH] Set "wait-on-eos" to allow other streams to continue while
|
||||
appsink buffers.
|
||||
|
||||
---
|
||||
dlls/winegstreamer/media_source.c | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
diff --git a/dlls/winegstreamer/media_source.c b/dlls/winegstreamer/media_source.c
|
||||
index a3f76518eb..0165ea1570 100644
|
||||
--- a/dlls/winegstreamer/media_source.c
|
||||
+++ b/dlls/winegstreamer/media_source.c
|
||||
@@ -1042,6 +1042,7 @@ static HRESULT media_stream_constructor(struct media_source *source, GstPad *pad
|
||||
g_object_set(object->appsink, "emit-signals", TRUE, NULL);
|
||||
g_object_set(object->appsink, "sync", FALSE, NULL);
|
||||
g_object_set(object->appsink, "async", FALSE, NULL); /* <- This allows us interact with the bin w/o prerolling */
|
||||
+ g_object_set(object->appsink, "wait-on-eos", FALSE, NULL);
|
||||
g_signal_connect(object->appsink, "new-sample", G_CALLBACK(stream_new_sample_wrapper), object);
|
||||
|
||||
if (FAILED(hr = media_stream_align_with_mf(object, &stream_type)))
|
||||
--
|
||||
2.28.0
|
||||
|
@ -1,7 +1,7 @@
|
||||
From e42f00a2fd98ea18f76b2f8c874d86b27723c57d Mon Sep 17 00:00:00 2001
|
||||
From: Alistair Leslie-Hughes <leslie_alistair@hotmail.com>
|
||||
Date: Tue, 11 Aug 2020 09:27:00 +1000
|
||||
Subject: [PATCH 03/54] Revert "mf/topoloader: Switch to public interface for
|
||||
From 7a0d07917acb65ae5dd623231e5756b2371d1484 Mon Sep 17 00:00:00 2001
|
||||
From: Derek Lesho <dlesho@codeweavers.com>
|
||||
Date: Tue, 11 Aug 2020 15:59:13 -0500
|
||||
Subject: [PATCH 47/52] Revert "mf/topoloader: Switch to public interface for
|
||||
initial topology validation."
|
||||
|
||||
This reverts commit 8e343024b577892bd4908304ded34b758579698d.
|
||||
@ -10,7 +10,7 @@ This reverts commit 8e343024b577892bd4908304ded34b758579698d.
|
||||
1 file changed, 12 insertions(+), 24 deletions(-)
|
||||
|
||||
diff --git a/dlls/mf/topology.c b/dlls/mf/topology.c
|
||||
index 8522f56969..abe66c45fd 100644
|
||||
index 8522f569691..abe66c45fd4 100644
|
||||
--- a/dlls/mf/topology.c
|
||||
+++ b/dlls/mf/topology.c
|
||||
@@ -1936,50 +1936,38 @@ static ULONG WINAPI topology_loader_Release(IMFTopoLoader *iface)
|
@ -1,8 +1,8 @@
|
||||
From 01329fe9741031c7ae7cbe74f7b79d5a92f5e52c Mon Sep 17 00:00:00 2001
|
||||
From 5c73b5ab912098d1399781cef97956c188bdc187 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Sergio=20G=C3=B3mez=20Del=20Real?=
|
||||
<sdelreal@codeweavers.com>
|
||||
Date: Wed, 1 Apr 2020 16:11:07 -0500
|
||||
Subject: [PATCH 06/54] mf: Partially implement the topology loader.
|
||||
Subject: [PATCH 48/52] mf: Partially implement the topology loader.
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
@ -14,10 +14,10 @@ Signed-off-by: Sergio Gómez Del Real <sdelreal@codeweavers.com>
|
||||
2 files changed, 321 insertions(+), 19 deletions(-)
|
||||
|
||||
diff --git a/dlls/mf/tests/mf.c b/dlls/mf/tests/mf.c
|
||||
index 8691ef55c9..f4f72dda5e 100644
|
||||
index aa2c5199b95..1a08604fb39 100644
|
||||
--- a/dlls/mf/tests/mf.c
|
||||
+++ b/dlls/mf/tests/mf.c
|
||||
@@ -1572,7 +1572,6 @@ static void test_topology_loader(void)
|
||||
@@ -1428,7 +1428,6 @@ static void test_topology_loader(void)
|
||||
|
||||
/* Empty topology */
|
||||
hr = IMFTopoLoader_Load(loader, topology, &full_topology, NULL);
|
||||
@ -25,7 +25,7 @@ index 8691ef55c9..f4f72dda5e 100644
|
||||
ok(hr == MF_E_TOPO_UNSUPPORTED, "Unexpected hr %#x.\n", hr);
|
||||
|
||||
hr = MFCreateSourceResolver(&resolver);
|
||||
@@ -1617,7 +1616,6 @@ todo_wine
|
||||
@@ -1473,7 +1472,6 @@ todo_wine
|
||||
|
||||
/* Source node only. */
|
||||
hr = IMFTopoLoader_Load(loader, topology, &full_topology, NULL);
|
||||
@ -33,7 +33,7 @@ index 8691ef55c9..f4f72dda5e 100644
|
||||
ok(hr == MF_E_TOPO_UNSUPPORTED, "Unexpected hr %#x.\n", hr);
|
||||
|
||||
/* Add grabber sink. */
|
||||
@@ -1643,7 +1641,6 @@ todo_wine
|
||||
@@ -1499,7 +1497,6 @@ todo_wine
|
||||
ok(hr == S_OK, "Failed to add sink node, hr %#x.\n", hr);
|
||||
|
||||
hr = IMFTopoLoader_Load(loader, topology, &full_topology, NULL);
|
||||
@ -42,7 +42,7 @@ index 8691ef55c9..f4f72dda5e 100644
|
||||
|
||||
hr = IMFTopologyNode_ConnectOutput(src_node, 0, sink_node, 0);
|
||||
diff --git a/dlls/mf/topology.c b/dlls/mf/topology.c
|
||||
index abe66c45fd..d4a59f7136 100644
|
||||
index abe66c45fd4..d4a59f7136e 100644
|
||||
--- a/dlls/mf/topology.c
|
||||
+++ b/dlls/mf/topology.c
|
||||
@@ -1933,47 +1933,352 @@ static ULONG WINAPI topology_loader_Release(IMFTopoLoader *iface)
|
@ -1,14 +1,14 @@
|
||||
From 3162911a265859e6767fb3c61229ca512dc06bc1 Mon Sep 17 00:00:00 2001
|
||||
From b66660df34eeb885c28a9381461255712a7b3bd1 Mon Sep 17 00:00:00 2001
|
||||
From: Derek Lesho <dlesho@codeweavers.com>
|
||||
Date: Thu, 2 Apr 2020 15:43:52 -0500
|
||||
Subject: [PATCH 38/54] mf: Miscelaneous fixes to topology resolution.
|
||||
Subject: [PATCH 49/52] mf: Miscelaneous fixes to topology resolution.
|
||||
|
||||
---
|
||||
dlls/mf/topology.c | 16 +++++++++-------
|
||||
1 file changed, 9 insertions(+), 7 deletions(-)
|
||||
|
||||
diff --git a/dlls/mf/topology.c b/dlls/mf/topology.c
|
||||
index d4a59f7136..2e84920434 100644
|
||||
index d4a59f7136e..2e849204343 100644
|
||||
--- a/dlls/mf/topology.c
|
||||
+++ b/dlls/mf/topology.c
|
||||
@@ -2026,7 +2026,7 @@ static HRESULT topology_loader_resolve_branch(IMFTopologyNode *src, IMFMediaType
|
@ -1,18 +1,18 @@
|
||||
From f60e21e99a3cddea383792307c4b8c8278e887b8 Mon Sep 17 00:00:00 2001
|
||||
From ebfd4c055be8d68a34b4bfd6a80e449afce5d9c8 Mon Sep 17 00:00:00 2001
|
||||
From: Derek Lesho <dlesho@codeweavers.com>
|
||||
Date: Thu, 2 Apr 2020 15:45:52 -0500
|
||||
Subject: [PATCH] Rewrite branch resolver.
|
||||
Subject: [PATCH 50/52] Rewrite branch resolver.
|
||||
|
||||
and a HACK: Set output type of found decoder, this should probably happen somewhere else.
|
||||
---
|
||||
dlls/mf/topology.c | 280 ++++++++++++++++++++++++++++-----------------
|
||||
1 file changed, 172 insertions(+), 108 deletions(-)
|
||||
1 file changed, 173 insertions(+), 107 deletions(-)
|
||||
|
||||
diff --git a/dlls/mf/topology.c b/dlls/mf/topology.c
|
||||
index 2e84920434..5a00fe7ea3 100644
|
||||
index 2e849204343..91d29782582 100644
|
||||
--- a/dlls/mf/topology.c
|
||||
+++ b/dlls/mf/topology.c
|
||||
@@ -1948,135 +1948,195 @@ static void topology_loader_add_branch(struct topology *topology, IMFTopologyNod
|
||||
@@ -1948,135 +1948,196 @@ static void topology_loader_add_branch(struct topology *topology, IMFTopologyNod
|
||||
}
|
||||
}
|
||||
|
||||
@ -29,7 +29,6 @@ index 2e84920434..5a00fe7ea3 100644
|
||||
+ IMFActivate **activates;
|
||||
+ UINT32 num_activates;
|
||||
+ HRESULT hr;
|
||||
+ unsigned int i;
|
||||
+
|
||||
+ if (FAILED(hr = IMFMediaType_GetMajorType(input_type, &major_type)))
|
||||
+ return hr;
|
||||
@ -45,7 +44,7 @@ index 2e84920434..5a00fe7ea3 100644
|
||||
+
|
||||
+ hr = E_FAIL;
|
||||
+
|
||||
+ for (i = 0; i < num_activates; i++)
|
||||
+ for (unsigned int i = 0; i < num_activates; i++)
|
||||
+ {
|
||||
+ IMFTransform *mft;
|
||||
+
|
||||
@ -83,13 +82,14 @@ index 2e84920434..5a00fe7ea3 100644
|
||||
+ IMFTopologyNode *node;
|
||||
+ struct connect_to_sink_context *ctx = context;
|
||||
+
|
||||
+ if (SUCCEEDED(IMFMediaTypeHandler_SetCurrentMediaType(ctx->sink_mth, type->type)))
|
||||
+ if (SUCCEEDED(IMFMediaTypeHandler_IsMediaTypeSupported(ctx->sink_mth, type->type, NULL)))
|
||||
+ {
|
||||
+ MFCreateTopologyNode(MF_TOPOLOGY_TRANSFORM_NODE, &node);
|
||||
+ IMFTopologyNode_SetObject(node, (IUnknown *) type->transform);
|
||||
+ IMFTopologyNode_ConnectOutput(ctx->src, 0, node, 0);
|
||||
+ IMFTopologyNode_ConnectOutput(node, 0, ctx->sink, 0);
|
||||
+
|
||||
+ IMFMediaTypeHandler_SetCurrentMediaType(ctx->sink_mth, type->type);
|
||||
+ IMFTransform_SetOutputType(type->transform, 0, type->type, 0);
|
||||
+
|
||||
+ return S_OK;
|
||||
@ -141,11 +141,12 @@ index 2e84920434..5a00fe7ea3 100644
|
||||
IMFStreamSink_GetMediaTypeHandler(streamsink, &mth);
|
||||
- if (method == MF_CONNECT_DIRECT)
|
||||
+
|
||||
+ if (SUCCEEDED(hr = IMFMediaTypeHandler_SetCurrentMediaType(mth, mediatype)))
|
||||
+ if (SUCCEEDED(hr = IMFMediaTypeHandler_IsMediaTypeSupported(mth, mediatype, NULL)))
|
||||
{
|
||||
- if (FAILED(hr = IMFMediaTypeHandler_SetCurrentMediaType(mth, mediatype)))
|
||||
- return hr;
|
||||
- hr = IMFTopologyNode_ConnectOutput(src, 0, sink, 0);
|
||||
+ IMFMediaTypeHandler_SetCurrentMediaType(mth, mediatype);
|
||||
+ return IMFTopologyNode_ConnectOutput(src, 0, sink, 0);
|
||||
+ }
|
||||
+
|
||||
@ -310,7 +311,7 @@ index 2e84920434..5a00fe7ea3 100644
|
||||
IMFAttributes *attrs_src;
|
||||
IMFStreamSink *strm_sink;
|
||||
IMFMediaType *mtype_src;
|
||||
@@ -2084,6 +2144,7 @@ static HRESULT topology_loader_resolve_partial_topology(struct topology_node *sr
|
||||
@@ -2084,6 +2145,7 @@ static HRESULT topology_loader_resolve_partial_topology(struct topology_node *sr
|
||||
HRESULT hr;
|
||||
int i;
|
||||
|
||||
@ -318,7 +319,7 @@ index 2e84920434..5a00fe7ea3 100644
|
||||
attrs_src = src->attributes;
|
||||
if (FAILED(hr = IMFAttributes_GetUnknown(attrs_src, &MF_TOPONODE_STREAM_DESCRIPTOR, &IID_IMFStreamDescriptor, (void **)&desc)))
|
||||
return hr;
|
||||
@@ -2137,12 +2198,15 @@ static HRESULT topology_loader_resolve_partial_topology(struct topology_node *sr
|
||||
@@ -2137,12 +2199,15 @@ static HRESULT topology_loader_resolve_partial_topology(struct topology_node *sr
|
||||
if (FAILED(IMFTopologyNode_GetUINT32(clone_sink, &MF_TOPONODE_STREAMID, &streamid)))
|
||||
IMFTopologyNode_SetUINT32(clone_sink, &MF_TOPONODE_STREAMID, 0);
|
||||
|
||||
@ -337,7 +338,7 @@ index 2e84920434..5a00fe7ea3 100644
|
||||
for (i = 0; i < num_media_types; i++)
|
||||
if (SUCCEEDED(topology_loader_resolve_branch(clone_src, src_mediatypes[i], clone_sink, method)))
|
||||
{
|
||||
@@ -2154,7 +2218,7 @@ static HRESULT topology_loader_resolve_partial_topology(struct topology_node *sr
|
||||
@@ -2154,7 +2219,7 @@ static HRESULT topology_loader_resolve_partial_topology(struct topology_node *sr
|
||||
else
|
||||
{
|
||||
for (i = 0; i < num_media_types; i++)
|
||||
@ -346,7 +347,7 @@ index 2e84920434..5a00fe7ea3 100644
|
||||
if (SUCCEEDED(topology_loader_resolve_branch(clone_src, src_mediatypes[i], clone_sink, method)))
|
||||
{
|
||||
topology_loader_add_branch(*full_topology, clone_src, clone_sink);
|
||||
@@ -2165,10 +2229,10 @@ static HRESULT topology_loader_resolve_partial_topology(struct topology_node *sr
|
||||
@@ -2165,7 +2230,7 @@ static HRESULT topology_loader_resolve_partial_topology(struct topology_node *sr
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -354,11 +355,15 @@ index 2e84920434..5a00fe7ea3 100644
|
||||
+ for (method = MF_CONNECT_DIRECT; method <= sink_method; method++)
|
||||
if (SUCCEEDED(topology_loader_resolve_branch(clone_src, src_mediatypes[0], clone_sink, method)))
|
||||
{
|
||||
- TRACE("Successfully connected nodes with method %u\n", method);
|
||||
+ TRACE("Successfully connected nodes with method %u\n", src_method);
|
||||
topology_loader_add_branch(*full_topology, clone_src, clone_sink);
|
||||
heap_free(src_mediatypes);
|
||||
return S_OK;
|
||||
TRACE("Successfully connected nodes with method %u\n", method);
|
||||
@@ -2274,6 +2339,7 @@ static HRESULT WINAPI topology_loader_Load(IMFTopoLoader *iface, IMFTopology *in
|
||||
|
||||
if (FAILED(hr = topology_loader_resolve_partial_topology(src, sink, topology, &full_topology)))
|
||||
{
|
||||
+ ERR("Failed to resolve connection between %p and %p. %x\n", src, sink, hr);
|
||||
heap_free(node_pairs);
|
||||
return hr;
|
||||
}
|
||||
--
|
||||
2.28.0
|
||||
|
@ -0,0 +1,30 @@
|
||||
From 7884831a19a53abf4b33b7c6cabf5a52247c2b32 Mon Sep 17 00:00:00 2001
|
||||
From: Derek Lesho <dlesho@codeweavers.com>
|
||||
Date: Wed, 26 Aug 2020 10:23:58 -0500
|
||||
Subject: [PATCH 51/52] mf/sar: Compare against native media type in
|
||||
IsMediaTypeSupported.
|
||||
|
||||
TODO: add tests.
|
||||
---
|
||||
dlls/mf/sar.c | 5 +++--
|
||||
1 file changed, 3 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/dlls/mf/sar.c b/dlls/mf/sar.c
|
||||
index 6f1f1bd834e..547f8eb391c 100644
|
||||
--- a/dlls/mf/sar.c
|
||||
+++ b/dlls/mf/sar.c
|
||||
@@ -1479,8 +1479,9 @@ static HRESULT WINAPI audio_renderer_stream_type_handler_IsMediaTypeSupported(IM
|
||||
TRACE("%p, %p, %p.\n", iface, in_type, out_type);
|
||||
|
||||
EnterCriticalSection(&renderer->cs);
|
||||
- hr = renderer->current_media_type && IMFMediaType_IsEqual(renderer->current_media_type, in_type, &flags) == S_OK ?
|
||||
- S_OK : MF_E_INVALIDMEDIATYPE;
|
||||
+ hr = IMFMediaType_IsEqual(renderer->current_media_type ? renderer->current_media_type : renderer->media_type, in_type, &flags) == S_OK ?
|
||||
+ S_OK : MF_E_INVALIDMEDIATYPE;
|
||||
+
|
||||
LeaveCriticalSection(&renderer->cs);
|
||||
|
||||
return hr;
|
||||
--
|
||||
2.28.0
|
||||
|
@ -1,27 +0,0 @@
|
||||
From 12817ac3db28b1945a664ea3411186e1e64f6ed4 Mon Sep 17 00:00:00 2001
|
||||
From: Victor Hermann Chiletto <v@hnn.net.br>
|
||||
Date: Tue, 9 Jun 2020 01:35:53 -0300
|
||||
Subject: [PATCH 52/54] winegstreamer: Fix unrecognized format errors when
|
||||
transforming caps to media type
|
||||
|
||||
Probably not needed, but it's nice to get this out of the way
|
||||
---
|
||||
dlls/winegstreamer/mfplat.c | 2 ++
|
||||
1 file changed, 2 insertions(+)
|
||||
|
||||
diff --git a/dlls/winegstreamer/mfplat.c b/dlls/winegstreamer/mfplat.c
|
||||
index bcfcd398ec..39b98f3eba 100644
|
||||
--- a/dlls/winegstreamer/mfplat.c
|
||||
+++ b/dlls/winegstreamer/mfplat.c
|
||||
@@ -910,6 +910,8 @@ static IMFMediaType* transform_to_media_type(GstCaps *caps)
|
||||
{
|
||||
if (!(strcmp(format, "WVC1")))
|
||||
IMFMediaType_SetGUID(media_type, &MF_MT_SUBTYPE, &MFVideoFormat_WVC1);
|
||||
+ else if (!(strcmp(format, "WMV3")))
|
||||
+ IMFMediaType_SetGUID(media_type, &MF_MT_SUBTYPE, &MFVideoFormat_WMV3);
|
||||
else
|
||||
FIXME("Unrecognized format %s\n", format);
|
||||
}
|
||||
--
|
||||
2.28.0
|
||||
|
@ -0,0 +1,879 @@
|
||||
From 779877a3e829ba787f289ea13047562652e79ad9 Mon Sep 17 00:00:00 2001
|
||||
From: Derek Lesho <dlesho@codeweavers.com>
|
||||
Date: Wed, 26 Aug 2020 10:28:37 -0500
|
||||
Subject: [PATCH 52/52] winegstreamer: Implement audio conversion MFT.
|
||||
|
||||
Signed-off-by: Derek Lesho <dlesho@codeweavers.com>
|
||||
---
|
||||
dlls/winegstreamer/Makefile.in | 1 +
|
||||
dlls/winegstreamer/audioconvert.c | 762 +++++++++++++++++++
|
||||
dlls/winegstreamer/gst_private.h | 1 +
|
||||
dlls/winegstreamer/mfplat.c | 23 +
|
||||
dlls/winegstreamer/winegstreamer_classes.idl | 6 +
|
||||
5 files changed, 793 insertions(+)
|
||||
create mode 100644 dlls/winegstreamer/audioconvert.c
|
||||
|
||||
diff --git a/dlls/winegstreamer/Makefile.in b/dlls/winegstreamer/Makefile.in
|
||||
index a266b0a95e4..81c670c17e4 100644
|
||||
--- a/dlls/winegstreamer/Makefile.in
|
||||
+++ b/dlls/winegstreamer/Makefile.in
|
||||
@@ -6,6 +6,7 @@ EXTRALIBS = $(GSTREAMER_LIBS) $(PTHREAD_LIBS)
|
||||
PARENTSRC = ../strmbase ../mf
|
||||
|
||||
C_SRCS = \
|
||||
+ audioconvert.c \
|
||||
colorconvert.c \
|
||||
filter.c \
|
||||
gst_cbs.c \
|
||||
diff --git a/dlls/winegstreamer/audioconvert.c b/dlls/winegstreamer/audioconvert.c
|
||||
new file mode 100644
|
||||
index 00000000000..acb842242f1
|
||||
--- /dev/null
|
||||
+++ b/dlls/winegstreamer/audioconvert.c
|
||||
@@ -0,0 +1,762 @@
|
||||
+#include "config.h"
|
||||
+#include <gst/gst.h>
|
||||
+
|
||||
+#include "gst_private.h"
|
||||
+#include "gst_cbs.h"
|
||||
+
|
||||
+#include "mfapi.h"
|
||||
+#include "mferror.h"
|
||||
+#include "mfidl.h"
|
||||
+
|
||||
+#include "wine/debug.h"
|
||||
+#include "wine/heap.h"
|
||||
+
|
||||
+WINE_DEFAULT_DEBUG_CHANNEL(mfplat);
|
||||
+
|
||||
+static const GUID *raw_types[] = {
|
||||
+ &MFAudioFormat_PCM,
|
||||
+ &MFAudioFormat_Float,
|
||||
+};
|
||||
+
|
||||
+struct audio_converter
|
||||
+{
|
||||
+ IMFTransform IMFTransform_iface;
|
||||
+ LONG refcount;
|
||||
+ IMFAttributes *attributes;
|
||||
+ IMFAttributes *output_attributes;
|
||||
+ IMFMediaType *input_type;
|
||||
+ IMFMediaType *output_type;
|
||||
+ BOOL valid_state, inflight;
|
||||
+ GstElement *container, *appsrc, *audioconvert, *resampler, *appsink;
|
||||
+ GstBus *bus;
|
||||
+ CRITICAL_SECTION cs;
|
||||
+};
|
||||
+
|
||||
+static struct audio_converter *impl_audio_converter_from_IMFTransform(IMFTransform *iface)
|
||||
+{
|
||||
+ return CONTAINING_RECORD(iface, struct audio_converter, IMFTransform_iface);
|
||||
+}
|
||||
+
|
||||
+static HRESULT WINAPI audio_converter_QueryInterface(IMFTransform *iface, REFIID riid, void **obj)
|
||||
+{
|
||||
+ TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), obj);
|
||||
+
|
||||
+ if (IsEqualIID(riid, &IID_IMFTransform) ||
|
||||
+ IsEqualIID(riid, &IID_IUnknown))
|
||||
+ {
|
||||
+ *obj = iface;
|
||||
+ IMFTransform_AddRef(iface);
|
||||
+ return S_OK;
|
||||
+ }
|
||||
+
|
||||
+ WARN("Unsupported %s.\n", debugstr_guid(riid));
|
||||
+ *obj = NULL;
|
||||
+ return E_NOINTERFACE;
|
||||
+}
|
||||
+
|
||||
+static ULONG WINAPI audio_converter_AddRef(IMFTransform *iface)
|
||||
+{
|
||||
+ struct audio_converter *transform = impl_audio_converter_from_IMFTransform(iface);
|
||||
+ ULONG refcount = InterlockedIncrement(&transform->refcount);
|
||||
+
|
||||
+ TRACE("%p, refcount %u.\n", iface, refcount);
|
||||
+
|
||||
+ return refcount;
|
||||
+}
|
||||
+
|
||||
+static ULONG WINAPI audio_converter_Release(IMFTransform *iface)
|
||||
+{
|
||||
+ struct audio_converter *transform = impl_audio_converter_from_IMFTransform(iface);
|
||||
+ ULONG refcount = InterlockedDecrement(&transform->refcount);
|
||||
+
|
||||
+ TRACE("%p, refcount %u.\n", iface, refcount);
|
||||
+
|
||||
+ if (!refcount)
|
||||
+ {
|
||||
+ if (transform->attributes)
|
||||
+ IMFAttributes_Release(transform->attributes);
|
||||
+ if (transform->output_attributes)
|
||||
+ IMFAttributes_Release(transform->output_attributes);
|
||||
+ heap_free(transform);
|
||||
+ }
|
||||
+
|
||||
+ return refcount;
|
||||
+}
|
||||
+
|
||||
+static HRESULT WINAPI audio_converter_GetStreamLimits(IMFTransform *iface, DWORD *input_minimum, DWORD *input_maximum,
|
||||
+ DWORD *output_minimum, DWORD *output_maximum)
|
||||
+{
|
||||
+ TRACE("%p, %p, %p, %p, %p.\n", iface, input_minimum, input_maximum, output_minimum, output_maximum);
|
||||
+
|
||||
+ *input_minimum = *input_maximum = *output_minimum = *output_maximum = 1;
|
||||
+
|
||||
+ return S_OK;
|
||||
+}
|
||||
+
|
||||
+static HRESULT WINAPI audio_converter_GetStreamCount(IMFTransform *iface, DWORD *inputs, DWORD *outputs)
|
||||
+{
|
||||
+ TRACE("%p, %p, %p.\n", iface, inputs, outputs);
|
||||
+
|
||||
+ *inputs = *outputs = 1;
|
||||
+
|
||||
+ return S_OK;
|
||||
+}
|
||||
+
|
||||
+static HRESULT WINAPI audio_converter_GetStreamIDs(IMFTransform *iface, DWORD input_size, DWORD *inputs,
|
||||
+ DWORD output_size, DWORD *outputs)
|
||||
+{
|
||||
+ return E_NOTIMPL;
|
||||
+}
|
||||
+
|
||||
+static HRESULT WINAPI audio_converter_GetInputStreamInfo(IMFTransform *iface, DWORD id, MFT_INPUT_STREAM_INFO *info)
|
||||
+{
|
||||
+ struct audio_converter *converter = impl_audio_converter_from_IMFTransform(iface);
|
||||
+
|
||||
+ TRACE("%p %u %p\n", converter, id, info);
|
||||
+
|
||||
+ if (id != 0)
|
||||
+ return MF_E_INVALIDSTREAMNUMBER;
|
||||
+
|
||||
+ /* If we create a wrapped GstBuffer, remove MFT_INPUT_STREAM_DOES_NOT_ADDREF */
|
||||
+ info->dwFlags = MFT_INPUT_STREAM_WHOLE_SAMPLES | MFT_INPUT_STREAM_DOES_NOT_ADDREF;
|
||||
+ info->cbMaxLookahead = 0;
|
||||
+ info->cbAlignment = 0;
|
||||
+ /* this is incorrect */
|
||||
+ info->hnsMaxLatency = 0;
|
||||
+ return S_OK;
|
||||
+}
|
||||
+
|
||||
+static HRESULT WINAPI audio_converter_GetOutputStreamInfo(IMFTransform *iface, DWORD id, MFT_OUTPUT_STREAM_INFO *info)
|
||||
+{
|
||||
+ struct audio_converter *converter = impl_audio_converter_from_IMFTransform(iface);
|
||||
+
|
||||
+ MFT_OUTPUT_STREAM_INFO stream_info = {};
|
||||
+
|
||||
+ TRACE("%p %u %p\n", converter, id, info);
|
||||
+
|
||||
+ if (id != 0)
|
||||
+ return MF_E_INVALIDSTREAMNUMBER;
|
||||
+
|
||||
+ stream_info.dwFlags = MFT_OUTPUT_STREAM_PROVIDES_SAMPLES;
|
||||
+ stream_info.cbSize = 0;
|
||||
+ stream_info.cbAlignment = 0;
|
||||
+
|
||||
+ *info = stream_info;
|
||||
+
|
||||
+ return S_OK;
|
||||
+}
|
||||
+
|
||||
+static HRESULT WINAPI audio_converter_GetAttributes(IMFTransform *iface, IMFAttributes **attributes)
|
||||
+{
|
||||
+ struct audio_converter *transform = impl_audio_converter_from_IMFTransform(iface);
|
||||
+
|
||||
+ TRACE("%p, %p.\n", iface, attributes);
|
||||
+
|
||||
+ *attributes = transform->attributes;
|
||||
+ IMFAttributes_AddRef(*attributes);
|
||||
+
|
||||
+ return S_OK;
|
||||
+}
|
||||
+
|
||||
+static HRESULT WINAPI audio_converter_GetInputStreamAttributes(IMFTransform *iface, DWORD id,
|
||||
+ IMFAttributes **attributes)
|
||||
+{
|
||||
+ return E_NOTIMPL;
|
||||
+}
|
||||
+
|
||||
+static HRESULT WINAPI audio_converter_GetOutputStreamAttributes(IMFTransform *iface, DWORD id,
|
||||
+ IMFAttributes **attributes)
|
||||
+{
|
||||
+ struct audio_converter *transform = impl_audio_converter_from_IMFTransform(iface);
|
||||
+
|
||||
+ TRACE("%p, %u, %p.\n", iface, id, attributes);
|
||||
+
|
||||
+ *attributes = transform->output_attributes;
|
||||
+ IMFAttributes_AddRef(*attributes);
|
||||
+
|
||||
+ return S_OK;
|
||||
+}
|
||||
+
|
||||
+static HRESULT WINAPI audio_converter_DeleteInputStream(IMFTransform *iface, DWORD id)
|
||||
+{
|
||||
+ TRACE("%p, %u.\n", iface, id);
|
||||
+
|
||||
+ return E_NOTIMPL;
|
||||
+}
|
||||
+
|
||||
+static HRESULT WINAPI audio_converter_AddInputStreams(IMFTransform *iface, DWORD streams, DWORD *ids)
|
||||
+{
|
||||
+ TRACE("%p, %u, %p.\n", iface, streams, ids);
|
||||
+
|
||||
+ return E_NOTIMPL;
|
||||
+}
|
||||
+
|
||||
+static HRESULT WINAPI audio_converter_GetInputAvailableType(IMFTransform *iface, DWORD id, DWORD index,
|
||||
+ IMFMediaType **type)
|
||||
+{
|
||||
+ IMFMediaType *ret;
|
||||
+ HRESULT hr;
|
||||
+
|
||||
+ TRACE("%p, %u, %u, %p.\n", iface, id, index, type);
|
||||
+
|
||||
+ if (id != 0)
|
||||
+ return MF_E_INVALIDSTREAMNUMBER;
|
||||
+
|
||||
+ if (index >= ARRAY_SIZE(raw_types))
|
||||
+ return MF_E_NO_MORE_TYPES;
|
||||
+
|
||||
+ if (FAILED(hr = MFCreateMediaType(&ret)))
|
||||
+ return hr;
|
||||
+
|
||||
+ if (FAILED(hr = IMFMediaType_SetGUID(ret, &MF_MT_MAJOR_TYPE, &MFMediaType_Audio)))
|
||||
+ {
|
||||
+ IMFMediaType_Release(ret);
|
||||
+ return hr;
|
||||
+ }
|
||||
+
|
||||
+ if (FAILED(hr = IMFMediaType_SetGUID(ret, &MF_MT_SUBTYPE, raw_types[index])))
|
||||
+ {
|
||||
+ IMFMediaType_Release(ret);
|
||||
+ return hr;
|
||||
+ }
|
||||
+
|
||||
+ *type = ret;
|
||||
+
|
||||
+ return S_OK;
|
||||
+}
|
||||
+
|
||||
+static void copy_attr(IMFMediaType *target, IMFMediaType *source, const GUID *key)
|
||||
+{
|
||||
+ PROPVARIANT val;
|
||||
+
|
||||
+ if (SUCCEEDED(IMFAttributes_GetItem((IMFAttributes *)source, key, &val)))
|
||||
+ {
|
||||
+ IMFAttributes_SetItem((IMFAttributes* )target, key, &val);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static HRESULT WINAPI audio_converter_GetOutputAvailableType(IMFTransform *iface, DWORD id, DWORD index,
|
||||
+ IMFMediaType **type)
|
||||
+{
|
||||
+ struct audio_converter *converter = impl_audio_converter_from_IMFTransform(iface);
|
||||
+ IMFMediaType *output_type;
|
||||
+ HRESULT hr;
|
||||
+
|
||||
+ static const DWORD rates[] = {44100, 48000};
|
||||
+ static const DWORD channel_cnts[] = {1, 2, 6};
|
||||
+ static const DWORD sizes[] = {16, 24, 32};
|
||||
+ const GUID *subtype;
|
||||
+ DWORD rate, channels, bps;
|
||||
+
|
||||
+ TRACE("%p, %u, %u, %p.\n", iface, id, index, type);
|
||||
+
|
||||
+ if (id != 0)
|
||||
+ return MF_E_INVALIDSTREAMNUMBER;
|
||||
+
|
||||
+ if (!(converter->input_type))
|
||||
+ return MF_E_TRANSFORM_TYPE_NOT_SET;
|
||||
+
|
||||
+ if (index >= (2/*rates*/ * 3/*layouts*/ * 3/*bps PCM*/) + (2 * 3))
|
||||
+ return MF_E_NO_MORE_TYPES;
|
||||
+
|
||||
+ if (FAILED(hr = MFCreateMediaType(&output_type)))
|
||||
+ return hr;
|
||||
+
|
||||
+ copy_attr(output_type, converter->input_type, &MF_MT_MAJOR_TYPE);
|
||||
+
|
||||
+ if (index < 2 * 3 * 3)
|
||||
+ {
|
||||
+ subtype = &MFAudioFormat_PCM;
|
||||
+ rate = rates[index % 2];
|
||||
+ channels = channel_cnts[(index / 2) % 3];
|
||||
+ bps = sizes[(index / (2*3)) % 3];
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ index -= (2 * 3 * 3);
|
||||
+ subtype = &MFAudioFormat_Float;
|
||||
+ bps = 32;
|
||||
+ rate = rates[index % 2];
|
||||
+ channels = channel_cnts[(index / 2) % 3];
|
||||
+ }
|
||||
+
|
||||
+ if (FAILED(hr = IMFMediaType_SetGUID(output_type, &MF_MT_SUBTYPE, subtype)))
|
||||
+ goto fail;
|
||||
+ if (FAILED(hr = IMFMediaType_SetUINT32(output_type, &MF_MT_AUDIO_SAMPLES_PER_SECOND, rate)))
|
||||
+ goto fail;
|
||||
+ if (FAILED(hr = IMFMediaType_SetUINT32(output_type, &MF_MT_AUDIO_NUM_CHANNELS, channels)))
|
||||
+ goto fail;
|
||||
+ if (FAILED(hr = IMFMediaType_SetUINT32(output_type, &MF_MT_AUDIO_BITS_PER_SAMPLE, bps)))
|
||||
+ goto fail;
|
||||
+
|
||||
+ if (FAILED(hr = IMFMediaType_SetUINT32(output_type, &MF_MT_AUDIO_BLOCK_ALIGNMENT, channels * bps / 8)))
|
||||
+ goto fail;
|
||||
+ if (FAILED(hr = IMFMediaType_SetUINT32(output_type, &MF_MT_AUDIO_AVG_BYTES_PER_SECOND, rate * channels * bps / 8)))
|
||||
+ goto fail;
|
||||
+ if (FAILED(hr = IMFMediaType_SetUINT32(output_type, &MF_MT_AUDIO_CHANNEL_MASK,
|
||||
+ channels == 1 ? SPEAKER_FRONT_CENTER :
|
||||
+ channels == 2 ? SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT :
|
||||
+ /*channels == 6*/ 0x3F)))
|
||||
+ goto fail;
|
||||
+ if (FAILED(hr = IMFMediaType_SetUINT32(output_type, &MF_MT_ALL_SAMPLES_INDEPENDENT, TRUE)))
|
||||
+ goto fail;
|
||||
+
|
||||
+ *type = output_type;
|
||||
+
|
||||
+ return S_OK;
|
||||
+ fail:
|
||||
+ IMFMediaType_Release(output_type);
|
||||
+ return hr;
|
||||
+}
|
||||
+
|
||||
+static void audio_converter_update_pipeline_state(struct audio_converter *converter)
|
||||
+{
|
||||
+ GstCaps *input_caps, *output_caps;
|
||||
+ gchar *input_caps_str, *output_caps_str;
|
||||
+
|
||||
+ converter->valid_state = converter->input_type && converter->output_type;
|
||||
+
|
||||
+ if (!converter->valid_state)
|
||||
+ {
|
||||
+ gst_element_set_state(converter->container, GST_STATE_READY);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ g_object_set(converter->appsrc, "caps", (input_caps = caps_from_mf_media_type(converter->input_type)), NULL);
|
||||
+ g_object_set(converter->appsink, "caps", (output_caps = caps_from_mf_media_type(converter->output_type)), NULL);
|
||||
+
|
||||
+ input_caps_str = gst_caps_to_string(input_caps);
|
||||
+ output_caps_str = gst_caps_to_string(output_caps);
|
||||
+ TRACE("AUDIO CONVERTER IN =\n%s\nAUDIO CONVERTER OUT = \n%s\n", debugstr_a(input_caps_str), debugstr_a(output_caps_str));
|
||||
+ g_free(input_caps_str);
|
||||
+ g_free(output_caps_str);
|
||||
+
|
||||
+ gst_element_set_state(converter->container, GST_STATE_PLAYING);
|
||||
+ return;
|
||||
+}
|
||||
+
|
||||
+static HRESULT WINAPI audio_converter_SetInputType(IMFTransform *iface, DWORD id, IMFMediaType *type, DWORD flags)
|
||||
+{
|
||||
+ HRESULT hr;
|
||||
+
|
||||
+ struct audio_converter *converter = impl_audio_converter_from_IMFTransform(iface);
|
||||
+
|
||||
+ TRACE("%p, %u, %p, %#x.\n", iface, id, type, flags);
|
||||
+
|
||||
+ if (id != 0)
|
||||
+ return MF_E_INVALIDSTREAMNUMBER;
|
||||
+
|
||||
+ if (type)
|
||||
+ {
|
||||
+ GUID major_type, subtype;
|
||||
+ DWORD unused;
|
||||
+ BOOL found = FALSE;
|
||||
+
|
||||
+ if (FAILED(IMFMediaType_GetGUID(type, &MF_MT_MAJOR_TYPE, &major_type)))
|
||||
+ return MF_E_INVALIDTYPE;
|
||||
+ if (FAILED(IMFMediaType_GetGUID(type, &MF_MT_SUBTYPE, &subtype)))
|
||||
+ return MF_E_INVALIDTYPE;
|
||||
+ if (FAILED(IMFMediaType_GetUINT32(type, &MF_MT_AUDIO_SAMPLES_PER_SECOND, &unused)))
|
||||
+ return MF_E_INVALIDTYPE;
|
||||
+ if (FAILED(IMFMediaType_GetUINT32(type, &MF_MT_AUDIO_NUM_CHANNELS, &unused)))
|
||||
+ return MF_E_INVALIDTYPE;
|
||||
+ if (IsEqualGUID(&subtype, &MFAudioFormat_PCM) && FAILED(IMFMediaType_GetUINT32(type, &MF_MT_AUDIO_BITS_PER_SAMPLE, &unused)))
|
||||
+ return MF_E_INVALIDTYPE;
|
||||
+
|
||||
+ if (!(IsEqualGUID(&major_type, &MFMediaType_Audio)))
|
||||
+ return MF_E_INVALIDTYPE;
|
||||
+
|
||||
+ for (unsigned int i = 0; i < ARRAY_SIZE(raw_types); i++)
|
||||
+ {
|
||||
+ if (IsEqualGUID(&subtype, raw_types[i]))
|
||||
+ {
|
||||
+ found = TRUE;
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (!found)
|
||||
+ return MF_E_INVALIDTYPE;
|
||||
+ }
|
||||
+
|
||||
+ if (flags & MFT_SET_TYPE_TEST_ONLY)
|
||||
+ return S_OK;
|
||||
+
|
||||
+ hr = S_OK;
|
||||
+
|
||||
+ EnterCriticalSection(&converter->cs);
|
||||
+
|
||||
+ if (type)
|
||||
+ {
|
||||
+ if (!converter->input_type)
|
||||
+ if (FAILED(hr = MFCreateMediaType(&converter->input_type)))
|
||||
+ goto done;
|
||||
+
|
||||
+ if (FAILED(hr = IMFMediaType_CopyAllItems(type, (IMFAttributes *) converter->input_type)))
|
||||
+ goto done;
|
||||
+ }
|
||||
+ else if (converter->input_type)
|
||||
+ {
|
||||
+ IMFMediaType_Release(converter->input_type);
|
||||
+ converter->input_type = NULL;
|
||||
+ }
|
||||
+
|
||||
+ done:
|
||||
+ if (hr == S_OK)
|
||||
+ audio_converter_update_pipeline_state(converter);
|
||||
+ LeaveCriticalSection(&converter->cs);
|
||||
+
|
||||
+ return S_OK;
|
||||
+}
|
||||
+
|
||||
+static HRESULT WINAPI audio_converter_SetOutputType(IMFTransform *iface, DWORD id, IMFMediaType *type, DWORD flags)
|
||||
+{
|
||||
+ struct audio_converter *converter = impl_audio_converter_from_IMFTransform(iface);
|
||||
+ HRESULT hr;
|
||||
+ GUID major_type, subtype;
|
||||
+ DWORD output_sample_rate;
|
||||
+ DWORD unused;
|
||||
+
|
||||
+ TRACE("%p, %u, %p, %#x.\n", iface, id, type, flags);
|
||||
+
|
||||
+ if (id != 0)
|
||||
+ return MF_E_INVALIDSTREAMNUMBER;
|
||||
+
|
||||
+ if (!converter->input_type)
|
||||
+ return MF_E_TRANSFORM_TYPE_NOT_SET;
|
||||
+
|
||||
+ if (type)
|
||||
+ {
|
||||
+ /* validate the type */
|
||||
+
|
||||
+ if (FAILED(IMFMediaType_GetGUID(type, &MF_MT_MAJOR_TYPE, &major_type)))
|
||||
+ return MF_E_INVALIDTYPE;
|
||||
+ if (FAILED(IMFMediaType_GetGUID(type, &MF_MT_SUBTYPE, &subtype)))
|
||||
+ return MF_E_INVALIDTYPE;
|
||||
+ if (FAILED(IMFMediaType_GetUINT32(type, &MF_MT_AUDIO_NUM_CHANNELS, &unused)))
|
||||
+ return MF_E_INVALIDTYPE;
|
||||
+ if (IsEqualGUID(&subtype, &MFAudioFormat_PCM) && FAILED(IMFMediaType_GetUINT32(type, &MF_MT_AUDIO_BITS_PER_SAMPLE, &unused)))
|
||||
+ return MF_E_INVALIDTYPE;
|
||||
+
|
||||
+
|
||||
+ if (FAILED(IMFMediaType_GetUINT32(type, &MF_MT_AUDIO_SAMPLES_PER_SECOND, &output_sample_rate)))
|
||||
+ return MF_E_INVALIDTYPE;
|
||||
+
|
||||
+ if (!(IsEqualGUID(&major_type, &MFMediaType_Audio)))
|
||||
+ return MF_E_INVALIDTYPE;
|
||||
+
|
||||
+ for (unsigned int i = 0; i < ARRAY_SIZE(raw_types); i++)
|
||||
+ {
|
||||
+ if (IsEqualGUID(&subtype, raw_types[i]))
|
||||
+ break;
|
||||
+ if (i == ARRAY_SIZE(raw_types))
|
||||
+ return MF_E_INVALIDTYPE;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (flags & MFT_SET_TYPE_TEST_ONLY)
|
||||
+ return S_OK;
|
||||
+
|
||||
+ EnterCriticalSection(&converter->cs);
|
||||
+
|
||||
+ hr = S_OK;
|
||||
+
|
||||
+ if (type)
|
||||
+ {
|
||||
+ if (!converter->output_type)
|
||||
+ if (FAILED(hr = MFCreateMediaType(&converter->output_type)))
|
||||
+ goto done;
|
||||
+
|
||||
+ if (FAILED(hr = IMFMediaType_CopyAllItems(type, (IMFAttributes *) converter->output_type)))
|
||||
+ goto done;
|
||||
+ }
|
||||
+ else if (converter->output_type)
|
||||
+ {
|
||||
+ IMFMediaType_Release(converter->output_type);
|
||||
+ converter->output_type = NULL;
|
||||
+ }
|
||||
+
|
||||
+ done:
|
||||
+ if (hr == S_OK)
|
||||
+ audio_converter_update_pipeline_state(converter);
|
||||
+ LeaveCriticalSection(&converter->cs);
|
||||
+
|
||||
+ return hr;
|
||||
+}
|
||||
+
|
||||
+static HRESULT WINAPI audio_converter_GetInputCurrentType(IMFTransform *iface, DWORD id, IMFMediaType **type)
|
||||
+{
|
||||
+ FIXME("%p, %u, %p.\n", iface, id, type);
|
||||
+
|
||||
+ return E_NOTIMPL;
|
||||
+}
|
||||
+
|
||||
+static HRESULT WINAPI audio_converter_GetOutputCurrentType(IMFTransform *iface, DWORD id, IMFMediaType **type)
|
||||
+{
|
||||
+ FIXME("%p, %u, %p.\n", iface, id, type);
|
||||
+
|
||||
+ return E_NOTIMPL;
|
||||
+}
|
||||
+
|
||||
+static HRESULT WINAPI audio_converter_GetInputStatus(IMFTransform *iface, DWORD id, DWORD *flags)
|
||||
+{
|
||||
+ FIXME("%p, %u, %p.\n", iface, id, flags);
|
||||
+
|
||||
+ return E_NOTIMPL;
|
||||
+}
|
||||
+
|
||||
+static HRESULT WINAPI audio_converter_GetOutputStatus(IMFTransform *iface, DWORD *flags)
|
||||
+{
|
||||
+ FIXME("%p, %p.\n", iface, flags);
|
||||
+
|
||||
+ return E_NOTIMPL;
|
||||
+}
|
||||
+
|
||||
+static HRESULT WINAPI audio_converter_SetOutputBounds(IMFTransform *iface, LONGLONG lower, LONGLONG upper)
|
||||
+{
|
||||
+ FIXME("%p, %s, %s.\n", iface, wine_dbgstr_longlong(lower), wine_dbgstr_longlong(upper));
|
||||
+
|
||||
+ return E_NOTIMPL;
|
||||
+}
|
||||
+
|
||||
+static HRESULT WINAPI audio_converter_ProcessEvent(IMFTransform *iface, DWORD id, IMFMediaEvent *event)
|
||||
+{
|
||||
+ TRACE("%p, %u, %p.\n", iface, id, event);
|
||||
+
|
||||
+ return E_NOTIMPL;
|
||||
+}
|
||||
+
|
||||
+static HRESULT WINAPI audio_converter_ProcessMessage(IMFTransform *iface, MFT_MESSAGE_TYPE message, ULONG_PTR param)
|
||||
+{
|
||||
+ FIXME("%p, %u.\n", iface, message);
|
||||
+
|
||||
+ return S_OK;
|
||||
+}
|
||||
+
|
||||
+static HRESULT WINAPI audio_converter_ProcessInput(IMFTransform *iface, DWORD id, IMFSample *sample, DWORD flags)
|
||||
+{
|
||||
+ struct audio_converter *converter = impl_audio_converter_from_IMFTransform(iface);
|
||||
+ GstBuffer *gst_buffer;
|
||||
+ HRESULT hr = S_OK;
|
||||
+ int ret;
|
||||
+
|
||||
+ TRACE("%p, %u, %p, %#x.\n", iface, id, sample, flags);
|
||||
+
|
||||
+ if (flags)
|
||||
+ WARN("Unsupported flags %#x\n", flags);
|
||||
+
|
||||
+ if (id != 0)
|
||||
+ return MF_E_INVALIDSTREAMNUMBER;
|
||||
+
|
||||
+ EnterCriticalSection(&converter->cs);
|
||||
+
|
||||
+ if (!converter->valid_state)
|
||||
+ {
|
||||
+ hr = MF_E_TRANSFORM_TYPE_NOT_SET;
|
||||
+ goto done;
|
||||
+ }
|
||||
+
|
||||
+ if (converter->inflight)
|
||||
+ {
|
||||
+ hr = MF_E_NOTACCEPTING;
|
||||
+ goto done;
|
||||
+ }
|
||||
+
|
||||
+ if (!(gst_buffer = gst_buffer_from_mf_sample(sample)))
|
||||
+ {
|
||||
+ hr = E_FAIL;
|
||||
+ goto done;
|
||||
+ }
|
||||
+
|
||||
+ g_signal_emit_by_name(converter->appsrc, "push-buffer", gst_buffer, &ret);
|
||||
+ gst_buffer_unref(gst_buffer);
|
||||
+ if (ret != GST_FLOW_OK)
|
||||
+ {
|
||||
+ ERR("Couldn't push buffer ret = %d\n", ret);
|
||||
+ hr = E_FAIL;
|
||||
+ goto done;
|
||||
+ }
|
||||
+
|
||||
+ converter->inflight = TRUE;
|
||||
+
|
||||
+ done:
|
||||
+ LeaveCriticalSection(&converter->cs);
|
||||
+
|
||||
+ return hr;
|
||||
+}
|
||||
+
|
||||
+static HRESULT WINAPI audio_converter_ProcessOutput(IMFTransform *iface, DWORD flags, DWORD count,
|
||||
+ MFT_OUTPUT_DATA_BUFFER *samples, DWORD *status)
|
||||
+{
|
||||
+ struct audio_converter *converter = impl_audio_converter_from_IMFTransform(iface);
|
||||
+ MFT_OUTPUT_DATA_BUFFER *relevant_buffer = NULL;
|
||||
+ GstSample *sample;
|
||||
+ HRESULT hr = S_OK;
|
||||
+
|
||||
+ TRACE("%p, %#x, %u, %p, %p.\n", iface, flags, count, samples, status);
|
||||
+
|
||||
+ if (flags)
|
||||
+ WARN("Unsupported flags %#x\n", flags);
|
||||
+
|
||||
+ for (unsigned int i = 0; i < count; i++)
|
||||
+ {
|
||||
+ MFT_OUTPUT_DATA_BUFFER *out_buffer = &samples[i];
|
||||
+
|
||||
+ if (out_buffer->dwStreamID != 0)
|
||||
+ return MF_E_INVALIDSTREAMNUMBER;
|
||||
+
|
||||
+ if (relevant_buffer)
|
||||
+ return MF_E_INVALIDSTREAMNUMBER;
|
||||
+
|
||||
+ relevant_buffer = out_buffer;
|
||||
+ }
|
||||
+
|
||||
+ if (!relevant_buffer)
|
||||
+ return S_OK;
|
||||
+
|
||||
+ EnterCriticalSection(&converter->cs);
|
||||
+
|
||||
+ if (!converter->valid_state)
|
||||
+ {
|
||||
+ hr = MF_E_TRANSFORM_TYPE_NOT_SET;
|
||||
+ goto done;
|
||||
+ }
|
||||
+
|
||||
+ if (!converter->inflight)
|
||||
+ {
|
||||
+ hr = MF_E_TRANSFORM_NEED_MORE_INPUT;
|
||||
+ goto done;
|
||||
+ }
|
||||
+
|
||||
+ g_signal_emit_by_name(converter->appsink, "pull-sample", &sample);
|
||||
+
|
||||
+ converter->inflight = FALSE;
|
||||
+
|
||||
+ relevant_buffer->pSample = mf_sample_from_gst_buffer(gst_sample_get_buffer(sample));
|
||||
+ gst_sample_unref(sample);
|
||||
+ relevant_buffer->dwStatus = S_OK;
|
||||
+ relevant_buffer->pEvents = NULL;
|
||||
+ *status = 0;
|
||||
+
|
||||
+ done:
|
||||
+ LeaveCriticalSection(&converter->cs);
|
||||
+
|
||||
+ return hr;
|
||||
+}
|
||||
+
|
||||
+static const IMFTransformVtbl audio_converter_vtbl =
|
||||
+{
|
||||
+ audio_converter_QueryInterface,
|
||||
+ audio_converter_AddRef,
|
||||
+ audio_converter_Release,
|
||||
+ audio_converter_GetStreamLimits,
|
||||
+ audio_converter_GetStreamCount,
|
||||
+ audio_converter_GetStreamIDs,
|
||||
+ audio_converter_GetInputStreamInfo,
|
||||
+ audio_converter_GetOutputStreamInfo,
|
||||
+ audio_converter_GetAttributes,
|
||||
+ audio_converter_GetInputStreamAttributes,
|
||||
+ audio_converter_GetOutputStreamAttributes,
|
||||
+ audio_converter_DeleteInputStream,
|
||||
+ audio_converter_AddInputStreams,
|
||||
+ audio_converter_GetInputAvailableType,
|
||||
+ audio_converter_GetOutputAvailableType,
|
||||
+ audio_converter_SetInputType,
|
||||
+ audio_converter_SetOutputType,
|
||||
+ audio_converter_GetInputCurrentType,
|
||||
+ audio_converter_GetOutputCurrentType,
|
||||
+ audio_converter_GetInputStatus,
|
||||
+ audio_converter_GetOutputStatus,
|
||||
+ audio_converter_SetOutputBounds,
|
||||
+ audio_converter_ProcessEvent,
|
||||
+ audio_converter_ProcessMessage,
|
||||
+ audio_converter_ProcessInput,
|
||||
+ audio_converter_ProcessOutput,
|
||||
+};
|
||||
+
|
||||
+HRESULT audio_converter_create(REFIID riid, void **ret)
|
||||
+{
|
||||
+ struct audio_converter *object;
|
||||
+ HRESULT hr;
|
||||
+
|
||||
+ TRACE("%s %p\n", debugstr_guid(riid), ret);
|
||||
+
|
||||
+ if (!(object = heap_alloc_zero(sizeof(*object))))
|
||||
+ return E_OUTOFMEMORY;
|
||||
+
|
||||
+ object->IMFTransform_iface.lpVtbl = &audio_converter_vtbl;
|
||||
+ object->refcount = 1;
|
||||
+
|
||||
+ InitializeCriticalSection(&object->cs);
|
||||
+
|
||||
+ if (FAILED(hr = MFCreateAttributes(&object->attributes, 0)))
|
||||
+ goto failed;
|
||||
+
|
||||
+ if (FAILED(hr = MFCreateAttributes(&object->output_attributes, 0)))
|
||||
+ goto failed;
|
||||
+
|
||||
+ object->container = gst_bin_new(NULL);
|
||||
+ object->bus = gst_bus_new();
|
||||
+ gst_element_set_bus(object->container, object->bus);
|
||||
+
|
||||
+ if (!(object->appsrc = gst_element_factory_make("appsrc", NULL)))
|
||||
+ {
|
||||
+ ERR("Failed to create appsrc");
|
||||
+ hr = E_FAIL;
|
||||
+ goto failed;
|
||||
+ }
|
||||
+ gst_bin_add(GST_BIN(object->container), object->appsrc);
|
||||
+
|
||||
+ if (!(object->audioconvert = gst_element_factory_make("audioconvert", NULL)))
|
||||
+ {
|
||||
+ ERR("Failed to create converter\n");
|
||||
+ hr = E_FAIL;
|
||||
+ goto failed;
|
||||
+ }
|
||||
+ gst_bin_add(GST_BIN(object->container), object->audioconvert);
|
||||
+
|
||||
+ if (!(object->resampler = gst_element_factory_make("audioresample", NULL)))
|
||||
+ {
|
||||
+ ERR("Failed to create resampler\n");
|
||||
+ hr = E_FAIL;
|
||||
+ goto failed;
|
||||
+ }
|
||||
+ gst_bin_add(GST_BIN(object->container), object->resampler);
|
||||
+
|
||||
+ if (!(object->appsink = gst_element_factory_make("appsink", NULL)))
|
||||
+ {
|
||||
+ ERR("Failed to create appsink\n");
|
||||
+ hr = E_FAIL;
|
||||
+ goto failed;
|
||||
+ }
|
||||
+ gst_bin_add(GST_BIN(object->container), object->appsink);
|
||||
+
|
||||
+ if (!(gst_element_link(object->appsrc, object->audioconvert)))
|
||||
+ {
|
||||
+ ERR("Failed to link appsrc to audioconvert\n");
|
||||
+ hr = E_FAIL;
|
||||
+ goto failed;
|
||||
+ }
|
||||
+
|
||||
+ if (!(gst_element_link(object->audioconvert, object->resampler)))
|
||||
+ {
|
||||
+ ERR("Failed to link audioconvert to resampler\n");
|
||||
+ hr = E_FAIL;
|
||||
+ goto failed;
|
||||
+ }
|
||||
+
|
||||
+ if (!(gst_element_link(object->resampler, object->appsink)))
|
||||
+ {
|
||||
+ ERR("Failed to link resampler to appsink\n");
|
||||
+ hr = E_FAIL;
|
||||
+ goto failed;
|
||||
+ }
|
||||
+
|
||||
+ *ret = &object->IMFTransform_iface;
|
||||
+ return S_OK;
|
||||
+
|
||||
+failed:
|
||||
+
|
||||
+ IMFTransform_Release(&object->IMFTransform_iface);
|
||||
+ return hr;
|
||||
+}
|
||||
\ No newline at end of file
|
||||
diff --git a/dlls/winegstreamer/gst_private.h b/dlls/winegstreamer/gst_private.h
|
||||
index 8e75beb82dd..b505387637b 100644
|
||||
--- a/dlls/winegstreamer/gst_private.h
|
||||
+++ b/dlls/winegstreamer/gst_private.h
|
||||
@@ -75,5 +75,6 @@ HRESULT generic_decoder_construct(REFIID riid, void **obj, enum decoder_type) DE
|
||||
HRESULT winegstreamer_stream_handler_create(REFIID riid, void **obj) DECLSPEC_HIDDEN;
|
||||
|
||||
HRESULT color_converter_create(REFIID riid, void **ret);
|
||||
+HRESULT audio_converter_create(REFIID riid, void **ret);
|
||||
|
||||
#endif /* __GST_PRIVATE_INCLUDED__ */
|
||||
diff --git a/dlls/winegstreamer/mfplat.c b/dlls/winegstreamer/mfplat.c
|
||||
index 28c9beb4649..3b50264d0f8 100644
|
||||
--- a/dlls/winegstreamer/mfplat.c
|
||||
+++ b/dlls/winegstreamer/mfplat.c
|
||||
@@ -433,6 +433,8 @@ static HRESULT m4s2_decoder_create(REFIID riid, void **ret)
|
||||
|
||||
static GUID CLSID_CColorConvertDMO = {0x98230571,0x0087,0x4204,{0xb0,0x20,0x32,0x82,0x53,0x8e,0x57,0xd3}};
|
||||
|
||||
+static GUID CLSID_WINEAudioConverter = {0x6a170414,0xaad9,0x4693,{0xb8,0x06,0x3a,0x0c,0x47,0xc5,0x70,0xd6}};
|
||||
+
|
||||
static const struct class_object
|
||||
{
|
||||
const GUID *clsid;
|
||||
@@ -448,6 +450,7 @@ class_objects[] =
|
||||
{ &CLSID_CWMADecMediaObject, &wma_decoder_create },
|
||||
{ &CLSID_CMpeg4sDecMFT, m4s2_decoder_create },
|
||||
{ &CLSID_CColorConvertDMO, &color_converter_create },
|
||||
+ { &CLSID_WINEAudioConverter, &audio_converter_create },
|
||||
};
|
||||
|
||||
HRESULT mfplat_get_class_object(REFCLSID rclsid, REFIID riid, void **obj)
|
||||
@@ -497,6 +500,14 @@ const GUID *color_converter_supported_types[] =
|
||||
&MFVideoFormat_YVYU,
|
||||
};
|
||||
|
||||
+static WCHAR audio_converterW[] = {'A','u','d','i','o',' ','C','o','n','v','e','r','t','e','r',0};
|
||||
+
|
||||
+const GUID *audio_converter_supported_types[] =
|
||||
+{
|
||||
+ &MFAudioFormat_PCM,
|
||||
+ &MFAudioFormat_Float,
|
||||
+};
|
||||
+
|
||||
static WCHAR h264decoderW[] = {'H','.','2','6','4',' ','D','e','c','o','d','e','r',0};
|
||||
const GUID *h264_decoder_input_types[] =
|
||||
{
|
||||
@@ -603,6 +614,18 @@ mfts[] =
|
||||
color_converter_supported_types,
|
||||
NULL
|
||||
},
|
||||
+ {
|
||||
+ &CLSID_WINEAudioConverter,
|
||||
+ &MFT_CATEGORY_AUDIO_EFFECT,
|
||||
+ audio_converterW,
|
||||
+ MFT_ENUM_FLAG_SYNCMFT,
|
||||
+ &MFMediaType_Audio,
|
||||
+ ARRAY_SIZE(audio_converter_supported_types),
|
||||
+ audio_converter_supported_types,
|
||||
+ ARRAY_SIZE(audio_converter_supported_types),
|
||||
+ audio_converter_supported_types,
|
||||
+ NULL
|
||||
+ },
|
||||
{
|
||||
&CLSID_CMSH264DecoderMFT,
|
||||
&MFT_CATEGORY_VIDEO_DECODER,
|
||||
diff --git a/dlls/winegstreamer/winegstreamer_classes.idl b/dlls/winegstreamer/winegstreamer_classes.idl
|
||||
index c014d359a39..c58fa417bbe 100644
|
||||
--- a/dlls/winegstreamer/winegstreamer_classes.idl
|
||||
+++ b/dlls/winegstreamer/winegstreamer_classes.idl
|
||||
@@ -97,3 +97,9 @@ coclass CLSID_CWMADecMediaObject {}
|
||||
uuid(98230571-0087-4204-b020-3282538e57d3)
|
||||
]
|
||||
coclass CColorConvertDMO { }
|
||||
+
|
||||
+[
|
||||
+ threading(both),
|
||||
+ uuid(6a170414-aad9-4693-b806-3a0c47c570d6)
|
||||
+]
|
||||
+coclass WINEAudioConverter { }
|
||||
--
|
||||
2.28.0
|
||||
|
@ -1,32 +0,0 @@
|
||||
From 69fd2aa695178b36154ded6a13b74a5ec4b98304 Mon Sep 17 00:00:00 2001
|
||||
From: Victor Hermann Chiletto <v@hnn.net.br>
|
||||
Date: Tue, 9 Jun 2020 01:36:53 -0300
|
||||
Subject: [PATCH 53/54] winegstreamer: Translate WMV3 attributes to caps
|
||||
|
||||
---
|
||||
dlls/winegstreamer/mfplat.c | 9 +++++++++
|
||||
1 file changed, 9 insertions(+)
|
||||
|
||||
diff --git a/dlls/winegstreamer/mfplat.c b/dlls/winegstreamer/mfplat.c
|
||||
index 39b98f3eba..042c02c486 100644
|
||||
--- a/dlls/winegstreamer/mfplat.c
|
||||
+++ b/dlls/winegstreamer/mfplat.c
|
||||
@@ -1319,6 +1319,15 @@ GstCaps *caps_from_mf_media_type(IMFMediaType *type)
|
||||
|
||||
user_data_to_codec_data(type, output);
|
||||
}
|
||||
+ else if (IsEqualGUID(&subtype, &MFVideoFormat_WMV3))
|
||||
+ {
|
||||
+ output = gst_caps_new_empty_simple("video/x-wmv");
|
||||
+ gst_caps_set_simple(output, "format", G_TYPE_STRING, "WMV3", NULL);
|
||||
+
|
||||
+ gst_caps_set_simple(output, "wmvversion", G_TYPE_INT, 3, NULL);
|
||||
+
|
||||
+ user_data_to_codec_data(type, output);
|
||||
+ }
|
||||
else {
|
||||
FIXME("Unrecognized subtype %s\n", debugstr_guid(&subtype));
|
||||
return NULL;
|
||||
--
|
||||
2.28.0
|
||||
|
@ -1,42 +0,0 @@
|
||||
From 8aabbee010a69fde257706cf3d178864feb1858c Mon Sep 17 00:00:00 2001
|
||||
From: Victor Hermann Chiletto <v@hnn.net.br>
|
||||
Date: Wed, 10 Jun 2020 01:10:57 -0300
|
||||
Subject: [PATCH 54/54] winegstreamer: expose NV12 as the first color space in
|
||||
IMFTransform::GetOutputAvailableType
|
||||
|
||||
---
|
||||
dlls/winegstreamer/mf_decode.c | 2 +-
|
||||
dlls/winegstreamer/mfplat.c | 2 +-
|
||||
2 files changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/dlls/winegstreamer/mf_decode.c b/dlls/winegstreamer/mf_decode.c
|
||||
index 3d314eaab4..6e41838fdc 100644
|
||||
--- a/dlls/winegstreamer/mf_decode.c
|
||||
+++ b/dlls/winegstreamer/mf_decode.c
|
||||
@@ -23,7 +23,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(mfplat);
|
||||
/* keep in sync with mfplat.c's mft registrations */
|
||||
|
||||
const GUID *h264_input_types[] = {&MFVideoFormat_H264};
|
||||
-const GUID *h264_output_types[] = {&MFVideoFormat_I420, &MFVideoFormat_IYUV, &MFVideoFormat_NV12, &MFVideoFormat_YUY2, &MFVideoFormat_YV12};
|
||||
+const GUID *h264_output_types[] = {&MFVideoFormat_NV12, &MFVideoFormat_I420, &MFVideoFormat_IYUV, &MFVideoFormat_YUY2, &MFVideoFormat_YV12};
|
||||
|
||||
const GUID *aac_input_types[] = {&MFAudioFormat_AAC};
|
||||
const GUID *aac_output_types[] = {&MFAudioFormat_Float, &MFAudioFormat_PCM};
|
||||
diff --git a/dlls/winegstreamer/mfplat.c b/dlls/winegstreamer/mfplat.c
|
||||
index 042c02c486..94e6ca534f 100644
|
||||
--- a/dlls/winegstreamer/mfplat.c
|
||||
+++ b/dlls/winegstreamer/mfplat.c
|
||||
@@ -516,9 +516,9 @@ const GUID *h264_decoder_input_types[] =
|
||||
};
|
||||
const GUID *h264_decoder_output_types[] =
|
||||
{
|
||||
+ &MFVideoFormat_NV12,
|
||||
&MFVideoFormat_I420,
|
||||
&MFVideoFormat_IYUV,
|
||||
- &MFVideoFormat_NV12,
|
||||
&MFVideoFormat_YUY2,
|
||||
&MFVideoFormat_YV12,
|
||||
};
|
||||
--
|
||||
2.28.0
|
||||
|
@ -1,2 +1 @@
|
||||
Fixes: [49692] mfplat: Improved support for multiple video formats.
|
||||
Disabled: True
|
||||
|
@ -149,6 +149,7 @@ 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"
|
||||
@ -544,6 +545,9 @@ 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"
|
||||
;;
|
||||
@ -2768,6 +2772,77 @@ 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:
|
||||
# | * 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
|
||||
fi
|
||||
|
||||
# Patchset mmsystem.dll16-MIDIHDR_Refcount
|
||||
# |
|
||||
# | This patchset fixes the following Wine bugs:
|
||||
|
Loading…
Reference in New Issue
Block a user