mirror of
https://gitlab.winehq.org/wine/wine-staging.git
synced 2025-01-28 22:04:43 -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)
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -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;
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user