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
9c8608eea6
commit
9bf50b7e1f
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
Loading…
x
Reference in New Issue
Block a user