Updated mfplat-streaming-support patchset

This commit is contained in:
Alistair Leslie-Hughes 2021-06-22 15:33:24 +10:00
parent 9c8608eea6
commit 9bf50b7e1f
80 changed files with 5564 additions and 6942 deletions

View File

@ -0,0 +1,90 @@
From d95656904e4d7d2c9a4006e90f123e28bbcdbb70 Mon Sep 17 00:00:00 2001
From: Derek Lesho <dlesho@codeweavers.com>
Date: Tue, 9 Mar 2021 16:53:09 -0500
Subject: [PATCH 01/39] winegstreamer: Activate source pad in push mode if it
isn't activated in pull mode.
Since our source pad is not part of any element, gstreamer won't end up activating it
directly through the state transition. Instead, if the downstream element doesn't
activate the source pad into pull mode during the transition to the READY state,
we activate our pad in push mode.
Signed-off-by: Derek Lesho <dlesho@codeweavers.com>
---
dlls/winegstreamer/wg_parser.c | 15 ++++++++++++++-
1 file changed, 14 insertions(+), 1 deletion(-)
diff --git a/dlls/winegstreamer/wg_parser.c b/dlls/winegstreamer/wg_parser.c
index 0d59297a026..00ff02ef462 100644
--- a/dlls/winegstreamer/wg_parser.c
+++ b/dlls/winegstreamer/wg_parser.c
@@ -58,7 +58,7 @@ struct wg_parser
pthread_mutex_t mutex;
pthread_cond_t init_cond;
- bool no_more_pads, has_duration, error;
+ bool no_more_pads, has_duration, error, pull_mode;
pthread_cond_t read_cond, read_done_cond;
struct
@@ -1365,9 +1365,12 @@ static gboolean src_activate_mode_cb(GstPad *pad, GstObject *parent, GstPadMode
GST_DEBUG("%s source pad for parser %p in %s mode.",
activate ? "Activating" : "Deactivating", parser, gst_pad_mode_get_name(mode));
+ parser->pull_mode = false;
+
switch (mode)
{
case GST_PAD_MODE_PULL:
+ parser->pull_mode = activate;
return TRUE;
case GST_PAD_MODE_PUSH:
return activate_push(pad, activate);
@@ -1612,6 +1615,8 @@ static void CDECL wg_parser_disconnect(struct wg_parser *parser)
pthread_mutex_unlock(&parser->mutex);
gst_element_set_state(parser->container, GST_STATE_NULL);
+ if (!parser->pull_mode)
+ gst_pad_set_active(parser->my_src, 0);
gst_pad_unlink(parser->my_src, parser->their_sink);
gst_object_unref(parser->my_src);
gst_object_unref(parser->their_sink);
@@ -1667,6 +1672,8 @@ static BOOL decodebin_parser_init_gst(struct wg_parser *parser)
}
gst_element_set_state(parser->container, GST_STATE_PAUSED);
+ if (!parser->pull_mode)
+ gst_pad_set_active(parser->my_src, 1);
ret = gst_element_get_state(parser->container, NULL, NULL, -1);
if (ret == GST_STATE_CHANGE_FAILURE)
{
@@ -1718,6 +1725,8 @@ static BOOL avi_parser_init_gst(struct wg_parser *parser)
}
gst_element_set_state(parser->container, GST_STATE_PAUSED);
+ if (!parser->pull_mode)
+ gst_pad_set_active(parser->my_src, 1);
ret = gst_element_get_state(parser->container, NULL, NULL, -1);
if (ret == GST_STATE_CHANGE_FAILURE)
{
@@ -1772,6 +1781,8 @@ static BOOL mpeg_audio_parser_init_gst(struct wg_parser *parser)
gst_pad_set_active(stream->my_sink, 1);
gst_element_set_state(parser->container, GST_STATE_PAUSED);
+ if (!parser->pull_mode)
+ gst_pad_set_active(parser->my_src, 1);
ret = gst_element_get_state(parser->container, NULL, NULL, -1);
if (ret == GST_STATE_CHANGE_FAILURE)
{
@@ -1826,6 +1837,8 @@ static BOOL wave_parser_init_gst(struct wg_parser *parser)
gst_pad_set_active(stream->my_sink, 1);
gst_element_set_state(parser->container, GST_STATE_PAUSED);
+ if (!parser->pull_mode)
+ gst_pad_set_active(parser->my_src, 1);
ret = gst_element_get_state(parser->container, NULL, NULL, -1);
if (ret == GST_STATE_CHANGE_FAILURE)
{
--
2.30.2

View File

@ -0,0 +1,60 @@
From 9ec96ab12a41323abb477922cd2401446bd95457 Mon Sep 17 00:00:00 2001
From: Derek Lesho <dlesho@codeweavers.com>
Date: Wed, 10 Mar 2021 10:43:03 -0500
Subject: [PATCH 02/39] winegstreamer: Push stream-start and segment events in
push mode.
Signed-off-by: Derek Lesho <dlesho@codeweavers.com>
---
dlls/winegstreamer/wg_parser.c | 13 +++++++++++++
1 file changed, 13 insertions(+)
diff --git a/dlls/winegstreamer/wg_parser.c b/dlls/winegstreamer/wg_parser.c
index 00ff02ef462..c83afe4e195 100644
--- a/dlls/winegstreamer/wg_parser.c
+++ b/dlls/winegstreamer/wg_parser.c
@@ -1286,6 +1286,7 @@ static void *push_data(void *arg)
{
struct wg_parser *parser = arg;
GstBuffer *buffer;
+ GstSegment *segment;
guint max_size;
GST_DEBUG("Starting push thread.");
@@ -1298,6 +1299,12 @@ static void *push_data(void *arg)
max_size = parser->stop_offset ? parser->stop_offset : parser->file_size;
+ gst_pad_push_event(parser->my_src, gst_event_new_stream_start("wg_stream"));
+
+ segment = gst_segment_new();
+ gst_segment_init(segment, GST_FORMAT_BYTES);
+ gst_pad_push_event(parser->my_src, gst_event_new_segment(segment));
+
for (;;)
{
ULONG size;
@@ -1432,6 +1439,7 @@ static gboolean src_perform_seek(struct wg_parser *parser, GstEvent *event)
GstEvent *flush_event;
GstSeekFlags flags;
gint64 cur, stop;
+ GstSegment *seg;
guint32 seqnum;
gdouble rate;
@@ -1465,7 +1473,12 @@ static gboolean src_perform_seek(struct wg_parser *parser, GstEvent *event)
gst_event_set_seqnum(flush_event, seqnum);
gst_pad_push_event(parser->my_src, flush_event);
if (thread)
+ {
gst_pad_set_active(parser->my_src, 1);
+ seg = gst_segment_new();
+ gst_segment_init(seg, GST_FORMAT_BYTES);
+ gst_pad_push_event(parser->my_src, gst_event_new_segment(seg));
+ }
}
return TRUE;
--
2.30.2

View File

@ -1,407 +0,0 @@
From: Derek Lesho <dlesho@codeweavers.com>
Subject: [PATCH resend 3/5] winegstreamer: Implement ::Process(Input/Output) for audio conversion transform.
Message-Id: <20210118193047.267366-3-dlesho@codeweavers.com>
Date: Mon, 18 Jan 2021 14:30:45 -0500
In-Reply-To: <20210118193047.267366-1-dlesho@codeweavers.com>
References: <20210118193047.267366-1-dlesho@codeweavers.com>
Signed-off-by: Derek Lesho <dlesho@codeweavers.com>
---
dlls/winegstreamer/audioconvert.c | 188 ++++++++++++++++++++++++++++--
dlls/winegstreamer/gst_private.h | 1 +
dlls/winegstreamer/mfplat.c | 69 +++++++++++
3 files changed, 250 insertions(+), 8 deletions(-)
diff --git a/dlls/winegstreamer/audioconvert.c b/dlls/winegstreamer/audioconvert.c
index 85f44dd8856..e16fc6f1a78 100644
--- a/dlls/winegstreamer/audioconvert.c
+++ b/dlls/winegstreamer/audioconvert.c
@@ -40,6 +40,8 @@ struct audio_converter
IMFMediaType *input_type;
IMFMediaType *output_type;
CRITICAL_SECTION cs;
+ BOOL inflight;
+ GstElement *container, *appsrc, *appsink;
};
static struct audio_converter *impl_audio_converter_from_IMFTransform(IMFTransform *iface)
@@ -85,6 +87,7 @@ static ULONG WINAPI audio_converter_Release(IMFTransform *iface)
{
transform->cs.DebugInfo->Spare[0] = 0;
DeleteCriticalSection(&transform->cs);
+ gst_object_unref(transform->container);
heap_free(transform);
}
@@ -295,6 +298,9 @@ static HRESULT WINAPI audio_converter_SetInputType(IMFTransform *iface, DWORD id
EnterCriticalSection(&converter->cs);
+ converter->inflight = FALSE;
+ gst_element_set_state(converter->container, GST_STATE_READY);
+
if (converter->input_type)
{
IMFMediaType_Release(converter->input_type);
@@ -326,14 +332,17 @@ static HRESULT WINAPI audio_converter_SetInputType(IMFTransform *iface, DWORD id
if (!(input_caps = caps_from_mf_media_type(type)))
return MF_E_INVALIDTYPE;
- gst_caps_unref(input_caps);
-
if (flags & MFT_SET_TYPE_TEST_ONLY)
+ {
+ gst_caps_unref(input_caps);
return S_OK;
+ }
EnterCriticalSection(&converter->cs);
hr = S_OK;
+ converter->inflight = FALSE;
+ gst_element_set_state(converter->container, GST_STATE_READY);
if (!converter->input_type)
hr = MFCreateMediaType(&converter->input_type);
@@ -341,12 +350,18 @@ static HRESULT WINAPI audio_converter_SetInputType(IMFTransform *iface, DWORD id
if (SUCCEEDED(hr))
hr = IMFMediaType_CopyAllItems(type, (IMFAttributes *) converter->input_type);
+ g_object_set(converter->appsrc, "caps", input_caps, NULL);
+ gst_caps_unref(input_caps);
+
if (FAILED(hr))
{
IMFMediaType_Release(converter->input_type);
converter->input_type = NULL;
}
+ if (converter->input_type && converter->output_type)
+ gst_element_set_state(converter->container, GST_STATE_PLAYING);
+
LeaveCriticalSection(&converter->cs);
return hr;
@@ -375,6 +390,9 @@ static HRESULT WINAPI audio_converter_SetOutputType(IMFTransform *iface, DWORD i
EnterCriticalSection(&converter->cs);
+ converter->inflight = FALSE;
+ gst_element_set_state(converter->container, GST_STATE_READY);
+
if (converter->output_type)
{
IMFMediaType_Release(converter->output_type);
@@ -406,14 +424,17 @@ static HRESULT WINAPI audio_converter_SetOutputType(IMFTransform *iface, DWORD i
if (!(output_caps = caps_from_mf_media_type(type)))
return MF_E_INVALIDTYPE;
- gst_caps_unref(output_caps);
-
if (flags & MFT_SET_TYPE_TEST_ONLY)
+ {
+ gst_caps_unref(output_caps);
return S_OK;
+ }
EnterCriticalSection(&converter->cs);
hr = S_OK;
+ converter->inflight = FALSE;
+ gst_element_set_state(converter->container, GST_STATE_READY);
if (!converter->output_type)
hr = MFCreateMediaType(&converter->output_type);
@@ -421,12 +442,18 @@ static HRESULT WINAPI audio_converter_SetOutputType(IMFTransform *iface, DWORD i
if (SUCCEEDED(hr))
hr = IMFMediaType_CopyAllItems(type, (IMFAttributes *) converter->output_type);
+ g_object_set(converter->appsink, "caps", output_caps, NULL);
+ gst_caps_unref(output_caps);
+
if (FAILED(hr))
{
IMFMediaType_Release(converter->output_type);
converter->output_type = NULL;
}
+ if (converter->input_type && converter->output_type)
+ gst_element_set_state(converter->container, GST_STATE_PLAYING);
+
LeaveCriticalSection(&converter->cs);
return hr;
@@ -538,17 +565,102 @@ static HRESULT WINAPI audio_converter_ProcessMessage(IMFTransform *iface, MFT_ME
static HRESULT WINAPI audio_converter_ProcessInput(IMFTransform *iface, DWORD id, IMFSample *sample, DWORD flags)
{
- FIXME("%p, %u, %p, %#x.\n", iface, id, sample, flags);
+ GstBuffer *gst_buffer;
+ int ret;
- return E_NOTIMPL;
+ struct audio_converter *converter = impl_audio_converter_from_IMFTransform(iface);
+
+ TRACE("%p, %u, %p, %#x.\n", iface, id, sample, flags);
+
+ if (flags)
+ WARN("Unsupported flags %#x\n", flags);
+
+ if (id != 0)
+ return MF_E_INVALIDSTREAMNUMBER;
+
+ EnterCriticalSection(&converter->cs);
+
+ if (!converter->input_type || !converter->output_type)
+ {
+ LeaveCriticalSection(&converter->cs);
+ return MF_E_TRANSFORM_TYPE_NOT_SET;
+ }
+
+ if (converter->inflight)
+ {
+ LeaveCriticalSection(&converter->cs);
+ return MF_E_NOTACCEPTING;
+ }
+
+ if (!(gst_buffer = gst_buffer_from_mf_sample(sample)))
+ {
+ LeaveCriticalSection(&converter->cs);
+ return E_FAIL;
+ }
+
+ g_signal_emit_by_name(converter->appsrc, "push-buffer", gst_buffer, &ret);
+ gst_buffer_unref(gst_buffer);
+ if (ret != GST_FLOW_OK)
+ {
+ ERR("Couldn't push buffer ret, (%s)\n", gst_flow_get_name(ret));
+ LeaveCriticalSection(&converter->cs);
+ return E_FAIL;
+ }
+
+ converter->inflight = TRUE;
+ LeaveCriticalSection(&converter->cs);
+
+ return S_OK;
}
static HRESULT WINAPI audio_converter_ProcessOutput(IMFTransform *iface, DWORD flags, DWORD count,
MFT_OUTPUT_DATA_BUFFER *samples, DWORD *status)
{
- FIXME("%p, %#x, %u, %p, %p.\n", iface, flags, count, samples, status);
+ GstSample *sample;
- return E_NOTIMPL;
+ struct audio_converter *converter = impl_audio_converter_from_IMFTransform(iface);
+
+ TRACE("%p, %#x, %u, %p, %p.\n", iface, flags, count, samples, status);
+
+ if (flags)
+ WARN("Unsupported flags %#x\n", flags);
+
+ if (!count)
+ return S_OK;
+
+ if (count != 1)
+ return MF_E_INVALIDSTREAMNUMBER;
+
+ if (samples[0].dwStreamID != 0)
+ return MF_E_INVALIDSTREAMNUMBER;
+
+ EnterCriticalSection(&converter->cs);
+
+ if (!converter->input_type || !converter->output_type)
+ {
+ LeaveCriticalSection(&converter->cs);
+ return MF_E_TRANSFORM_TYPE_NOT_SET;
+ }
+
+ if (!converter->inflight)
+ {
+ LeaveCriticalSection(&converter->cs);
+ return MF_E_TRANSFORM_NEED_MORE_INPUT;
+ }
+
+ g_signal_emit_by_name(converter->appsink, "pull-sample", &sample);
+
+ converter->inflight = FALSE;
+
+ samples[0].pSample = mf_sample_from_gst_buffer(gst_sample_get_buffer(sample));
+ gst_sample_unref(sample);
+ samples[0].dwStatus = S_OK;
+ samples[0].pEvents = NULL;
+ *status = 0;
+
+ LeaveCriticalSection(&converter->cs);
+
+ return S_OK;
}
static const IMFTransformVtbl audio_converter_vtbl =
@@ -583,6 +695,7 @@ static const IMFTransformVtbl audio_converter_vtbl =
HRESULT audio_converter_create(REFIID riid, void **ret)
{
+ GstElement *audioconvert, *resampler;
struct audio_converter *object;
TRACE("%s %p\n", debugstr_guid(riid), ret);
@@ -596,6 +709,65 @@ HRESULT audio_converter_create(REFIID riid, void **ret)
InitializeCriticalSection(&object->cs);
object->cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": audio_converter_lock");
+ object->container = gst_bin_new(NULL);
+
+ if (!(object->appsrc = gst_element_factory_make("appsrc", NULL)))
+ {
+ ERR("Failed to create appsrc, are %u-bit Gstreamer \"base\" plugins installed?\n",
+ 8 * (int)sizeof(void *));
+ IMFTransform_Release(&object->IMFTransform_iface);
+ return E_FAIL;
+ }
+ gst_bin_add(GST_BIN(object->container), object->appsrc);
+
+ if (!(audioconvert = gst_element_factory_make("audioconvert", NULL)))
+ {
+ ERR("Failed to create audioconvert, are %u-bit Gstreamer \"base\" plugins installed?\n",
+ 8 * (int)sizeof(void *));
+ IMFTransform_Release(&object->IMFTransform_iface);
+ return E_FAIL;
+ }
+ gst_bin_add(GST_BIN(object->container), audioconvert);
+
+ if (!(resampler = gst_element_factory_make("audioresample", NULL)))
+ {
+ ERR("Failed to create audioresample, are %u-bit Gstreamer \"base\" plugins installed?\n",
+ 8 * (int)sizeof(void *));
+ IMFTransform_Release(&object->IMFTransform_iface);
+ return E_FAIL;
+ }
+ gst_bin_add(GST_BIN(object->container), resampler);
+
+ if (!(object->appsink = gst_element_factory_make("appsink", NULL)))
+ {
+ ERR("Failed to create appsink, are %u-bit Gstreamer \"base\" plugins installed?\n",
+ 8 * (int)sizeof(void *));
+ IMFTransform_Release(&object->IMFTransform_iface);
+ return E_FAIL;
+ }
+ gst_bin_add(GST_BIN(object->container), object->appsink);
+
+ if (!gst_element_link(object->appsrc, audioconvert))
+ {
+ ERR("Failed to link appsrc to audioconvert\n");
+ IMFTransform_Release(&object->IMFTransform_iface);
+ return E_FAIL;
+ }
+
+ if (!gst_element_link(audioconvert, resampler))
+ {
+ ERR("Failed to link audioconvert to resampler\n");
+ IMFTransform_Release(&object->IMFTransform_iface);
+ return E_FAIL;
+ }
+
+ if (!gst_element_link(resampler, object->appsink))
+ {
+ ERR("Failed to link resampler to appsink\n");
+ IMFTransform_Release(&object->IMFTransform_iface);
+ return E_FAIL;
+ }
+
*ret = &object->IMFTransform_iface;
return S_OK;
}
diff --git a/dlls/winegstreamer/gst_private.h b/dlls/winegstreamer/gst_private.h
index 9518f721504..14b6a011ac2 100644
--- a/dlls/winegstreamer/gst_private.h
+++ b/dlls/winegstreamer/gst_private.h
@@ -82,6 +82,7 @@ HRESULT winegstreamer_stream_handler_create(REFIID riid, void **obj) DECLSPEC_HI
IMFMediaType *mf_media_type_from_caps(const GstCaps *caps) DECLSPEC_HIDDEN;
GstCaps *caps_from_mf_media_type(IMFMediaType *type) DECLSPEC_HIDDEN;
IMFSample *mf_sample_from_gst_buffer(GstBuffer *in) DECLSPEC_HIDDEN;
+GstBuffer *gst_buffer_from_mf_sample(IMFSample *in) DECLSPEC_HIDDEN;
HRESULT winegstreamer_stream_handler_create(REFIID riid, void **obj) DECLSPEC_HIDDEN;
diff --git a/dlls/winegstreamer/mfplat.c b/dlls/winegstreamer/mfplat.c
index f300988fc5c..b2b5b247dac 100644
--- a/dlls/winegstreamer/mfplat.c
+++ b/dlls/winegstreamer/mfplat.c
@@ -865,3 +865,72 @@ done:
return out;
}
+
+GstBuffer *gst_buffer_from_mf_sample(IMFSample *mf_sample)
+{
+ GstBuffer *out = gst_buffer_new();
+ IMFMediaBuffer *mf_buffer = NULL;
+ LONGLONG duration, time;
+ DWORD buffer_count;
+ unsigned int i;
+ HRESULT hr;
+
+ if (FAILED(hr = IMFSample_GetSampleDuration(mf_sample, &duration)))
+ goto fail;
+
+ if (FAILED(hr = IMFSample_GetSampleTime(mf_sample, &time)))
+ goto fail;
+
+ GST_BUFFER_DURATION(out) = duration;
+ GST_BUFFER_PTS(out) = time * 100;
+
+ if (FAILED(hr = IMFSample_GetBufferCount(mf_sample, &buffer_count)))
+ goto fail;
+
+ for (i = 0; i < buffer_count; i++)
+ {
+ DWORD buffer_size;
+ GstMapInfo map_info;
+ GstMemory *memory;
+ BYTE *buf_data;
+
+ if (FAILED(hr = IMFSample_GetBufferByIndex(mf_sample, i, &mf_buffer)))
+ goto fail;
+
+ if (FAILED(hr = IMFMediaBuffer_GetCurrentLength(mf_buffer, &buffer_size)))
+ goto fail;
+
+ memory = gst_allocator_alloc(NULL, buffer_size, NULL);
+ gst_memory_resize(memory, 0, buffer_size);
+
+ if (!gst_memory_map(memory, &map_info, GST_MAP_WRITE))
+ {
+ hr = E_FAIL;
+ goto fail;
+ }
+
+ if (FAILED(hr = IMFMediaBuffer_Lock(mf_buffer, &buf_data, NULL, NULL)))
+ goto fail;
+
+ memcpy(map_info.data, buf_data, buffer_size);
+
+ if (FAILED(hr = IMFMediaBuffer_Unlock(mf_buffer)))
+ goto fail;
+
+ gst_memory_unmap(memory, &map_info);
+
+ gst_buffer_append_memory(out, memory);
+
+ IMFMediaBuffer_Release(mf_buffer);
+ mf_buffer = NULL;
+ }
+
+ return out;
+
+fail:
+ ERR("Failed to copy IMFSample to GstBuffer, hr = %#x\n", hr);
+ if (mf_buffer)
+ IMFMediaBuffer_Release(mf_buffer);
+ gst_buffer_unref(out);
+ return NULL;
+}
--
2.30.0

View File

@ -0,0 +1,384 @@
From 95db72178f4906d02785c707a46c8298f4c008d0 Mon Sep 17 00:00:00 2001
From: Derek Lesho <dlesho@codeweavers.com>
Date: Wed, 10 Mar 2021 13:09:51 -0500
Subject: [PATCH 03/39] winegstreamer: Introduce H.264 decoder transform.
Signed-off-by: Derek Lesho <dlesho@codeweavers.com>
---
dlls/winegstreamer/Makefile.in | 1 +
dlls/winegstreamer/decode_transform.c | 301 +++++++++++++++++++
dlls/winegstreamer/gst_private.h | 2 +
dlls/winegstreamer/mfplat.c | 1 +
dlls/winegstreamer/winegstreamer_classes.idl | 6 +
include/mfidl.idl | 1 +
6 files changed, 312 insertions(+)
create mode 100644 dlls/winegstreamer/decode_transform.c
diff --git a/dlls/winegstreamer/Makefile.in b/dlls/winegstreamer/Makefile.in
index 4d5dece64b3..7459cccf7e4 100644
--- a/dlls/winegstreamer/Makefile.in
+++ b/dlls/winegstreamer/Makefile.in
@@ -8,6 +8,7 @@ EXTRADLLFLAGS = -mno-cygwin
C_SRCS = \
audioconvert.c \
+ decode_transform.c \
main.c \
media_source.c \
mfplat.c \
diff --git a/dlls/winegstreamer/decode_transform.c b/dlls/winegstreamer/decode_transform.c
new file mode 100644
index 00000000000..f5d4763bde4
--- /dev/null
+++ b/dlls/winegstreamer/decode_transform.c
@@ -0,0 +1,301 @@
+/* GStreamer Decoder Transform
+ *
+ * Copyright 2021 Derek Lesho
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include "gst_private.h"
+
+#include "mfapi.h"
+#include "mferror.h"
+#include "mfobjects.h"
+#include "mftransform.h"
+
+#include "wine/debug.h"
+#include "wine/heap.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(mfplat);
+
+struct mf_decoder
+{
+ IMFTransform IMFTransform_iface;
+ LONG refcount;
+};
+
+static struct mf_decoder *impl_mf_decoder_from_IMFTransform(IMFTransform *iface)
+{
+ return CONTAINING_RECORD(iface, struct mf_decoder, IMFTransform_iface);
+}
+
+static HRESULT WINAPI mf_decoder_QueryInterface (IMFTransform *iface, REFIID riid, void **out)
+{
+ TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), out);
+
+ if (IsEqualIID(riid, &IID_IMFTransform) ||
+ IsEqualIID(riid, &IID_IUnknown))
+ {
+ *out = iface;
+ IMFTransform_AddRef(iface);
+ return S_OK;
+ }
+
+ WARN("Unsupported %s.\n", debugstr_guid(riid));
+ *out = NULL;
+ return E_NOINTERFACE;
+}
+
+static ULONG WINAPI mf_decoder_AddRef(IMFTransform *iface)
+{
+ struct mf_decoder *decoder = impl_mf_decoder_from_IMFTransform(iface);
+ ULONG refcount = InterlockedIncrement(&decoder->refcount);
+
+ TRACE("%p, refcount %u.\n", iface, refcount);
+
+ return refcount;
+}
+
+static ULONG WINAPI mf_decoder_Release(IMFTransform *iface)
+{
+ struct mf_decoder *decoder = impl_mf_decoder_from_IMFTransform(iface);
+ ULONG refcount = InterlockedDecrement(&decoder->refcount);
+
+ TRACE("%p, refcount %u.\n", iface, refcount);
+
+ if (!refcount)
+ {
+ heap_free(decoder);
+ }
+
+ return refcount;
+}
+
+static HRESULT WINAPI mf_decoder_GetStreamLimits(IMFTransform *iface, DWORD *input_minimum, DWORD *input_maximum,
+ DWORD *output_minimum, DWORD *output_maximum)
+{
+ TRACE("%p, %p, %p, %p, %p.\n", iface, input_minimum, input_maximum, output_minimum, output_maximum);
+
+ *input_minimum = *input_maximum = *output_minimum = *output_maximum = 1;
+
+ return S_OK;
+}
+
+static HRESULT WINAPI mf_decoder_GetStreamCount(IMFTransform *iface, DWORD *inputs, DWORD *outputs)
+{
+ TRACE("%p %p %p.\n", iface, inputs, outputs);
+
+ *inputs = *outputs = 1;
+
+ return S_OK;
+}
+
+static HRESULT WINAPI mf_decoder_GetStreamIDs(IMFTransform *iface, DWORD input_size, DWORD *inputs,
+ DWORD output_size, DWORD *outputs)
+{
+ TRACE("%p %u %p %u %p.\n", iface, input_size, inputs, output_size, outputs);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI mf_decoder_GetInputStreamInfo(IMFTransform *iface, DWORD id, MFT_INPUT_STREAM_INFO *info)
+{
+ FIXME("%p %u %p.\n", iface, id, info);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI mf_decoder_GetOutputStreamInfo(IMFTransform *iface, DWORD id, MFT_OUTPUT_STREAM_INFO *info)
+{
+ FIXME("%p %u %p.\n", iface, id, info);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI mf_decoder_GetAttributes(IMFTransform *iface, IMFAttributes **attributes)
+{
+ FIXME("%p, %p.\n", iface, attributes);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI mf_decoder_GetInputStreamAttributes(IMFTransform *iface, DWORD id,
+ IMFAttributes **attributes)
+{
+ FIXME("%p, %u, %p.\n", iface, id, attributes);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI mf_decoder_GetOutputStreamAttributes(IMFTransform *iface, DWORD id,
+ IMFAttributes **attributes)
+{
+ FIXME("%p, %u, %p.\n", iface, id, attributes);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI mf_decoder_DeleteInputStream(IMFTransform *iface, DWORD id)
+{
+ TRACE("%p, %u.\n", iface, id);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI mf_decoder_AddInputStreams(IMFTransform *iface, DWORD streams, DWORD *ids)
+{
+ TRACE("%p, %u, %p.\n", iface, streams, ids);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI mf_decoder_GetInputAvailableType(IMFTransform *iface, DWORD id, DWORD index,
+ IMFMediaType **type)
+{
+ FIXME("%p, %u, %u, %p.\n", iface, id, index, type);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI mf_decoder_GetOutputAvailableType(IMFTransform *iface, DWORD id, DWORD index,
+ IMFMediaType **type)
+{
+ FIXME("%p, %u, %u, %p.\n", iface, id, index, type);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI mf_decoder_SetInputType(IMFTransform *iface, DWORD id, IMFMediaType *type, DWORD flags)
+{
+ FIXME("%p, %u, %p, %#x.\n", iface, id, type, flags);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI mf_decoder_SetOutputType(IMFTransform *iface, DWORD id, IMFMediaType *type, DWORD flags)
+{
+ FIXME("%p, %u, %p, %#x.\n", iface, id, type, flags);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI mf_decoder_GetInputCurrentType(IMFTransform *iface, DWORD id, IMFMediaType **type)
+{
+ FIXME("%p, %u, %p.\n", iface, id, type);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI mf_decoder_GetOutputCurrentType(IMFTransform *iface, DWORD id, IMFMediaType **type)
+{
+ FIXME("%p, %u, %p.\n", iface, id, type);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI mf_decoder_GetInputStatus(IMFTransform *iface, DWORD id, DWORD *flags)
+{
+ FIXME("%p, %u, %p\n", iface, id, flags);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI mf_decoder_GetOutputStatus(IMFTransform *iface, DWORD *flags)
+{
+ FIXME("%p, %p.\n", iface, flags);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI mf_decoder_SetOutputBounds(IMFTransform *iface, LONGLONG lower, LONGLONG upper)
+{
+ FIXME("%p, %s, %s.\n", iface, wine_dbgstr_longlong(lower), wine_dbgstr_longlong(upper));
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI mf_decoder_ProcessEvent(IMFTransform *iface, DWORD id, IMFMediaEvent *event)
+{
+ FIXME("%p, %u, %p.\n", iface, id, event);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI mf_decoder_ProcessMessage(IMFTransform *iface, MFT_MESSAGE_TYPE message, ULONG_PTR param)
+{
+ FIXME("%p, %u %lu.\n", iface, message, param);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI mf_decoder_ProcessInput(IMFTransform *iface, DWORD id, IMFSample *sample, DWORD flags)
+{
+ FIXME("%p, %u, %p, %#x.\n", iface, id, sample, flags);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI mf_decoder_ProcessOutput(IMFTransform *iface, DWORD flags, DWORD count,
+ MFT_OUTPUT_DATA_BUFFER *samples, DWORD *status)
+{
+ FIXME("%p, %#x, %u, %p, %p.\n", iface, flags, count, samples, status);
+
+ return E_NOTIMPL;
+}
+
+static const IMFTransformVtbl mf_decoder_vtbl =
+{
+ mf_decoder_QueryInterface,
+ mf_decoder_AddRef,
+ mf_decoder_Release,
+ mf_decoder_GetStreamLimits,
+ mf_decoder_GetStreamCount,
+ mf_decoder_GetStreamIDs,
+ mf_decoder_GetInputStreamInfo,
+ mf_decoder_GetOutputStreamInfo,
+ mf_decoder_GetAttributes,
+ mf_decoder_GetInputStreamAttributes,
+ mf_decoder_GetOutputStreamAttributes,
+ mf_decoder_DeleteInputStream,
+ mf_decoder_AddInputStreams,
+ mf_decoder_GetInputAvailableType,
+ mf_decoder_GetOutputAvailableType,
+ mf_decoder_SetInputType,
+ mf_decoder_SetOutputType,
+ mf_decoder_GetInputCurrentType,
+ mf_decoder_GetOutputCurrentType,
+ mf_decoder_GetInputStatus,
+ mf_decoder_GetOutputStatus,
+ mf_decoder_SetOutputBounds,
+ mf_decoder_ProcessEvent,
+ mf_decoder_ProcessMessage,
+ mf_decoder_ProcessInput,
+ mf_decoder_ProcessOutput,
+};
+
+HRESULT decode_transform_create(REFIID riid, void **obj)
+{
+ struct mf_decoder *object;
+
+ TRACE("%s, %p.\n", debugstr_guid(riid), obj);
+
+ if (!(object = heap_alloc_zero(sizeof(*object))))
+ return E_OUTOFMEMORY;
+
+ object->IMFTransform_iface.lpVtbl = &mf_decoder_vtbl;
+ object->refcount = 1;
+
+ *obj = &object->IMFTransform_iface;
+ return S_OK;
+}
diff --git a/dlls/winegstreamer/gst_private.h b/dlls/winegstreamer/gst_private.h
index 55a62361966..cdf90d52025 100644
--- a/dlls/winegstreamer/gst_private.h
+++ b/dlls/winegstreamer/gst_private.h
@@ -219,4 +219,6 @@ HRESULT winegstreamer_stream_handler_create(REFIID riid, void **obj) DECLSPEC_HI
HRESULT audio_converter_create(REFIID riid, void **ret) DECLSPEC_HIDDEN;
+HRESULT decode_transform_create(REFIID riid, void **obj) DECLSPEC_HIDDEN;
+
#endif /* __GST_PRIVATE_INCLUDED__ */
diff --git a/dlls/winegstreamer/mfplat.c b/dlls/winegstreamer/mfplat.c
index dfa448afcfe..de679a62023 100644
--- a/dlls/winegstreamer/mfplat.c
+++ b/dlls/winegstreamer/mfplat.c
@@ -412,6 +412,7 @@ class_objects[] =
{ &CLSID_VideoProcessorMFT, &video_processor_create },
{ &CLSID_GStreamerByteStreamHandler, &winegstreamer_stream_handler_create },
{ &CLSID_WINEAudioConverter, &audio_converter_create },
+ { &CLSID_CMSH264DecoderMFT, &decode_transform_create },
};
HRESULT mfplat_get_class_object(REFCLSID rclsid, REFIID riid, void **obj)
diff --git a/dlls/winegstreamer/winegstreamer_classes.idl b/dlls/winegstreamer/winegstreamer_classes.idl
index 072ec90eea4..064a6872c79 100644
--- a/dlls/winegstreamer/winegstreamer_classes.idl
+++ b/dlls/winegstreamer/winegstreamer_classes.idl
@@ -67,3 +67,9 @@ coclass GStreamerByteStreamHandler {}
uuid(6a170414-aad9-4693-b806-3a0c47c570d6)
]
coclass WINEAudioConverter { }
+
+[
+ threading(both),
+ uuid(62ce7e72-4c71-4d20-b15d-452831a87d9d)
+]
+coclass CMSH264DecoderMFT { }
diff --git a/include/mfidl.idl b/include/mfidl.idl
index 76e0d0dfeb4..616271861aa 100644
--- a/include/mfidl.idl
+++ b/include/mfidl.idl
@@ -1574,3 +1574,4 @@ cpp_quote("EXTERN_GUID(MF_ACTIVATE_CUSTOM_VIDEO_PRESENTER_ACTIVATE, 0xba491365,
cpp_quote("EXTERN_GUID(MF_ACTIVATE_CUSTOM_VIDEO_PRESENTER_FLAGS, 0xba491366, 0xbe50, 0x451e, 0x95, 0xab, 0x6d, 0x4a, 0xcc, 0xc7, 0xda, 0xd8);")
cpp_quote("EXTERN_GUID(CLSID_VideoProcessorMFT, 0x88753b26, 0x5b24, 0x49bd, 0xb2, 0xe7, 0xc, 0x44, 0x5c, 0x78, 0xc9, 0x82);")
+cpp_quote("EXTERN_GUID(CLSID_CMSH264DecoderMFT, 0x62ce7e72, 0x4c71, 0x4d20, 0xb1, 0x5d, 0x45, 0x28, 0x31, 0xa8, 0x7d, 0x9d);")
--
2.30.2

View File

@ -0,0 +1,157 @@
From 17dab7f1ec1e00c313fa9f9bdcd64847de83b785 Mon Sep 17 00:00:00 2001
From: Derek Lesho <dlesho@codeweavers.com>
Date: Wed, 10 Mar 2021 14:14:21 -0500
Subject: [PATCH 04/39] winegstreamer: Implement ::GetInputAvailableType for
decode transform.
Signed-off-by: Derek Lesho <dlesho@codeweavers.com>
---
dlls/winegstreamer/decode_transform.c | 60 +++++++++++++++++++++++++--
dlls/winegstreamer/gst_private.h | 6 ++-
dlls/winegstreamer/mfplat.c | 7 +++-
3 files changed, 67 insertions(+), 6 deletions(-)
diff --git a/dlls/winegstreamer/decode_transform.c b/dlls/winegstreamer/decode_transform.c
index f5d4763bde4..55a0c1c6c9b 100644
--- a/dlls/winegstreamer/decode_transform.c
+++ b/dlls/winegstreamer/decode_transform.c
@@ -29,10 +29,33 @@
WINE_DEFAULT_DEBUG_CHANNEL(mfplat);
+const GUID *h264_input_types[] = {&MFVideoFormat_H264};
+/* NV12 comes first https://docs.microsoft.com/en-us/windows/win32/medfound/mft-decoder-expose-output-types-in-native-order . thanks to @vitorhnn */
+const GUID *h264_output_types[] = {&MFVideoFormat_NV12, &MFVideoFormat_I420, &MFVideoFormat_IYUV, &MFVideoFormat_YUY2, &MFVideoFormat_YV12};
+
+static struct decoder_desc
+{
+ const GUID *major_type;
+ const GUID **input_types;
+ unsigned int input_types_count;
+ const GUID **output_types;
+ unsigned int output_types_count;
+} decoder_descs[] =
+{
+ { /* DECODER_TYPE_H264 */
+ &MFMediaType_Video,
+ h264_input_types,
+ ARRAY_SIZE(h264_input_types),
+ h264_output_types,
+ ARRAY_SIZE(h264_output_types),
+ },
+};
+
struct mf_decoder
{
IMFTransform IMFTransform_iface;
LONG refcount;
+ enum decoder_type type;
};
static struct mf_decoder *impl_mf_decoder_from_IMFTransform(IMFTransform *iface)
@@ -163,9 +186,36 @@ static HRESULT WINAPI mf_decoder_AddInputStreams(IMFTransform *iface, DWORD stre
static HRESULT WINAPI mf_decoder_GetInputAvailableType(IMFTransform *iface, DWORD id, DWORD index,
IMFMediaType **type)
{
- FIXME("%p, %u, %u, %p.\n", iface, id, index, type);
+ struct mf_decoder *decoder = impl_mf_decoder_from_IMFTransform(iface);
+ IMFMediaType *input_type;
+ HRESULT hr;
- return E_NOTIMPL;
+ TRACE("%p, %u, %u, %p\n", decoder, id, index, type);
+
+ if (id != 0)
+ return MF_E_INVALIDSTREAMNUMBER;
+
+ if (index >= decoder_descs[decoder->type].input_types_count)
+ return MF_E_NO_MORE_TYPES;
+
+ if (FAILED(hr = MFCreateMediaType(&input_type)))
+ return hr;
+
+ if (FAILED(hr = IMFMediaType_SetGUID(input_type, &MF_MT_MAJOR_TYPE, decoder_descs[decoder->type].major_type)))
+ {
+ IMFMediaType_Release(input_type);
+ return hr;
+ }
+
+ if (FAILED(hr = IMFMediaType_SetGUID(input_type, &MF_MT_SUBTYPE, decoder_descs[decoder->type].input_types[index])))
+ {
+ IMFMediaType_Release(input_type);
+ return hr;
+ }
+
+ *type = input_type;
+
+ return S_OK;
}
static HRESULT WINAPI mf_decoder_GetOutputAvailableType(IMFTransform *iface, DWORD id, DWORD index,
@@ -284,11 +334,11 @@ static const IMFTransformVtbl mf_decoder_vtbl =
mf_decoder_ProcessOutput,
};
-HRESULT decode_transform_create(REFIID riid, void **obj)
+HRESULT decode_transform_create(REFIID riid, void **obj, enum decoder_type type)
{
struct mf_decoder *object;
- TRACE("%s, %p.\n", debugstr_guid(riid), obj);
+ TRACE("%s, %p %u.\n", debugstr_guid(riid), obj, type);
if (!(object = heap_alloc_zero(sizeof(*object))))
return E_OUTOFMEMORY;
@@ -296,6 +346,8 @@ HRESULT decode_transform_create(REFIID riid, void **obj)
object->IMFTransform_iface.lpVtbl = &mf_decoder_vtbl;
object->refcount = 1;
+ object->type = type;
+
*obj = &object->IMFTransform_iface;
return S_OK;
}
diff --git a/dlls/winegstreamer/gst_private.h b/dlls/winegstreamer/gst_private.h
index cdf90d52025..2d2ebbda61f 100644
--- a/dlls/winegstreamer/gst_private.h
+++ b/dlls/winegstreamer/gst_private.h
@@ -219,6 +219,10 @@ HRESULT winegstreamer_stream_handler_create(REFIID riid, void **obj) DECLSPEC_HI
HRESULT audio_converter_create(REFIID riid, void **ret) DECLSPEC_HIDDEN;
-HRESULT decode_transform_create(REFIID riid, void **obj) DECLSPEC_HIDDEN;
+enum decoder_type
+{
+ DECODER_TYPE_H264,
+};
+HRESULT decode_transform_create(REFIID riid, void **obj, enum decoder_type) DECLSPEC_HIDDEN;
#endif /* __GST_PRIVATE_INCLUDED__ */
diff --git a/dlls/winegstreamer/mfplat.c b/dlls/winegstreamer/mfplat.c
index de679a62023..40bb7969fc3 100644
--- a/dlls/winegstreamer/mfplat.c
+++ b/dlls/winegstreamer/mfplat.c
@@ -402,6 +402,11 @@ static const GUID CLSID_GStreamerByteStreamHandler = {0x317df618, 0x5e5a, 0x468a
static const GUID CLSID_WINEAudioConverter = {0x6a170414,0xaad9,0x4693,{0xb8,0x06,0x3a,0x0c,0x47,0xc5,0x70,0xd6}};
+static HRESULT h264_decoder_create(REFIID riid, void **ret)
+{
+ return decode_transform_create(riid, ret, DECODER_TYPE_H264);
+}
+
static const struct class_object
{
const GUID *clsid;
@@ -412,7 +417,7 @@ class_objects[] =
{ &CLSID_VideoProcessorMFT, &video_processor_create },
{ &CLSID_GStreamerByteStreamHandler, &winegstreamer_stream_handler_create },
{ &CLSID_WINEAudioConverter, &audio_converter_create },
- { &CLSID_CMSH264DecoderMFT, &decode_transform_create },
+ { &CLSID_CMSH264DecoderMFT, &h264_decoder_create },
};
HRESULT mfplat_get_class_object(REFCLSID rclsid, REFIID riid, void **obj)
--
2.30.2

View File

@ -0,0 +1,57 @@
From 5842d8b762b85ff36de01d672e81d3e6eab9c554 Mon Sep 17 00:00:00 2001
From: Derek Lesho <dlesho@codeweavers.com>
Date: Wed, 10 Mar 2021 14:23:09 -0500
Subject: [PATCH 05/39] winegstreamer: Implement ::GetOutputAvailableType for
decode transform.
Signed-off-by: Derek Lesho <dlesho@codeweavers.com>
---
dlls/winegstreamer/decode_transform.c | 31 +++++++++++++++++++++++++--
1 file changed, 29 insertions(+), 2 deletions(-)
diff --git a/dlls/winegstreamer/decode_transform.c b/dlls/winegstreamer/decode_transform.c
index 55a0c1c6c9b..3c71fddd67c 100644
--- a/dlls/winegstreamer/decode_transform.c
+++ b/dlls/winegstreamer/decode_transform.c
@@ -221,9 +221,36 @@ static HRESULT WINAPI mf_decoder_GetInputAvailableType(IMFTransform *iface, DWOR
static HRESULT WINAPI mf_decoder_GetOutputAvailableType(IMFTransform *iface, DWORD id, DWORD index,
IMFMediaType **type)
{
- FIXME("%p, %u, %u, %p.\n", iface, id, index, type);
+ struct mf_decoder *decoder = impl_mf_decoder_from_IMFTransform(iface);
+ IMFMediaType *output_type;
+ HRESULT hr;
- return E_NOTIMPL;
+ TRACE("%p, %u, %u, %p\n", decoder, id, index, type);
+
+ if (id != 0)
+ return MF_E_INVALIDSTREAMNUMBER;
+
+ if (index >= decoder_descs[decoder->type].output_types_count)
+ return MF_E_NO_MORE_TYPES;
+
+ if (FAILED(hr = MFCreateMediaType(&output_type)))
+ return hr;
+
+ if (FAILED(hr = IMFMediaType_SetGUID(output_type, &MF_MT_MAJOR_TYPE, decoder_descs[decoder->type].major_type)))
+ {
+ IMFMediaType_Release(output_type);
+ return hr;
+ }
+
+ if (FAILED(hr = IMFMediaType_SetGUID(output_type, &MF_MT_SUBTYPE, decoder_descs[decoder->type].output_types[index])))
+ {
+ IMFMediaType_Release(output_type);
+ return hr;
+ }
+
+ *type = output_type;
+
+ return S_OK;
}
static HRESULT WINAPI mf_decoder_SetInputType(IMFTransform *iface, DWORD id, IMFMediaType *type, DWORD flags)
--
2.30.2

View File

@ -0,0 +1,305 @@
From 6d41356d8849c741c93e6eaab81784a8be515aa5 Mon Sep 17 00:00:00 2001
From: Derek Lesho <dlesho@codeweavers.com>
Date: Thu, 11 Mar 2021 12:33:02 -0500
Subject: [PATCH 06/39] winegstreamer: Implement ::SetInputType for decode
transform.
Signed-off-by: Derek Lesho <dlesho@codeweavers.com>
---
dlls/winegstreamer/decode_transform.c | 80 ++++++++++++++++++++++++++-
dlls/winegstreamer/gst_private.h | 10 ++++
dlls/winegstreamer/mfplat.c | 17 +++++-
dlls/winegstreamer/quartz_parser.c | 1 +
dlls/winegstreamer/wg_parser.c | 76 +++++++++++++++++++++++++
5 files changed, 180 insertions(+), 4 deletions(-)
diff --git a/dlls/winegstreamer/decode_transform.c b/dlls/winegstreamer/decode_transform.c
index 3c71fddd67c..f709ef32fc1 100644
--- a/dlls/winegstreamer/decode_transform.c
+++ b/dlls/winegstreamer/decode_transform.c
@@ -56,6 +56,8 @@ struct mf_decoder
IMFTransform IMFTransform_iface;
LONG refcount;
enum decoder_type type;
+ IMFMediaType *input_type;
+ CRITICAL_SECTION cs;
};
static struct mf_decoder *impl_mf_decoder_from_IMFTransform(IMFTransform *iface)
@@ -99,6 +101,14 @@ static ULONG WINAPI mf_decoder_Release(IMFTransform *iface)
if (!refcount)
{
+ if (decoder->input_type)
+ {
+ IMFMediaType_Release(decoder->input_type);
+ decoder->input_type = NULL;
+ }
+
+ DeleteCriticalSection(&decoder->cs);
+
heap_free(decoder);
}
@@ -255,9 +265,73 @@ static HRESULT WINAPI mf_decoder_GetOutputAvailableType(IMFTransform *iface, DWO
static HRESULT WINAPI mf_decoder_SetInputType(IMFTransform *iface, DWORD id, IMFMediaType *type, DWORD flags)
{
- FIXME("%p, %u, %p, %#x.\n", iface, id, type, flags);
+ struct mf_decoder *decoder = impl_mf_decoder_from_IMFTransform(iface);
+ struct wg_format input_format;
+ GUID major_type, subtype;
+ unsigned int i;
+ HRESULT hr;
- return E_NOTIMPL;
+ TRACE("%p, %u, %p, %#x.\n", decoder, id, type, flags);
+
+ if (id != 0)
+ return MF_E_INVALIDSTREAMNUMBER;
+
+ if (!type)
+ {
+ if (flags & MFT_SET_TYPE_TEST_ONLY)
+ return S_OK;
+
+ EnterCriticalSection(&decoder->cs);
+
+ if (decoder->input_type)
+ {
+ IMFMediaType_Release(decoder->input_type);
+ decoder->input_type = NULL;
+ }
+
+ LeaveCriticalSection(&decoder->cs);
+
+ return S_OK;
+ }
+
+ if (FAILED(IMFMediaType_GetGUID(type, &MF_MT_MAJOR_TYPE, &major_type)))
+ return MF_E_INVALIDTYPE;
+ if (FAILED(IMFMediaType_GetGUID(type, &MF_MT_SUBTYPE, &subtype)))
+ return MF_E_INVALIDTYPE;
+
+ if (!(IsEqualGUID(&major_type, decoder_descs[decoder->type].major_type)))
+ return MF_E_INVALIDTYPE;
+
+ for (i = 0; i < decoder_descs[decoder->type].input_types_count; i++)
+ {
+ if (IsEqualGUID(&subtype, decoder_descs[decoder->type].input_types[i]))
+ break;
+ if (i == decoder_descs[decoder->type].input_types_count)
+ return MF_E_INVALIDTYPE;
+ }
+
+ mf_media_type_to_wg_format(type, &input_format);
+ if (!input_format.major_type)
+ return MF_E_INVALIDTYPE;
+
+ if (flags & MFT_SET_TYPE_TEST_ONLY)
+ return S_OK;
+
+ EnterCriticalSection(&decoder->cs);
+
+ hr = S_OK;
+
+ if (!decoder->input_type)
+ hr = MFCreateMediaType(&decoder->input_type);
+
+ if (SUCCEEDED(hr) && FAILED(hr = IMFMediaType_CopyAllItems(type, (IMFAttributes*) decoder->input_type)))
+ {
+ IMFMediaType_Release(decoder->input_type);
+ decoder->input_type = NULL;
+ }
+
+ LeaveCriticalSection(&decoder->cs);
+ return hr;
}
static HRESULT WINAPI mf_decoder_SetOutputType(IMFTransform *iface, DWORD id, IMFMediaType *type, DWORD flags)
@@ -375,6 +449,8 @@ HRESULT decode_transform_create(REFIID riid, void **obj, enum decoder_type type)
object->type = type;
+ InitializeCriticalSection(&object->cs);
+
*obj = &object->IMFTransform_iface;
return S_OK;
}
diff --git a/dlls/winegstreamer/gst_private.h b/dlls/winegstreamer/gst_private.h
index 2d2ebbda61f..215cf4577d4 100644
--- a/dlls/winegstreamer/gst_private.h
+++ b/dlls/winegstreamer/gst_private.h
@@ -97,9 +97,19 @@ struct wg_format
WG_VIDEO_FORMAT_YVYU,
WG_VIDEO_FORMAT_CINEPAK,
+
+ WG_VIDEO_FORMAT_H264,
} format;
uint32_t width, height;
uint32_t fps_n, fps_d;
+ union
+ {
+ struct
+ {
+ uint32_t profile;
+ uint32_t level;
+ } h264;
+ } compressed;
} video;
struct
{
diff --git a/dlls/winegstreamer/mfplat.c b/dlls/winegstreamer/mfplat.c
index 40bb7969fc3..9a599358c61 100644
--- a/dlls/winegstreamer/mfplat.c
+++ b/dlls/winegstreamer/mfplat.c
@@ -533,6 +533,7 @@ video_formats[] =
{&MFVideoFormat_YUY2, WG_VIDEO_FORMAT_YUY2},
{&MFVideoFormat_YV12, WG_VIDEO_FORMAT_YV12},
{&MFVideoFormat_YVYU, WG_VIDEO_FORMAT_YVYU},
+ {&MFVideoFormat_H264, WG_VIDEO_FORMAT_H264},
};
static const struct
@@ -718,10 +719,22 @@ static void mf_media_type_to_wg_format_video(IMFMediaType *type, struct wg_forma
if (IsEqualGUID(&subtype, video_formats[i].subtype))
{
format->u.video.format = video_formats[i].format;
- return;
+ break;
}
}
- FIXME("Unrecognized video subtype %s.\n", debugstr_guid(&subtype));
+ if (i == ARRAY_SIZE(video_formats))
+ FIXME("Unrecognized video subtype %s.\n", debugstr_guid(&subtype));
+
+ if (format->u.video.format == WG_VIDEO_FORMAT_H264)
+ {
+ UINT32 profile, level;
+
+ if (SUCCEEDED(IMFMediaType_GetUINT32(type, &MF_MT_MPEG2_PROFILE, &profile)))
+ format->u.video.compressed.h264.profile = profile;
+
+ if (SUCCEEDED(IMFMediaType_GetUINT32(type, &MF_MT_MPEG2_LEVEL, &level)))
+ format->u.video.compressed.h264.level = level;
+ }
}
void mf_media_type_to_wg_format(IMFMediaType *type, struct wg_format *format)
diff --git a/dlls/winegstreamer/quartz_parser.c b/dlls/winegstreamer/quartz_parser.c
index 5f9535659b4..4eceeae0757 100644
--- a/dlls/winegstreamer/quartz_parser.c
+++ b/dlls/winegstreamer/quartz_parser.c
@@ -268,6 +268,7 @@ static unsigned int get_image_size(const struct wg_format *format)
return width * height * 3;
case WG_VIDEO_FORMAT_UNKNOWN:
+ case WG_VIDEO_FORMAT_H264:
break;
}
diff --git a/dlls/winegstreamer/wg_parser.c b/dlls/winegstreamer/wg_parser.c
index c83afe4e195..e9689c01085 100644
--- a/dlls/winegstreamer/wg_parser.c
+++ b/dlls/winegstreamer/wg_parser.c
@@ -384,6 +384,22 @@ static void wg_channel_mask_to_gst(GstAudioChannelPosition *positions, uint32_t
}
}
+static void wg_set_caps_from_wg_format(GstCaps *caps, const struct wg_format *format)
+{
+ switch (format->major_type)
+ {
+ case WG_MAJOR_TYPE_VIDEO:
+ {
+ gst_caps_set_simple(caps, "width", G_TYPE_INT, format->u.video.width, NULL);
+ gst_caps_set_simple(caps, "height", G_TYPE_INT, format->u.video.height, NULL);
+ gst_caps_set_simple(caps, "framerate", GST_TYPE_FRACTION, format->u.video.fps_n, format->u.video.fps_d, NULL);
+ break;
+ }
+ default:
+ break;
+ }
+}
+
static GstCaps *wg_format_to_caps_audio(const struct wg_format *format)
{
GstAudioChannelPosition positions[32];
@@ -425,6 +441,65 @@ static GstCaps *wg_format_to_caps_video(const struct wg_format *format)
unsigned int i;
GstCaps *caps;
+ /* compressed types */
+
+ if (format->u.video.format == WG_VIDEO_FORMAT_H264)
+ {
+ const char *profile;
+ const char *level;
+
+ caps = gst_caps_new_empty_simple("video/x-h264");
+ wg_set_caps_from_wg_format(caps, format);
+
+ gst_caps_set_simple(caps, "stream-format", G_TYPE_STRING, "byte-stream", NULL);
+ gst_caps_set_simple(caps, "alignment", G_TYPE_STRING, "au", NULL);
+
+ switch (format->u.video.compressed.h264.profile)
+ {
+ case /* eAVEncH264VProfile_Main */ 77: profile = "main"; break;
+ case /* eAVEncH264VProfile_High */ 100: profile = "high"; break;
+ case /* eAVEncH264VProfile_444 */ 244: profile = "high-4:4:4"; break;
+ default:
+ ERR("Unrecognized H.264 profile attribute %u\n", format->u.video.compressed.h264.profile);
+ /* fallthrough */
+ case 0: profile = NULL;
+ }
+
+ switch (format->u.video.compressed.h264.level)
+ {
+ case /* eAVEncH264VLevel1 */ 10: level = "1"; break;
+ case /* eAVEncH264VLevel1_1 */ 11: level = "1.1"; break;
+ case /* eAVEncH264VLevel1_2 */ 12: level = "1.2"; break;
+ case /* eAVEncH264VLevel1_3 */ 13: level = "1.3"; break;
+ case /* eAVEncH264VLevel2 */ 20: level = "2"; break;
+ case /* eAVEncH264VLevel2_1 */ 21: level = "2.1"; break;
+ case /* eAVEncH264VLevel2_2 */ 22: level = "2.2"; break;
+ case /* eAVEncH264VLevel3 */ 30: level = "3"; break;
+ case /* eAVEncH264VLevel3_1 */ 31: level = "3.1"; break;
+ case /* eAVEncH264VLevel3_2 */ 32: level = "3.2"; break;
+ case /* eAVEncH264VLevel4 */ 40: level = "4"; break;
+ case /* eAVEncH264VLevel4_1 */ 41: level = "4.1"; break;
+ case /* eAVEncH264VLevel4_2 */ 42: level = "4.2"; break;
+ case /* eAVEncH264VLevel5 */ 50: level = "5"; break;
+ case /* eAVEncH264VLevel5_1 */ 51: level = "5.1"; break;
+ case /* eAVEncH264VLevel5_2 */ 52: level = "5.2"; break;
+ default:
+ ERR("Unrecognized H.264 level attribute %u\n", format->u.video.compressed.h264.level);
+ /* fallthrough */
+ case 0: level = NULL;
+ }
+
+ if (profile)
+ gst_caps_set_simple(caps, "profile", G_TYPE_STRING, profile, NULL);
+
+ if (level)
+ gst_caps_set_simple(caps, "level", G_TYPE_STRING, level, NULL);
+
+ return caps;
+ }
+
+ /* uncompressed types */
+
if ((video_format = wg_video_format_to_gst(format->u.video.format)) == GST_VIDEO_FORMAT_UNKNOWN)
return NULL;
@@ -584,6 +659,7 @@ static void CDECL wg_parser_stream_enable(struct wg_parser_stream *stream, const
case WG_VIDEO_FORMAT_YVYU:
case WG_VIDEO_FORMAT_UNKNOWN:
case WG_VIDEO_FORMAT_CINEPAK:
+ case WG_VIDEO_FORMAT_H264:
gst_util_set_object_arg(G_OBJECT(stream->flip), "method", "none");
break;
}
--
2.30.2

View File

@ -0,0 +1,116 @@
From 8a60a8ea1f93394afae504330ad623e4e85170d6 Mon Sep 17 00:00:00 2001
From: Derek Lesho <dlesho@codeweavers.com>
Date: Thu, 11 Mar 2021 12:58:32 -0500
Subject: [PATCH 07/39] winegstreamer: Implement ::SetOutputType for decode
transform.
Signed-off-by: Derek Lesho <dlesho@codeweavers.com>
---
dlls/winegstreamer/decode_transform.c | 76 +++++++++++++++++++++++++--
1 file changed, 73 insertions(+), 3 deletions(-)
diff --git a/dlls/winegstreamer/decode_transform.c b/dlls/winegstreamer/decode_transform.c
index f709ef32fc1..0848cb47c9d 100644
--- a/dlls/winegstreamer/decode_transform.c
+++ b/dlls/winegstreamer/decode_transform.c
@@ -56,7 +56,7 @@ struct mf_decoder
IMFTransform IMFTransform_iface;
LONG refcount;
enum decoder_type type;
- IMFMediaType *input_type;
+ IMFMediaType *input_type, *output_type;
CRITICAL_SECTION cs;
};
@@ -107,6 +107,12 @@ static ULONG WINAPI mf_decoder_Release(IMFTransform *iface)
decoder->input_type = NULL;
}
+ if (decoder->output_type)
+ {
+ IMFMediaType_Release(decoder->output_type);
+ decoder->output_type = NULL;
+ }
+
DeleteCriticalSection(&decoder->cs);
heap_free(decoder);
@@ -336,9 +342,73 @@ static HRESULT WINAPI mf_decoder_SetInputType(IMFTransform *iface, DWORD id, IMF
static HRESULT WINAPI mf_decoder_SetOutputType(IMFTransform *iface, DWORD id, IMFMediaType *type, DWORD flags)
{
- FIXME("%p, %u, %p, %#x.\n", iface, id, type, flags);
+ struct mf_decoder *decoder = impl_mf_decoder_from_IMFTransform(iface);
+ struct wg_format output_format;
+ GUID major_type, subtype;
+ HRESULT hr;
+ unsigned int i;
- return E_NOTIMPL;
+ TRACE("%p, %u, %p, %#x.\n", decoder, id, type, flags);
+
+ if (id != 0)
+ return MF_E_INVALIDSTREAMNUMBER;
+
+ if (!type)
+ {
+ if (flags & MFT_SET_TYPE_TEST_ONLY)
+ return S_OK;
+
+ EnterCriticalSection(&decoder->cs);
+
+ if (decoder->output_type)
+ {
+ IMFMediaType_Release(decoder->output_type);
+ decoder->output_type = NULL;
+ }
+
+ LeaveCriticalSection(&decoder->cs);
+
+ return S_OK;
+ }
+
+ if (FAILED(IMFMediaType_GetGUID(type, &MF_MT_MAJOR_TYPE, &major_type)))
+ return MF_E_INVALIDTYPE;
+ if (FAILED(IMFMediaType_GetGUID(type, &MF_MT_SUBTYPE, &subtype)))
+ return MF_E_INVALIDTYPE;
+
+ if (!(IsEqualGUID(&major_type, decoder_descs[decoder->type].major_type)))
+ return MF_E_INVALIDTYPE;
+
+ for (i = 0; i < decoder_descs[decoder->type].output_types_count; i++)
+ {
+ if (IsEqualGUID(&subtype, decoder_descs[decoder->type].output_types[i]))
+ break;
+ if (i == decoder_descs[decoder->type].output_types_count)
+ return MF_E_INVALIDTYPE;
+ }
+
+ mf_media_type_to_wg_format(type, &output_format);
+ if (!output_format.major_type)
+ return MF_E_INVALIDTYPE;
+
+ if (flags & MFT_SET_TYPE_TEST_ONLY)
+ return S_OK;
+
+ EnterCriticalSection(&decoder->cs);
+
+ hr = S_OK;
+
+ if (!decoder->output_type)
+ hr = MFCreateMediaType(&decoder->output_type);
+
+ if (SUCCEEDED(hr) && FAILED(hr = IMFMediaType_CopyAllItems(type, (IMFAttributes*) decoder->output_type)))
+ {
+ IMFMediaType_Release(decoder->output_type);
+ decoder->output_type = NULL;
+ }
+
+ LeaveCriticalSection(&decoder->cs);
+ return hr;
}
static HRESULT WINAPI mf_decoder_GetInputCurrentType(IMFTransform *iface, DWORD id, IMFMediaType **type)
--
2.30.2

View File

@ -0,0 +1,106 @@
From 7bb5efd92e23dfb1f734119000ec4866392f8d7c Mon Sep 17 00:00:00 2001
From: Derek Lesho <dlesho@codeweavers.com>
Date: Thu, 11 Mar 2021 14:40:32 -0500
Subject: [PATCH 08/39] winegstreamer: Implement ::Get(Input/Output)StreamInfo
for decode transform.
Signed-off-by: Derek Lesho <dlesho@codeweavers.com>
---
dlls/winegstreamer/decode_transform.c | 61 +++++++++++++++++++++++++--
1 file changed, 57 insertions(+), 4 deletions(-)
diff --git a/dlls/winegstreamer/decode_transform.c b/dlls/winegstreamer/decode_transform.c
index 0848cb47c9d..dadd161bcc9 100644
--- a/dlls/winegstreamer/decode_transform.c
+++ b/dlls/winegstreamer/decode_transform.c
@@ -58,6 +58,7 @@ struct mf_decoder
enum decoder_type type;
IMFMediaType *input_type, *output_type;
CRITICAL_SECTION cs;
+ BOOL video;
};
static struct mf_decoder *impl_mf_decoder_from_IMFTransform(IMFTransform *iface)
@@ -150,16 +151,67 @@ static HRESULT WINAPI mf_decoder_GetStreamIDs(IMFTransform *iface, DWORD input_s
static HRESULT WINAPI mf_decoder_GetInputStreamInfo(IMFTransform *iface, DWORD id, MFT_INPUT_STREAM_INFO *info)
{
- FIXME("%p %u %p.\n", iface, id, info);
+ struct mf_decoder *decoder = impl_mf_decoder_from_IMFTransform(iface);
- return E_NOTIMPL;
+ TRACE("%p %u %p\n", decoder, id, info);
+
+ if (id != 0)
+ return MF_E_INVALIDSTREAMNUMBER;
+
+ info->dwFlags = MFT_INPUT_STREAM_WHOLE_SAMPLES | MFT_INPUT_STREAM_DOES_NOT_ADDREF;
+ info->cbAlignment = 0;
+ info->cbSize = 0;
+ /* TODO: retrieve following fields from gstreamer */
+ info->hnsMaxLatency = 0;
+ info->cbMaxLookahead = 0;
+ return S_OK;
}
static HRESULT WINAPI mf_decoder_GetOutputStreamInfo(IMFTransform *iface, DWORD id, MFT_OUTPUT_STREAM_INFO *info)
{
- FIXME("%p %u %p.\n", iface, id, info);
+ struct mf_decoder *decoder = impl_mf_decoder_from_IMFTransform(iface);
+ MFT_OUTPUT_STREAM_INFO stream_info = {};
+ GUID output_subtype;
+ UINT64 framesize;
- return E_NOTIMPL;
+ TRACE("%p %u %p\n", decoder, id, info);
+
+ if (id != 0)
+ return MF_E_INVALIDSTREAMNUMBER;
+
+ EnterCriticalSection(&decoder->cs);
+
+ if (!decoder->output_type)
+ {
+ LeaveCriticalSection(&decoder->cs);
+ return MF_E_TRANSFORM_TYPE_NOT_SET;
+ }
+
+ if (decoder->video)
+ {
+ stream_info.dwFlags = MFT_OUTPUT_STREAM_WHOLE_SAMPLES | MFT_OUTPUT_STREAM_SINGLE_SAMPLE_PER_BUFFER |
+ MFT_OUTPUT_STREAM_FIXED_SAMPLE_SIZE | MFT_OUTPUT_STREAM_CAN_PROVIDE_SAMPLES;
+ stream_info.cbSize = 0;
+ if (SUCCEEDED(IMFMediaType_GetGUID(decoder->output_type, &MF_MT_SUBTYPE, &output_subtype)) &&
+ SUCCEEDED(IMFMediaType_GetUINT64(decoder->output_type, &MF_MT_FRAME_SIZE, &framesize)))
+ {
+ MFCalculateImageSize(&output_subtype, framesize >> 32, (UINT32) framesize, &stream_info.cbSize);
+ }
+ if (!stream_info.cbSize)
+ ERR("Failed to get desired output buffer size\n");
+ }
+ else
+ {
+ stream_info.dwFlags = MFT_OUTPUT_STREAM_FIXED_SAMPLE_SIZE | MFT_OUTPUT_STREAM_CAN_PROVIDE_SAMPLES;
+ stream_info.cbSize = 4;
+ }
+ stream_info.cbAlignment = 0;
+
+ LeaveCriticalSection(&decoder->cs);
+
+ *info = stream_info;
+
+ return S_OK;
}
static HRESULT WINAPI mf_decoder_GetAttributes(IMFTransform *iface, IMFAttributes **attributes)
@@ -518,6 +570,7 @@ HRESULT decode_transform_create(REFIID riid, void **obj, enum decoder_type type)
object->refcount = 1;
object->type = type;
+ object->video = decoder_descs[type].major_type == &MFMediaType_Video;
InitializeCriticalSection(&object->cs);
--
2.30.2

View File

@ -1,77 +0,0 @@
From 64cfb2a80d7ebc22b12d8b6c1e41cf7a74e15d88 Mon Sep 17 00:00:00 2001
From: Derek Lesho <dlesho@codeweavers.com>
Date: Thu, 3 Dec 2020 14:45:32 -0500
Subject: [PATCH] winegstreamer: Implement ::GetOutputAvailableType for color
conversion transform.
Signed-off-by: Derek Lesho <dlesho@codeweavers.com>
---
dlls/winegstreamer/colorconvert.c | 48 +++++++++++++++++++++++++++++--
1 file changed, 46 insertions(+), 2 deletions(-)
diff --git a/dlls/winegstreamer/colorconvert.c b/dlls/winegstreamer/colorconvert.c
index 5dd48188147..b80232e195b 100644
--- a/dlls/winegstreamer/colorconvert.c
+++ b/dlls/winegstreamer/colorconvert.c
@@ -217,12 +217,56 @@ static HRESULT WINAPI color_converter_GetInputAvailableType(IMFTransform *iface,
return S_OK;
}
+static void copy_attr(IMFMediaType *target, IMFMediaType *source, const GUID *key)
+{
+ PROPVARIANT val;
+
+ if (SUCCEEDED(IMFAttributes_GetItem((IMFAttributes *)source, key, &val)))
+ {
+ IMFAttributes_SetItem((IMFAttributes* )target, key, &val);
+ }
+}
+
static HRESULT WINAPI color_converter_GetOutputAvailableType(IMFTransform *iface, DWORD id, DWORD index,
IMFMediaType **type)
{
- FIXME("%p, %u, %u, %p.\n", iface, id, index, type);
+ IMFMediaType *output_type;
+ HRESULT hr;
- return E_NOTIMPL;
+ struct color_converter *converter = impl_color_converter_from_IMFTransform(iface);
+
+ TRACE("%p, %u, %u, %p.\n", iface, id, index, type);
+
+ if (id != 0)
+ return MF_E_INVALIDSTREAMNUMBER;
+
+ if (index >= ARRAY_SIZE(raw_types))
+ return MF_E_NO_MORE_TYPES;
+
+ if (FAILED(hr = MFCreateMediaType(&output_type)))
+ return hr;
+
+ EnterCriticalSection(&converter->cs);
+
+ if (!(converter->input_type))
+ {
+ LeaveCriticalSection(&converter->cs);
+ return MF_E_TRANSFORM_TYPE_NOT_SET;
+ }
+
+ IMFMediaType_CopyAllItems(converter->input_type, (IMFAttributes *)output_type);
+
+ LeaveCriticalSection(&converter->cs);
+
+ if (FAILED(hr = IMFMediaType_SetGUID(output_type, &MF_MT_SUBTYPE, raw_types[index])))
+ {
+ IMFMediaType_Release(output_type);
+ return hr;
+ }
+
+ *type = output_type;
+
+ return S_OK;
}
static HRESULT WINAPI color_converter_SetInputType(IMFTransform *iface, DWORD id, IMFMediaType *type, DWORD flags)
--
2.29.2

View File

@ -0,0 +1,122 @@
From 6da483d3feca1cd83a5fecdd5671fa8a0d10a2f8 Mon Sep 17 00:00:00 2001
From: Derek Lesho <dlesho@codeweavers.com>
Date: Fri, 19 Mar 2021 16:54:03 -0400
Subject: [PATCH 11/39] winestreamer: Implement ::ProcessMessage for decoder
transform.
Signed-off-by: Derek Lesho <dlesho@codeweavers.com>
---
dlls/winegstreamer/decode_transform.c | 96 ++++++++++++++++++++++++++-
1 file changed, 94 insertions(+), 2 deletions(-)
diff --git a/dlls/winegstreamer/decode_transform.c b/dlls/winegstreamer/decode_transform.c
index c30780ba7ff..04a07647de4 100644
--- a/dlls/winegstreamer/decode_transform.c
+++ b/dlls/winegstreamer/decode_transform.c
@@ -710,9 +710,101 @@ static struct pipeline_event get_pipeline_event(struct mf_decoder *decoder)
static HRESULT WINAPI mf_decoder_ProcessMessage(IMFTransform *iface, MFT_MESSAGE_TYPE message, ULONG_PTR param)
{
- FIXME("%p, %u %lu.\n", iface, message, param);
+ struct mf_decoder *decoder = impl_mf_decoder_from_IMFTransform(iface);
+ HRESULT hr;
- return E_NOTIMPL;
+ TRACE("%p, %x %lu.\n", decoder, message, param);
+
+ EnterCriticalSection(&decoder->cs);
+ if (!decoder->input_type || !decoder->output_type)
+ {
+ LeaveCriticalSection(&decoder->cs);
+ return MF_E_TRANSFORM_TYPE_NOT_SET;
+ }
+
+ hr = S_OK;
+
+ switch (message)
+ {
+ case MFT_MESSAGE_NOTIFY_BEGIN_STREAMING:
+ case MFT_MESSAGE_NOTIFY_START_OF_STREAM:
+ break;
+ case MFT_MESSAGE_NOTIFY_END_OF_STREAM:
+ {
+ if (param)
+ {
+ hr = MF_E_INVALIDSTREAMNUMBER;
+ break;
+ }
+ if (!decoder->wg_stream)
+ {
+ ERR("End-Of-Stream marked on a decoder MFT which hasn't finished initialization\n");
+ hr = E_FAIL;
+ break;
+ }
+
+ decoder->eos = TRUE;
+ break;
+ }
+ case MFT_MESSAGE_COMMAND_DRAIN:
+ {
+ struct pipeline_event pip_event;
+
+ if (!decoder->wg_stream)
+ {
+ ERR("Drain requested on a decoder MFT which hasn't finished initialization\n");
+ hr = E_FAIL;
+ break;
+ }
+
+ pip_event = get_pipeline_event(decoder);
+ assert(pip_event.type == PIPELINE_EVENT_READ_REQUEST);
+
+ unix_funcs->wg_parser_complete_read_request(decoder->wg_parser, WG_READ_EOS, 0);
+
+ EnterCriticalSection(&decoder->event_cs);
+ decoder->event.type = PIPELINE_EVENT_NONE;
+ LeaveCriticalSection(&decoder->event_cs);
+ WakeAllConditionVariable(&decoder->event_cv);
+
+ decoder->draining = TRUE;
+ decoder->offset_tracker = 0;
+ break;
+ }
+ case MFT_MESSAGE_COMMAND_FLUSH:
+ {
+ struct pipeline_event pip_event;
+
+ if (!decoder->wg_stream)
+ {
+ ERR("Flush requested on a decoder MFT which hasn't finished initialization\n");
+ hr = E_FAIL;
+ break;
+ }
+
+ pip_event = get_pipeline_event(decoder);
+ assert(pip_event.type == PIPELINE_EVENT_READ_REQUEST);
+
+ unix_funcs->wg_parser_complete_read_request(decoder->wg_parser, WG_READ_FLUSHING, 0);
+
+ EnterCriticalSection(&decoder->event_cs);
+ decoder->event.type = PIPELINE_EVENT_NONE;
+ LeaveCriticalSection(&decoder->event_cs);
+ WakeAllConditionVariable(&decoder->event_cv);
+
+ decoder->offset_tracker = 0;
+ break;
+ }
+ default:
+ {
+ ERR("Unhandled message type %x.\n", message);
+ hr = E_FAIL;
+ break;
+ }
+ }
+
+ LeaveCriticalSection(&decoder->cs);
+ return hr;
}
static HRESULT WINAPI mf_decoder_ProcessInput(IMFTransform *iface, DWORD id, IMFSample *sample, DWORD flags)
--
2.30.2

View File

@ -1,103 +0,0 @@
From f1714a949175290e9f01bd32fde1dacecfed7946 Mon Sep 17 00:00:00 2001
From: Derek Lesho <dlesho@codeweavers.com>
Date: Thu, 3 Dec 2020 14:55:41 -0500
Subject: [PATCH] winegstreamer: Implement ::SetOutputType for color conversion
transform.
Signed-off-by: Derek Lesho <dlesho@codeweavers.com>
---
dlls/winegstreamer/colorconvert.c | 70 ++++++++++++++++++++++++++++++-
1 file changed, 68 insertions(+), 2 deletions(-)
diff --git a/dlls/winegstreamer/colorconvert.c b/dlls/winegstreamer/colorconvert.c
index b80232e195b..e7e84690738 100644
--- a/dlls/winegstreamer/colorconvert.c
+++ b/dlls/winegstreamer/colorconvert.c
@@ -53,6 +53,7 @@ struct color_converter
IMFTransform IMFTransform_iface;
LONG refcount;
IMFMediaType *input_type;
+ IMFMediaType *output_type;
CRITICAL_SECTION cs;
};
@@ -343,9 +344,74 @@ static HRESULT WINAPI color_converter_SetInputType(IMFTransform *iface, DWORD id
static HRESULT WINAPI color_converter_SetOutputType(IMFTransform *iface, DWORD id, IMFMediaType *type, DWORD flags)
{
- FIXME("%p, %u, %p, %#x.\n", iface, id, type, flags);
+ GstCaps *output_caps;
+ unsigned int i;
+ HRESULT hr;
- return E_NOTIMPL;
+ struct color_converter *converter = impl_color_converter_from_IMFTransform(iface);
+
+ TRACE("%p, %u, %p, %#x.\n", iface, id, type, flags);
+
+ if (id != 0)
+ return MF_E_INVALIDSTREAMNUMBER;
+
+ if (type)
+ {
+ GUID major_type, subtype;
+
+ if (FAILED(IMFMediaType_GetGUID(type, &MF_MT_MAJOR_TYPE, &major_type)))
+ return MF_E_INVALIDTYPE;
+ if (FAILED(IMFMediaType_GetGUID(type, &MF_MT_SUBTYPE, &subtype)))
+ return MF_E_INVALIDTYPE;
+
+ if (!(IsEqualGUID(&major_type, &MFMediaType_Video)))
+ return MF_E_INVALIDTYPE;
+
+ for (i = 0; i < ARRAY_SIZE(raw_types); i++)
+ {
+ if (IsEqualGUID(&subtype, raw_types[i]))
+ break;
+ }
+
+ if (i == ARRAY_SIZE(raw_types))
+ return MF_E_INVALIDTYPE;
+
+ if (!(output_caps = caps_from_mf_media_type(type)))
+ return MF_E_INVALIDTYPE;
+
+ gst_caps_unref(output_caps);
+ }
+
+ if (flags & MFT_SET_TYPE_TEST_ONLY)
+ return S_OK;
+
+ EnterCriticalSection(&converter->cs);
+
+ hr = S_OK;
+
+ if (type)
+ {
+ if (!converter->output_type)
+ hr = MFCreateMediaType(&converter->output_type);
+
+ if (SUCCEEDED(hr))
+ hr = IMFMediaType_CopyAllItems(type, (IMFAttributes *) converter->output_type);
+
+ if (FAILED(hr))
+ {
+ IMFMediaType_Release(converter->output_type);
+ converter->output_type = NULL;
+ }
+ }
+ else
+ {
+ IMFMediaType_Release(converter->output_type);
+ converter->output_type = NULL;
+ }
+
+ LeaveCriticalSection(&converter->cs);
+
+ return hr;
}
static HRESULT WINAPI color_converter_GetInputCurrentType(IMFTransform *iface, DWORD id, IMFMediaType **type)
--
2.29.2

View File

@ -0,0 +1,30 @@
From 5c7b05aeb941b1fbd4a978894873438aa0e5b397 Mon Sep 17 00:00:00 2001
From: Derek Lesho <dlesho@codeweavers.com>
Date: Fri, 19 Mar 2021 16:55:15 -0400
Subject: [PATCH 12/39] winegstreamer: Semi-stub ::GetAttributes for decoder
transform.
Signed-off-by: Derek Lesho <dlesho@codeweavers.com>
---
dlls/winegstreamer/decode_transform.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/dlls/winegstreamer/decode_transform.c b/dlls/winegstreamer/decode_transform.c
index 04a07647de4..f0e8527631c 100644
--- a/dlls/winegstreamer/decode_transform.c
+++ b/dlls/winegstreamer/decode_transform.c
@@ -257,9 +257,9 @@ static HRESULT WINAPI mf_decoder_GetOutputStreamInfo(IMFTransform *iface, DWORD
static HRESULT WINAPI mf_decoder_GetAttributes(IMFTransform *iface, IMFAttributes **attributes)
{
- FIXME("%p, %p.\n", iface, attributes);
+ FIXME("%p, %p. semi-stub!\n", iface, attributes);
- return E_NOTIMPL;
+ return MFCreateAttributes(attributes, 0);
}
static HRESULT WINAPI mf_decoder_GetInputStreamAttributes(IMFTransform *iface, DWORD id,
--
2.30.2

View File

@ -1,267 +0,0 @@
From c94cfbf0ec1c10452c2cf1496f32eeefe5794cea Mon Sep 17 00:00:00 2001
From: Derek Lesho <dlesho@codeweavers.com>
Date: Thu, 3 Dec 2020 15:22:20 -0500
Subject: [PATCH] winegstreamer: Implement ::Process(Input/Output) for color
conversion transform.
Signed-off-by: Derek Lesho <dlesho@codeweavers.com>
---
dlls/winegstreamer/colorconvert.c | 159 +++++++++++++++++++++++++++++-
1 file changed, 154 insertions(+), 5 deletions(-)
diff --git a/dlls/winegstreamer/colorconvert.c b/dlls/winegstreamer/colorconvert.c
index e7e84690738..b77f3358c52 100644
--- a/dlls/winegstreamer/colorconvert.c
+++ b/dlls/winegstreamer/colorconvert.c
@@ -55,6 +55,8 @@ struct color_converter
IMFMediaType *input_type;
IMFMediaType *output_type;
CRITICAL_SECTION cs;
+ BOOL inflight;
+ GstElement *container, *appsrc, *videoconvert, *appsink;
};
static struct color_converter *impl_color_converter_from_IMFTransform(IMFTransform *iface)
@@ -100,6 +102,7 @@ static ULONG WINAPI color_converter_Release(IMFTransform *iface)
{
transform->cs.DebugInfo->Spare[0] = 0;
DeleteCriticalSection(&transform->cs);
+ gst_object_unref(transform->container);
heap_free(transform);
}
@@ -307,7 +310,8 @@ static HRESULT WINAPI color_converter_SetInputType(IMFTransform *iface, DWORD id
if (!(input_caps = caps_from_mf_media_type(type)))
return MF_E_INVALIDTYPE;
- gst_caps_unref(input_caps);
+ if (flags & MFT_SET_TYPE_TEST_ONLY)
+ gst_caps_unref(input_caps);
}
if (flags & MFT_SET_TYPE_TEST_ONLY)
@@ -316,6 +320,7 @@ static HRESULT WINAPI color_converter_SetInputType(IMFTransform *iface, DWORD id
EnterCriticalSection(&converter->cs);
hr = S_OK;
+ gst_element_set_state(converter->container, GST_STATE_READY);
if (type)
{
@@ -325,6 +330,9 @@ static HRESULT WINAPI color_converter_SetInputType(IMFTransform *iface, DWORD id
if (SUCCEEDED(hr))
hr = IMFMediaType_CopyAllItems(type, (IMFAttributes *) converter->input_type);
+ g_object_set(converter->appsrc, "caps", input_caps, NULL);
+ gst_caps_unref(input_caps);
+
if (FAILED(hr))
{
IMFMediaType_Release(converter->input_type);
@@ -337,6 +345,9 @@ static HRESULT WINAPI color_converter_SetInputType(IMFTransform *iface, DWORD id
converter->input_type = NULL;
}
+ if (converter->input_type && converter->output_type)
+ gst_element_set_state(converter->container, GST_STATE_PLAYING);
+
LeaveCriticalSection(&converter->cs);
return hr;
@@ -379,7 +390,8 @@ static HRESULT WINAPI color_converter_SetOutputType(IMFTransform *iface, DWORD i
if (!(output_caps = caps_from_mf_media_type(type)))
return MF_E_INVALIDTYPE;
- gst_caps_unref(output_caps);
+ if (flags & MFT_SET_TYPE_TEST_ONLY)
+ gst_caps_unref(output_caps);
}
if (flags & MFT_SET_TYPE_TEST_ONLY)
@@ -388,6 +400,7 @@ static HRESULT WINAPI color_converter_SetOutputType(IMFTransform *iface, DWORD i
EnterCriticalSection(&converter->cs);
hr = S_OK;
+ gst_element_set_state(converter->container, GST_STATE_READY);
if (type)
{
@@ -397,6 +410,9 @@ static HRESULT WINAPI color_converter_SetOutputType(IMFTransform *iface, DWORD i
if (SUCCEEDED(hr))
hr = IMFMediaType_CopyAllItems(type, (IMFAttributes *) converter->output_type);
+ g_object_set(converter->appsink, "caps", output_caps, NULL);
+ gst_caps_unref(output_caps);
+
if (FAILED(hr))
{
IMFMediaType_Release(converter->output_type);
@@ -409,6 +425,9 @@ static HRESULT WINAPI color_converter_SetOutputType(IMFTransform *iface, DWORD i
converter->output_type = NULL;
}
+ if (converter->input_type && converter->output_type)
+ gst_element_set_state(converter->container, GST_STATE_PLAYING);
+
LeaveCriticalSection(&converter->cs);
return hr;
@@ -465,15 +484,102 @@ static HRESULT WINAPI color_converter_ProcessMessage(IMFTransform *iface, MFT_ME
static HRESULT WINAPI color_converter_ProcessInput(IMFTransform *iface, DWORD id, IMFSample *sample, DWORD flags)
{
- FIXME("%p, %u, %p, %#x.\n", iface, id, sample, flags);
+ GstBuffer *gst_buffer;
+ int ret;
- return E_NOTIMPL;
+ struct color_converter *converter = impl_color_converter_from_IMFTransform(iface);
+
+ TRACE("%p, %u, %p, %#x.\n", iface, id, sample, flags);
+
+ if (flags)
+ WARN("Unsupported flags %#x\n", flags);
+
+ if (id != 0)
+ return MF_E_INVALIDSTREAMNUMBER;
+
+ EnterCriticalSection(&converter->cs);
+
+ if (!converter->input_type || !converter->output_type)
+ {
+ LeaveCriticalSection(&converter->cs);
+ return MF_E_TRANSFORM_TYPE_NOT_SET;
+ }
+
+ if (converter->inflight)
+ {
+ LeaveCriticalSection(&converter->cs);
+ return MF_E_NOTACCEPTING;
+ }
+
+ if (!(gst_buffer = gst_buffer_from_mf_sample(sample)))
+ {
+ LeaveCriticalSection(&converter->cs);
+ return E_FAIL;
+ }
+
+ g_signal_emit_by_name(converter->appsrc, "push-buffer", gst_buffer, &ret);
+ gst_buffer_unref(gst_buffer);
+ if (ret != GST_FLOW_OK)
+ {
+ ERR("Couldn't push buffer ret = %d (%s)\n", ret, gst_flow_get_name(ret));
+ LeaveCriticalSection(&converter->cs);
+ return E_FAIL;
+ }
+
+ converter->inflight = TRUE;
+ LeaveCriticalSection(&converter->cs);
+
+ return S_OK;
}
static HRESULT WINAPI color_converter_ProcessOutput(IMFTransform *iface, DWORD flags, DWORD count,
MFT_OUTPUT_DATA_BUFFER *samples, DWORD *status)
{
- FIXME("%p, %#x, %u, %p, %p.\n", iface, flags, count, samples, status);
+ GstSample *sample;
+
+ struct color_converter *converter = impl_color_converter_from_IMFTransform(iface);
+
+ TRACE("%p, %#x, %u, %p, %p.\n", iface, flags, count, samples, status);
+
+ if (flags)
+ WARN("Unsupported flags %#x\n", flags);
+
+ if (!count)
+ return S_OK;
+
+ if (count != 1)
+ return MF_E_INVALIDSTREAMNUMBER;
+
+ if (samples[0].dwStreamID != 0)
+ return MF_E_INVALIDSTREAMNUMBER;
+
+ EnterCriticalSection(&converter->cs);
+
+ if (!converter->input_type || !converter->output_type)
+ {
+ LeaveCriticalSection(&converter->cs);
+ return MF_E_TRANSFORM_TYPE_NOT_SET;
+ }
+
+ if (!converter->inflight)
+ {
+ LeaveCriticalSection(&converter->cs);
+ return MF_E_TRANSFORM_NEED_MORE_INPUT;
+ }
+
+ g_signal_emit_by_name(converter->appsink, "pull-sample", &sample);
+
+ converter->inflight = FALSE;
+
+ samples[0].pSample = mf_sample_from_gst_buffer(gst_sample_get_buffer(sample));
+ gst_sample_unref(sample);
+ samples[0].dwStatus = S_OK;
+ samples[0].pEvents = NULL;
+ *status = 0;
+
+ LeaveCriticalSection(&converter->cs);
+
+ return S_OK;
return E_NOTIMPL;
}
@@ -523,6 +629,49 @@ HRESULT color_converter_create(REFIID riid, void **ret)
InitializeCriticalSection(&object->cs);
object->cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": color_converter_lock");
+ object->container = gst_bin_new(NULL);
+
+ if (!(object->appsrc = gst_element_factory_make("appsrc", NULL)))
+ {
+ ERR("Failed to create appsrc, are %u-bit Gstreamer \"base\" plugins installed?\n",
+ 8 * (int)sizeof(void *));
+ IMFTransform_Release(&object->IMFTransform_iface);
+ return E_FAIL;
+ }
+ gst_bin_add(GST_BIN(object->container), object->appsrc);
+
+ if (!(object->videoconvert = gst_element_factory_make("videoconvert", NULL)))
+ {
+ ERR("Failed to create videoconvert, are %u-bit Gstreamer \"base\" plugins installed?\n",
+ 8 * (int)sizeof(void *));
+ IMFTransform_Release(&object->IMFTransform_iface);
+ return E_FAIL;
+ }
+ gst_bin_add(GST_BIN(object->container), object->videoconvert);
+
+ if (!(object->appsink = gst_element_factory_make("appsink", NULL)))
+ {
+ ERR("Failed to create appsink, are %u-bit Gstreamer \"base\" plugins installed?\n",
+ 8 * (int)sizeof(void *));
+ IMFTransform_Release(&object->IMFTransform_iface);
+ return E_FAIL;
+ }
+ gst_bin_add(GST_BIN(object->container), object->appsink);
+
+ if (!gst_element_link(object->appsrc, object->videoconvert))
+ {
+ ERR("Failed to link appsrc to videoconvert\n");
+ IMFTransform_Release(&object->IMFTransform_iface);
+ return E_FAIL;
+ }
+
+ if (!gst_element_link(object->videoconvert, object->appsink))
+ {
+ ERR("Failed to link videoconvert to appsink\n");
+ IMFTransform_Release(&object->IMFTransform_iface);
+ return E_FAIL;
+ }
+
*ret = &object->IMFTransform_iface;
return S_OK;
}
--
2.29.2

View File

@ -0,0 +1,56 @@
From 86f104e3b17755d2eecd6d46ea1c66875232e2bd Mon Sep 17 00:00:00 2001
From: Derek Lesho <dlesho@codeweavers.com>
Date: Fri, 19 Mar 2021 16:57:11 -0400
Subject: [PATCH 13/39] winegstreamer: Register the H.264 decoder transform.
Signed-off-by: Derek Lesho <dlesho@codeweavers.com>
---
dlls/winegstreamer/mfplat.c | 25 +++++++++++++++++++++++++
1 file changed, 25 insertions(+)
diff --git a/dlls/winegstreamer/mfplat.c b/dlls/winegstreamer/mfplat.c
index 9a599358c61..f015ecc3f47 100644
--- a/dlls/winegstreamer/mfplat.c
+++ b/dlls/winegstreamer/mfplat.c
@@ -453,6 +453,20 @@ static const GUID *audio_converter_supported_types[] =
&MFAudioFormat_Float,
};
+static WCHAR h264_decoderW[] = L"H.264 Decoder";
+static const GUID *h264_decoder_input_types[] =
+{
+ &MFVideoFormat_H264,
+};
+static const GUID *h264_decoder_output_types[] =
+{
+ &MFVideoFormat_NV12,
+ &MFVideoFormat_I420,
+ &MFVideoFormat_IYUV,
+ &MFVideoFormat_YUY2,
+ &MFVideoFormat_YV12,
+};
+
static const struct mft
{
const GUID *clsid;
@@ -478,6 +492,17 @@ mfts[] =
ARRAY_SIZE(audio_converter_supported_types),
audio_converter_supported_types,
},
+ {
+ &CLSID_CMSH264DecoderMFT,
+ &MFT_CATEGORY_VIDEO_DECODER,
+ h264_decoderW,
+ MFT_ENUM_FLAG_SYNCMFT,
+ &MFMediaType_Video,
+ ARRAY_SIZE(h264_decoder_input_types),
+ h264_decoder_input_types,
+ ARRAY_SIZE(h264_decoder_output_types),
+ h264_decoder_output_types,
+ },
};
HRESULT mfplat_DllRegisterServer(void)
--
2.30.2

View File

@ -0,0 +1,304 @@
From 8c2af2c3be9a337c07638206ba9d0c4035fda36e Mon Sep 17 00:00:00 2001
From: Derek Lesho <dlesho@codeweavers.com>
Date: Fri, 19 Mar 2021 16:59:29 -0400
Subject: [PATCH 14/39] winegstreamer: Introduce AAC decoder transform.
Signed-off-by: Derek Lesho <dlesho@codeweavers.com>
---
dlls/winegstreamer/decode_transform.c | 10 ++++
dlls/winegstreamer/gst_private.h | 17 ++++++
dlls/winegstreamer/mfplat.c | 63 +++++++++++++++++++-
dlls/winegstreamer/quartz_parser.c | 1 +
dlls/winegstreamer/wg_parser.c | 62 +++++++++++++++++++
dlls/winegstreamer/winegstreamer_classes.idl | 6 ++
include/mfidl.idl | 1 +
7 files changed, 159 insertions(+), 1 deletion(-)
diff --git a/dlls/winegstreamer/decode_transform.c b/dlls/winegstreamer/decode_transform.c
index f0e8527631c..bb9bd6d6327 100644
--- a/dlls/winegstreamer/decode_transform.c
+++ b/dlls/winegstreamer/decode_transform.c
@@ -33,6 +33,9 @@ const GUID *h264_input_types[] = {&MFVideoFormat_H264};
/* NV12 comes first https://docs.microsoft.com/en-us/windows/win32/medfound/mft-decoder-expose-output-types-in-native-order . thanks to @vitorhnn */
const GUID *h264_output_types[] = {&MFVideoFormat_NV12, &MFVideoFormat_I420, &MFVideoFormat_IYUV, &MFVideoFormat_YUY2, &MFVideoFormat_YV12};
+const GUID *aac_input_types[] = {&MFAudioFormat_AAC};
+const GUID *aac_output_types[] = {&MFAudioFormat_Float};
+
static struct decoder_desc
{
const GUID *major_type;
@@ -49,6 +52,13 @@ static struct decoder_desc
h264_output_types,
ARRAY_SIZE(h264_output_types),
},
+ { /* DECODER_TYPE_AAC */
+ &MFMediaType_Audio,
+ aac_input_types,
+ ARRAY_SIZE(aac_input_types),
+ aac_output_types,
+ ARRAY_SIZE(aac_output_types),
+ }
};
struct pipeline_event
diff --git a/dlls/winegstreamer/gst_private.h b/dlls/winegstreamer/gst_private.h
index 25694aae84d..6407aff484c 100644
--- a/dlls/winegstreamer/gst_private.h
+++ b/dlls/winegstreamer/gst_private.h
@@ -127,11 +127,27 @@ struct wg_format
WG_AUDIO_FORMAT_MPEG1_LAYER1,
WG_AUDIO_FORMAT_MPEG1_LAYER2,
WG_AUDIO_FORMAT_MPEG1_LAYER3,
+
+ WG_AUDIO_FORMAT_AAC,
} format;
uint32_t channels;
uint32_t channel_mask; /* In WinMM format. */
uint32_t rate;
+
+ union
+ {
+ struct
+ {
+ uint32_t payload_type;
+ uint32_t indication;
+ /* The definition of this structure is found in ISO/IEC 14496-3,
+ which we don't have access to, so we'll just keep
+ the size set to the largest instance we've seen used. */
+ unsigned char audio_specifc_config[2];
+ uint32_t asp_size;
+ } aac;
+ } compressed;
} audio;
} u;
};
@@ -256,6 +272,7 @@ HRESULT audio_converter_create(REFIID riid, void **ret) DECLSPEC_HIDDEN;
enum decoder_type
{
DECODER_TYPE_H264,
+ DECODER_TYPE_AAC,
};
HRESULT decode_transform_create(REFIID riid, void **obj, enum decoder_type) DECLSPEC_HIDDEN;
diff --git a/dlls/winegstreamer/mfplat.c b/dlls/winegstreamer/mfplat.c
index f015ecc3f47..f3d9fb61a66 100644
--- a/dlls/winegstreamer/mfplat.c
+++ b/dlls/winegstreamer/mfplat.c
@@ -407,6 +407,11 @@ static HRESULT h264_decoder_create(REFIID riid, void **ret)
return decode_transform_create(riid, ret, DECODER_TYPE_H264);
}
+static HRESULT aac_decoder_create(REFIID riid, void **ret)
+{
+ return decode_transform_create(riid, ret, DECODER_TYPE_AAC);
+}
+
static const struct class_object
{
const GUID *clsid;
@@ -418,6 +423,7 @@ class_objects[] =
{ &CLSID_GStreamerByteStreamHandler, &winegstreamer_stream_handler_create },
{ &CLSID_WINEAudioConverter, &audio_converter_create },
{ &CLSID_CMSH264DecoderMFT, &h264_decoder_create },
+ { &CLSID_CMSAACDecMFT, &aac_decoder_create },
};
HRESULT mfplat_get_class_object(REFCLSID rclsid, REFIID riid, void **obj)
@@ -599,7 +605,8 @@ static IMFMediaType *mf_media_type_from_wg_format_audio(const struct wg_format *
IMFMediaType_SetUINT32(type, &MF_MT_AUDIO_BITS_PER_SAMPLE, audio_formats[i].depth);
IMFMediaType_SetUINT32(type, &MF_MT_AUDIO_SAMPLES_PER_SECOND, format->u.audio.rate);
IMFMediaType_SetUINT32(type, &MF_MT_AUDIO_NUM_CHANNELS, format->u.audio.channels);
- IMFMediaType_SetUINT32(type, &MF_MT_AUDIO_CHANNEL_MASK, format->u.audio.channel_mask);
+ if (format->u.audio.channel_mask)
+ IMFMediaType_SetUINT32(type, &MF_MT_AUDIO_CHANNEL_MASK, format->u.audio.channel_mask);
return type;
}
@@ -687,6 +694,8 @@ static void mf_media_type_to_wg_format_audio(IMFMediaType *type, struct wg_forma
channel_mask = KSAUDIO_SPEAKER_MONO;
else if (channels == 2)
channel_mask = KSAUDIO_SPEAKER_STEREO;
+ else if IsEqualGUID(&subtype, &MFAudioFormat_AAC)
+ channel_mask = 0;
else
{
FIXME("Channel mask is not set.\n");
@@ -699,6 +708,58 @@ static void mf_media_type_to_wg_format_audio(IMFMediaType *type, struct wg_forma
format->u.audio.channel_mask = channel_mask;
format->u.audio.rate = rate;
+ if (IsEqualGUID(&subtype, &MFAudioFormat_AAC))
+ {
+ UINT32 payload_type, indication, user_data_size;
+ unsigned char *user_data;
+
+ format->u.audio.format = WG_AUDIO_FORMAT_AAC;
+
+ if (SUCCEEDED(IMFMediaType_GetBlobSize(type, &MF_MT_USER_DATA, &user_data_size)))
+ {
+ user_data = malloc(user_data_size);
+ if (SUCCEEDED(IMFMediaType_GetBlob(type, &MF_MT_USER_DATA, user_data, user_data_size, NULL)))
+ {
+ struct {
+ WORD payload_type;
+ WORD indication;
+ WORD type;
+ WORD reserved1;
+ DWORD reserved2;
+ } *aac_info = (void *) user_data;
+
+ format->u.audio.compressed.aac.payload_type = aac_info->payload_type;
+ format->u.audio.compressed.aac.indication = aac_info->indication;
+
+ /* Audio specific config is stored at after HEAACWAVEINFO in MF_MT_USER_DATA
+ https://docs.microsoft.com/en-us/windows/win32/api/mmreg/ns-mmreg-heaacwaveformat */
+ if (user_data_size > 12)
+ {
+ user_data += 12;
+ user_data_size -= 12;
+
+ if (user_data_size > sizeof(format->u.audio.compressed.aac.audio_specifc_config))
+ {
+ FIXME("Encountered Audio-Specific-Config with a size larger than we support %u\n", user_data_size);
+ user_data_size = sizeof(format->u.audio.compressed.aac.audio_specifc_config);
+ }
+
+ memcpy(format->u.audio.compressed.aac.audio_specifc_config, user_data, user_data_size);
+ format->u.audio.compressed.aac.asp_size = user_data_size;
+ }
+
+ }
+ }
+
+ if (SUCCEEDED(IMFMediaType_GetUINT32(type, &MF_MT_AAC_PAYLOAD_TYPE, &payload_type)))
+ format->u.audio.compressed.aac.payload_type = payload_type;
+
+ if (SUCCEEDED(IMFMediaType_GetUINT32(type, &MF_MT_AAC_AUDIO_PROFILE_LEVEL_INDICATION, &indication)))
+ format->u.audio.compressed.aac.indication = indication;
+
+ return;
+ }
+
for (i = 0; i < ARRAY_SIZE(audio_formats); ++i)
{
if (IsEqualGUID(&subtype, audio_formats[i].subtype) && depth == audio_formats[i].depth)
diff --git a/dlls/winegstreamer/quartz_parser.c b/dlls/winegstreamer/quartz_parser.c
index 1c68eba1872..b1e35521266 100644
--- a/dlls/winegstreamer/quartz_parser.c
+++ b/dlls/winegstreamer/quartz_parser.c
@@ -100,6 +100,7 @@ static bool amt_from_wg_format_audio(AM_MEDIA_TYPE *mt, const struct wg_format *
switch (format->u.audio.format)
{
case WG_AUDIO_FORMAT_UNKNOWN:
+ case WG_AUDIO_FORMAT_AAC:
return false;
case WG_AUDIO_FORMAT_MPEG1_LAYER1:
diff --git a/dlls/winegstreamer/wg_parser.c b/dlls/winegstreamer/wg_parser.c
index 9ca5abebfaf..2a982576ef5 100644
--- a/dlls/winegstreamer/wg_parser.c
+++ b/dlls/winegstreamer/wg_parser.c
@@ -398,6 +398,13 @@ static void wg_set_caps_from_wg_format(GstCaps *caps, const struct wg_format *fo
gst_caps_set_simple(caps, "framerate", GST_TYPE_FRACTION, format->u.video.fps_n, format->u.video.fps_d, NULL);
break;
}
+ case WG_MAJOR_TYPE_AUDIO:
+ {
+ gst_caps_set_simple(caps, "rate", G_TYPE_INT, format->u.audio.rate, NULL);
+ gst_caps_set_simple(caps, "channels", G_TYPE_INT, format->u.audio.channels, NULL);
+ if (format->u.audio.channel_mask)
+ gst_caps_set_simple(caps, "channel-mask", G_TYPE_INT, format->u.audio.channel_mask, NULL);
+ }
default:
break;
}
@@ -409,6 +416,61 @@ static GstCaps *wg_format_to_caps_audio(const struct wg_format *format)
GstAudioFormat audio_format;
GstAudioInfo info;
+ /* compressed types */
+
+ if (format->u.audio.format == WG_AUDIO_FORMAT_AAC)
+ {
+ const char *profile, *level;
+ GstBuffer *audio_specific_config;
+ GstCaps *caps = gst_caps_new_empty_simple("audio/mpeg");
+ wg_set_caps_from_wg_format(caps, format);
+
+ gst_caps_set_simple(caps, "mpegversion", G_TYPE_INT, 4, NULL);
+
+ switch (format->u.audio.compressed.aac.payload_type)
+ {
+ case 0:
+ gst_caps_set_simple(caps, "stream-format", G_TYPE_STRING, "raw", NULL);
+ break;
+ case 1:
+ gst_caps_set_simple(caps, "stream-format", G_TYPE_STRING, "adts", NULL);
+ break;
+ case 2:
+ gst_caps_set_simple(caps, "stream-format", G_TYPE_STRING, "adif", NULL);
+ break;
+ case 3:
+ gst_caps_set_simple(caps, "stream-format", G_TYPE_STRING, "loas", NULL);
+ break;
+ default:
+ gst_caps_set_simple(caps, "stream-format", G_TYPE_STRING, "raw", NULL);
+ };
+
+ switch (format->u.audio.compressed.aac.indication)
+ {
+ case 0x29: profile = "lc"; level = "2"; break;
+ case 0x2A: profile = "lc"; level = "4"; break;
+ case 0x2B: profile = "lc"; level = "5"; break;
+ default:
+ FIXME("Unrecognized profile-level-indication %u\n", format->u.audio.compressed.aac.indication);
+ /* fallthrough */
+ case 0x00: case 0xFE: profile = level = NULL; break; /* unspecified */
+ }
+
+ if (profile)
+ gst_caps_set_simple(caps, "profile", G_TYPE_STRING, profile, NULL);
+ if (level)
+ gst_caps_set_simple(caps, "level", G_TYPE_STRING, level, NULL);
+
+ audio_specific_config = gst_buffer_new_allocate(NULL, format->u.audio.compressed.aac.asp_size, NULL);
+ gst_buffer_fill(audio_specific_config, 0, format->u.audio.compressed.aac.audio_specifc_config, format->u.audio.compressed.aac.asp_size);
+ gst_caps_set_simple(caps, "codec_data", GST_TYPE_BUFFER, audio_specific_config, NULL);
+ gst_buffer_unref(audio_specific_config);
+
+ return caps;
+ }
+
+ /* uncompressed_types */
+
if ((audio_format = wg_audio_format_to_gst(format->u.audio.format)) == GST_AUDIO_FORMAT_UNKNOWN)
return NULL;
diff --git a/dlls/winegstreamer/winegstreamer_classes.idl b/dlls/winegstreamer/winegstreamer_classes.idl
index 064a6872c79..4c58d83403b 100644
--- a/dlls/winegstreamer/winegstreamer_classes.idl
+++ b/dlls/winegstreamer/winegstreamer_classes.idl
@@ -73,3 +73,9 @@ coclass WINEAudioConverter { }
uuid(62ce7e72-4c71-4d20-b15d-452831a87d9d)
]
coclass CMSH264DecoderMFT { }
+
+[
+ threading(both),
+ uuid(32d186a7-218f-4c75-8876-dd77273a8999)
+]
+coclass CMSAACDecMFT { }
diff --git a/include/mfidl.idl b/include/mfidl.idl
index 616271861aa..dee81338b2b 100644
--- a/include/mfidl.idl
+++ b/include/mfidl.idl
@@ -1575,3 +1575,4 @@ cpp_quote("EXTERN_GUID(MF_ACTIVATE_CUSTOM_VIDEO_PRESENTER_FLAGS, 0xba491366, 0xb
cpp_quote("EXTERN_GUID(CLSID_VideoProcessorMFT, 0x88753b26, 0x5b24, 0x49bd, 0xb2, 0xe7, 0xc, 0x44, 0x5c, 0x78, 0xc9, 0x82);")
cpp_quote("EXTERN_GUID(CLSID_CMSH264DecoderMFT, 0x62ce7e72, 0x4c71, 0x4d20, 0xb1, 0x5d, 0x45, 0x28, 0x31, 0xa8, 0x7d, 0x9d);")
+cpp_quote("EXTERN_GUID(CLSID_CMSAACDecMFT, 0x32d186a7, 0x218f, 0x4c75, 0x88, 0x76, 0xdd, 0x77, 0x27, 0x3a, 0x89, 0x99);")
--
2.30.2

View File

@ -1,54 +0,0 @@
From e8eef3f90da399a077f5853e2a399c7e27a6418e Mon Sep 17 00:00:00 2001
From: Derek Lesho <dlesho@codeweavers.com>
Date: Thu, 3 Dec 2020 15:28:42 -0500
Subject: [PATCH] winegstreamer: Implement ::Get(Input/Output)StreamInfo for
color conversion transform.
Signed-off-by: Derek Lesho <dlesho@codeweavers.com>
---
dlls/winegstreamer/colorconvert.c | 23 +++++++++++++++++++----
1 file changed, 19 insertions(+), 4 deletions(-)
diff --git a/dlls/winegstreamer/colorconvert.c b/dlls/winegstreamer/colorconvert.c
index c07ef22acc3..43b8dddeee7 100644
--- a/dlls/winegstreamer/colorconvert.c
+++ b/dlls/winegstreamer/colorconvert.c
@@ -138,16 +138,31 @@ static HRESULT WINAPI color_converter_GetStreamIDs(IMFTransform *iface, DWORD in
static HRESULT WINAPI color_converter_GetInputStreamInfo(IMFTransform *iface, DWORD id, MFT_INPUT_STREAM_INFO *info)
{
- FIXME("%p %u %p.\n", iface, id, info);
+ TRACE("%p %u %p.\n", iface, id, info);
- return E_NOTIMPL;
+ if (id != 0)
+ return MF_E_INVALIDSTREAMNUMBER;
+
+ info->dwFlags = MFT_INPUT_STREAM_WHOLE_SAMPLES | MFT_INPUT_STREAM_DOES_NOT_ADDREF;
+ info->cbMaxLookahead = 0;
+ info->cbAlignment = 0;
+ info->hnsMaxLatency = 0;
+
+ return S_OK;
}
static HRESULT WINAPI color_converter_GetOutputStreamInfo(IMFTransform *iface, DWORD id, MFT_OUTPUT_STREAM_INFO *info)
{
- FIXME("%p %u %p.\n", iface, id, info);
+ TRACE("%p %u %p.\n", iface, id, info);
- return E_NOTIMPL;
+ if (id != 0)
+ return MF_E_INVALIDSTREAMNUMBER;
+
+ info->dwFlags = MFT_OUTPUT_STREAM_PROVIDES_SAMPLES;
+ info->cbSize = 0;
+ info->cbAlignment = 0;
+
+ return S_OK;
}
static HRESULT WINAPI color_converter_GetAttributes(IMFTransform *iface, IMFAttributes **attributes)
--
2.29.2

View File

@ -0,0 +1,53 @@
From f1011219faa95c40cdcffda69c65dee5566b3b80 Mon Sep 17 00:00:00 2001
From: Derek Lesho <dlesho@codeweavers.com>
Date: Fri, 19 Mar 2021 17:00:27 -0400
Subject: [PATCH 15/39] winegstreamer: Register the AAC decoder transform.
Signed-off-by: Derek Lesho <dlesho@codeweavers.com>
---
dlls/winegstreamer/mfplat.c | 22 ++++++++++++++++++++++
1 file changed, 22 insertions(+)
diff --git a/dlls/winegstreamer/mfplat.c b/dlls/winegstreamer/mfplat.c
index f3d9fb61a66..28b45893b1b 100644
--- a/dlls/winegstreamer/mfplat.c
+++ b/dlls/winegstreamer/mfplat.c
@@ -473,6 +473,17 @@ static const GUID *h264_decoder_output_types[] =
&MFVideoFormat_YV12,
};
+static WCHAR aac_decoderW[] = L"AAC Decoder";
+static const GUID *aac_decoder_input_types[] =
+{
+ &MFAudioFormat_AAC,
+};
+static const GUID *aac_decoder_output_types[] =
+{
+ &MFAudioFormat_Float,
+ &MFAudioFormat_PCM,
+};
+
static const struct mft
{
const GUID *clsid;
@@ -509,6 +520,17 @@ mfts[] =
ARRAY_SIZE(h264_decoder_output_types),
h264_decoder_output_types,
},
+ {
+ &CLSID_CMSAACDecMFT,
+ &MFT_CATEGORY_AUDIO_DECODER,
+ aac_decoderW,
+ MFT_ENUM_FLAG_SYNCMFT,
+ &MFMediaType_Audio,
+ ARRAY_SIZE(aac_decoder_input_types),
+ aac_decoder_input_types,
+ ARRAY_SIZE(aac_decoder_output_types),
+ aac_decoder_output_types,
+ },
};
HRESULT mfplat_DllRegisterServer(void)
--
2.30.2

Some files were not shown because too many files have changed in this diff Show More