mirror of
https://gitlab.winehq.org/wine/wine-staging.git
synced 2024-11-21 16:46:54 -08:00
Updated mfplat-streaming-support patchset
This commit is contained in:
parent
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
|
||||
|
@ -0,0 +1,869 @@
|
||||
From 431374b54bf2c58515c9bd56acf45d15f2fdf42d Mon Sep 17 00:00:00 2001
|
||||
From: Derek Lesho <dlesho@codeweavers.com>
|
||||
Date: Fri, 19 Mar 2021 16:40:46 -0400
|
||||
Subject: [PATCH 09/39] winegstreamer: Add push-mode path for wg_parser.
|
||||
|
||||
Signed-off-by: Derek Lesho <dlesho@codeweavers.com>
|
||||
---
|
||||
dlls/winegstreamer/gst_private.h | 28 +-
|
||||
dlls/winegstreamer/media_source.c | 4 +-
|
||||
dlls/winegstreamer/quartz_parser.c | 4 +-
|
||||
dlls/winegstreamer/wg_parser.c | 426 +++++++++++++++++++++++++----
|
||||
4 files changed, 408 insertions(+), 54 deletions(-)
|
||||
|
||||
diff --git a/dlls/winegstreamer/gst_private.h b/dlls/winegstreamer/gst_private.h
|
||||
index 215cf4577d4..25694aae84d 100644
|
||||
--- a/dlls/winegstreamer/gst_private.h
|
||||
+++ b/dlls/winegstreamer/gst_private.h
|
||||
@@ -136,6 +136,14 @@ struct wg_format
|
||||
} u;
|
||||
};
|
||||
|
||||
+struct wg_rect
|
||||
+{
|
||||
+ uint32_t left;
|
||||
+ uint32_t right;
|
||||
+ uint32_t top;
|
||||
+ uint32_t bottom;
|
||||
+};
|
||||
+
|
||||
enum wg_parser_event_type
|
||||
{
|
||||
WG_PARSER_EVENT_NONE = 0,
|
||||
@@ -165,6 +173,14 @@ struct wg_parser_event
|
||||
};
|
||||
C_ASSERT(sizeof(struct wg_parser_event) == 40);
|
||||
|
||||
+enum wg_read_result
|
||||
+{
|
||||
+ WG_READ_SUCCESS,
|
||||
+ WG_READ_FAILURE,
|
||||
+ WG_READ_FLUSHING,
|
||||
+ WG_READ_EOS,
|
||||
+};
|
||||
+
|
||||
struct unix_funcs
|
||||
{
|
||||
struct wg_parser *(CDECL *wg_decodebin_parser_create)(void);
|
||||
@@ -174,6 +190,8 @@ struct unix_funcs
|
||||
void (CDECL *wg_parser_destroy)(struct wg_parser *parser);
|
||||
|
||||
HRESULT (CDECL *wg_parser_connect)(struct wg_parser *parser, uint64_t file_size);
|
||||
+ HRESULT (CDECL *wg_parser_connect_unseekable)(struct wg_parser *parser,
|
||||
+ const struct wg_format *in_format, uint32_t stream_count, const struct wg_format *out_formats, const struct wg_rect *apertures);
|
||||
void (CDECL *wg_parser_disconnect)(struct wg_parser *parser);
|
||||
|
||||
void (CDECL *wg_parser_begin_flush)(struct wg_parser *parser);
|
||||
@@ -181,7 +199,11 @@ struct unix_funcs
|
||||
|
||||
bool (CDECL *wg_parser_get_read_request)(struct wg_parser *parser,
|
||||
void **data, uint64_t *offset, uint32_t *size);
|
||||
- void (CDECL *wg_parser_complete_read_request)(struct wg_parser *parser, bool ret);
|
||||
+ /* bytes_available indicates the actual size of the input packet, or 0 if the source source pad isn't aware of packets.
|
||||
+ If this value is lower or equal to the requested buffer size, it signifies the number of valid bytes set, if this
|
||||
+ value is higher than the requested buffer size, it means that a push mode pad should query for the rest of packet,
|
||||
+ concatenate the result, then submit it downstream. */
|
||||
+ void (CDECL *wg_parser_complete_read_request)(struct wg_parser *parser, enum wg_read_result ret, uint32_t bytes_available);
|
||||
|
||||
void (CDECL *wg_parser_set_unlimited_buffering)(struct wg_parser *parser);
|
||||
|
||||
@@ -189,7 +211,7 @@ struct unix_funcs
|
||||
struct wg_parser_stream *(CDECL *wg_parser_get_stream)(struct wg_parser *parser, uint32_t index);
|
||||
|
||||
void (CDECL *wg_parser_stream_get_preferred_format)(struct wg_parser_stream *stream, struct wg_format *format);
|
||||
- void (CDECL *wg_parser_stream_enable)(struct wg_parser_stream *stream, const struct wg_format *format);
|
||||
+ void (CDECL *wg_parser_stream_enable)(struct wg_parser_stream *stream, const struct wg_format *format, const struct wg_rect *aperture);
|
||||
void (CDECL *wg_parser_stream_disable)(struct wg_parser_stream *stream);
|
||||
|
||||
bool (CDECL *wg_parser_stream_get_event)(struct wg_parser_stream *stream, struct wg_parser_event *event);
|
||||
@@ -204,6 +226,8 @@ struct unix_funcs
|
||||
/* start_pos and stop_pos are in 100-nanosecond units. */
|
||||
bool (CDECL *wg_parser_stream_seek)(struct wg_parser_stream *stream, double rate,
|
||||
uint64_t start_pos, uint64_t stop_pos, DWORD start_flags, DWORD stop_flags);
|
||||
+ /* true: The stream has fully drained or has been flushed. false: An event is available. */
|
||||
+ bool (CDECL *wg_parser_stream_drain)(struct wg_parser_stream *stream);
|
||||
};
|
||||
|
||||
extern const struct unix_funcs *unix_funcs;
|
||||
diff --git a/dlls/winegstreamer/media_source.c b/dlls/winegstreamer/media_source.c
|
||||
index 9c554c7c415..f658cc0a5fc 100644
|
||||
--- a/dlls/winegstreamer/media_source.c
|
||||
+++ b/dlls/winegstreamer/media_source.c
|
||||
@@ -305,7 +305,7 @@ static void start_pipeline(struct media_source *source, struct source_async_comm
|
||||
IMFMediaTypeHandler_GetCurrentMediaType(mth, ¤t_mt);
|
||||
|
||||
mf_media_type_to_wg_format(current_mt, &format);
|
||||
- unix_funcs->wg_parser_stream_enable(stream->wg_stream, &format);
|
||||
+ unix_funcs->wg_parser_stream_enable(stream->wg_stream, &format, NULL);
|
||||
|
||||
IMFMediaType_Release(current_mt);
|
||||
IMFMediaTypeHandler_Release(mth);
|
||||
@@ -548,7 +548,7 @@ static DWORD CALLBACK read_thread(void *arg)
|
||||
hr = IMFByteStream_Read(byte_stream, data, size, &ret_size);
|
||||
if (SUCCEEDED(hr) && ret_size != size)
|
||||
ERR("Unexpected short read: requested %u bytes, got %u.\n", size, ret_size);
|
||||
- unix_funcs->wg_parser_complete_read_request(source->wg_parser, SUCCEEDED(hr));
|
||||
+ unix_funcs->wg_parser_complete_read_request(source->wg_parser, SUCCEEDED(hr) ? WG_READ_SUCCESS : WG_READ_FAILURE, ret_size);
|
||||
}
|
||||
|
||||
TRACE("Media source is shutting down; exiting.\n");
|
||||
diff --git a/dlls/winegstreamer/quartz_parser.c b/dlls/winegstreamer/quartz_parser.c
|
||||
index 4eceeae0757..1c68eba1872 100644
|
||||
--- a/dlls/winegstreamer/quartz_parser.c
|
||||
+++ b/dlls/winegstreamer/quartz_parser.c
|
||||
@@ -799,7 +799,7 @@ static DWORD CALLBACK read_thread(void *arg)
|
||||
if (!unix_funcs->wg_parser_get_read_request(filter->wg_parser, &data, &offset, &size))
|
||||
continue;
|
||||
hr = IAsyncReader_SyncRead(filter->reader, offset, size, data);
|
||||
- unix_funcs->wg_parser_complete_read_request(filter->wg_parser, SUCCEEDED(hr));
|
||||
+ unix_funcs->wg_parser_complete_read_request(filter->wg_parser, SUCCEEDED(hr) ? WG_READ_SUCCESS : WG_READ_FAILURE, size);
|
||||
}
|
||||
|
||||
TRACE("Streaming stopped; exiting.\n");
|
||||
@@ -1447,7 +1447,7 @@ static HRESULT WINAPI GSTOutPin_DecideBufferSize(struct strmbase_source *iface,
|
||||
|
||||
ret = amt_to_wg_format(&pin->pin.pin.mt, &format);
|
||||
assert(ret);
|
||||
- unix_funcs->wg_parser_stream_enable(pin->wg_stream, &format);
|
||||
+ unix_funcs->wg_parser_stream_enable(pin->wg_stream, &format, NULL);
|
||||
|
||||
/* We do need to drop any buffers that might have been sent with the old
|
||||
* caps, but this will be handled in parser_init_stream(). */
|
||||
diff --git a/dlls/winegstreamer/wg_parser.c b/dlls/winegstreamer/wg_parser.c
|
||||
index e9689c01085..9ca5abebfaf 100644
|
||||
--- a/dlls/winegstreamer/wg_parser.c
|
||||
+++ b/dlls/winegstreamer/wg_parser.c
|
||||
@@ -44,7 +44,7 @@ struct wg_parser
|
||||
BOOL (*init_gst)(struct wg_parser *parser);
|
||||
|
||||
struct wg_parser_stream **streams;
|
||||
- unsigned int stream_count;
|
||||
+ unsigned int stream_count, expected_stream_count;
|
||||
|
||||
GstElement *container, *decodebin;
|
||||
GstBus *bus;
|
||||
@@ -58,7 +58,7 @@ struct wg_parser
|
||||
pthread_mutex_t mutex;
|
||||
|
||||
pthread_cond_t init_cond;
|
||||
- bool no_more_pads, has_duration, error, pull_mode;
|
||||
+ bool no_more_pads, has_duration, error, pull_mode, seekable;
|
||||
|
||||
pthread_cond_t read_cond, read_done_cond;
|
||||
struct
|
||||
@@ -67,10 +67,12 @@ struct wg_parser
|
||||
uint64_t offset;
|
||||
uint32_t size;
|
||||
bool done;
|
||||
- bool ret;
|
||||
+ enum wg_read_result ret;
|
||||
} read_request;
|
||||
|
||||
- bool flushing, sink_connected;
|
||||
+ bool flushing, sink_connected, draining;
|
||||
+
|
||||
+ struct wg_format input_format;
|
||||
};
|
||||
|
||||
struct wg_parser_stream
|
||||
@@ -78,9 +80,10 @@ struct wg_parser_stream
|
||||
struct wg_parser *parser;
|
||||
|
||||
GstPad *their_src, *post_sink, *post_src, *my_sink;
|
||||
- GstElement *flip;
|
||||
+ GstElement *flip, *box;
|
||||
GstSegment segment;
|
||||
struct wg_format preferred_format, current_format;
|
||||
+ struct wg_rect aperture;
|
||||
|
||||
pthread_cond_t event_cond, event_empty_cond;
|
||||
struct wg_parser_event event;
|
||||
@@ -571,6 +574,9 @@ static void CDECL wg_parser_begin_flush(struct wg_parser *parser)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
+ if (!parser->seekable)
|
||||
+ return;
|
||||
+
|
||||
pthread_mutex_lock(&parser->mutex);
|
||||
parser->flushing = true;
|
||||
pthread_mutex_unlock(&parser->mutex);
|
||||
@@ -584,6 +590,9 @@ static void CDECL wg_parser_begin_flush(struct wg_parser *parser)
|
||||
|
||||
static void CDECL wg_parser_end_flush(struct wg_parser *parser)
|
||||
{
|
||||
+ if (!parser->seekable)
|
||||
+ return;
|
||||
+
|
||||
pthread_mutex_lock(&parser->mutex);
|
||||
parser->flushing = false;
|
||||
pthread_mutex_unlock(&parser->mutex);
|
||||
@@ -594,7 +603,7 @@ static bool CDECL wg_parser_get_read_request(struct wg_parser *parser,
|
||||
{
|
||||
pthread_mutex_lock(&parser->mutex);
|
||||
|
||||
- while (parser->sink_connected && !parser->read_request.data)
|
||||
+ while (parser->sink_connected && (!parser->read_request.data || parser->read_request.done))
|
||||
pthread_cond_wait(&parser->read_cond, &parser->mutex);
|
||||
|
||||
if (!parser->sink_connected)
|
||||
@@ -611,14 +620,25 @@ static bool CDECL wg_parser_get_read_request(struct wg_parser *parser,
|
||||
return true;
|
||||
}
|
||||
|
||||
-static void CDECL wg_parser_complete_read_request(struct wg_parser *parser, bool ret)
|
||||
+static void CDECL wg_parser_complete_read_request(struct wg_parser *parser, enum wg_read_result ret, uint32_t bytes_available)
|
||||
{
|
||||
pthread_mutex_lock(&parser->mutex);
|
||||
- parser->read_request.done = true;
|
||||
parser->read_request.ret = ret;
|
||||
- parser->read_request.data = NULL;
|
||||
- pthread_mutex_unlock(&parser->mutex);
|
||||
+ if (ret == WG_READ_SUCCESS && bytes_available < parser->read_request.size)
|
||||
+ {
|
||||
+ parser->read_request.offset += bytes_available;
|
||||
+ parser->read_request.size -= bytes_available;
|
||||
+ parser->read_request.data = (unsigned char *)parser->read_request.data + bytes_available;
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ parser->read_request.data = NULL;
|
||||
+ /* reuse size parameter to indicate how many more bytes are left to write */
|
||||
+ parser->read_request.size = bytes_available;
|
||||
+ }
|
||||
+ parser->read_request.done = true;
|
||||
pthread_cond_signal(&parser->read_done_cond);
|
||||
+ pthread_mutex_unlock(&parser->mutex);
|
||||
}
|
||||
|
||||
static void CDECL wg_parser_set_unlimited_buffering(struct wg_parser *parser)
|
||||
@@ -630,11 +650,15 @@ static void CDECL wg_parser_set_unlimited_buffering(struct wg_parser *parser)
|
||||
|
||||
static void CDECL wg_parser_stream_get_preferred_format(struct wg_parser_stream *stream, struct wg_format *format)
|
||||
{
|
||||
- *format = stream->preferred_format;
|
||||
+ if (stream->has_caps)
|
||||
+ *format = stream->preferred_format;
|
||||
}
|
||||
|
||||
-static void CDECL wg_parser_stream_enable(struct wg_parser_stream *stream, const struct wg_format *format)
|
||||
+static void CDECL wg_parser_stream_enable(struct wg_parser_stream *stream, const struct wg_format *format, const struct wg_rect *aperture)
|
||||
{
|
||||
+ if (!stream->parser->seekable)
|
||||
+ return;
|
||||
+
|
||||
stream->current_format = *format;
|
||||
stream->enabled = true;
|
||||
|
||||
@@ -663,6 +687,18 @@ static void CDECL wg_parser_stream_enable(struct wg_parser_stream *stream, const
|
||||
gst_util_set_object_arg(G_OBJECT(stream->flip), "method", "none");
|
||||
break;
|
||||
}
|
||||
+
|
||||
+ if (aperture)
|
||||
+ {
|
||||
+ if (aperture->left)
|
||||
+ g_object_set(G_OBJECT(stream->box), "left", -aperture->left, NULL);
|
||||
+ if (aperture->top)
|
||||
+ g_object_set(G_OBJECT(stream->box), "top", -aperture->top, NULL);
|
||||
+ if (aperture->right)
|
||||
+ g_object_set(G_OBJECT(stream->box), "right", aperture->right - format->u.video.width, NULL);
|
||||
+ if (aperture->bottom)
|
||||
+ g_object_set(G_OBJECT(stream->box), "bottom", aperture->bottom - format->u.video.height, NULL);
|
||||
+ }
|
||||
}
|
||||
|
||||
gst_pad_push_event(stream->my_sink, gst_event_new_reconfigure());
|
||||
@@ -691,6 +727,11 @@ static bool CDECL wg_parser_stream_get_event(struct wg_parser_stream *stream, st
|
||||
|
||||
*event = stream->event;
|
||||
|
||||
+ /* Set to ensure that drain isn't called on an EOS stream, causing a lock-up
|
||||
+ due to pull_data never being called again */
|
||||
+ if (stream->event.type == WG_PARSER_EVENT_EOS)
|
||||
+ stream->eos = true;
|
||||
+
|
||||
if (stream->event.type != WG_PARSER_EVENT_BUFFER)
|
||||
{
|
||||
stream->event.type = WG_PARSER_EVENT_NONE;
|
||||
@@ -751,6 +792,9 @@ static bool CDECL wg_parser_stream_seek(struct wg_parser_stream *stream, double
|
||||
GstSeekType start_type = GST_SEEK_TYPE_SET, stop_type = GST_SEEK_TYPE_SET;
|
||||
GstSeekFlags flags = 0;
|
||||
|
||||
+ if (!stream->parser->seekable)
|
||||
+ return false;
|
||||
+
|
||||
if (start_flags & AM_SEEKING_SeekToKeyFrame)
|
||||
flags |= GST_SEEK_FLAG_KEY_UNIT;
|
||||
if (start_flags & AM_SEEKING_Segment)
|
||||
@@ -767,6 +811,43 @@ static bool CDECL wg_parser_stream_seek(struct wg_parser_stream *stream, double
|
||||
GST_FORMAT_TIME, flags, start_type, start_pos * 100, stop_type, stop_pos * 100));
|
||||
}
|
||||
|
||||
+static bool CDECL wg_parser_stream_drain(struct wg_parser_stream *stream)
|
||||
+{
|
||||
+ struct wg_parser *parser = stream->parser;
|
||||
+ bool ret;
|
||||
+
|
||||
+ pthread_mutex_lock(&parser->mutex);
|
||||
+
|
||||
+ /* Sanity check making sure caller didn't try to drain an already-EOS or unselected stream.
|
||||
+ There's no reason for a caller to do this, but it could be an accident in which case we
|
||||
+ should indicate that the stream is drained instead of locking-up. */
|
||||
+ if (!stream->enabled || stream->eos)
|
||||
+ {
|
||||
+ pthread_mutex_unlock(&parser->mutex);
|
||||
+ return true;
|
||||
+ }
|
||||
+
|
||||
+ parser->draining = true;
|
||||
+ pthread_cond_signal(&parser->read_done_cond);
|
||||
+
|
||||
+ /* We must wait for either an event to occur or the drain to complete.
|
||||
+ Since drains are blocking, we assign this responsibility to the thread
|
||||
+ pulling data, as the pipeline will not need to pull more data until
|
||||
+ the drain completes. If one input buffer yields more than one output
|
||||
+ buffer, the chain callback blocks on the wg_parser_stream_buffer_release
|
||||
+ for the first buffer, which would never be called if the drain function
|
||||
+ hadn't completed. */
|
||||
+ while (!parser->flushing && parser->draining && stream->event.type == WG_PARSER_EVENT_NONE)
|
||||
+ pthread_cond_wait(&stream->event_cond, &parser->mutex);
|
||||
+
|
||||
+ ret = stream->event.type == WG_PARSER_EVENT_NONE;
|
||||
+ parser->draining = false;
|
||||
+
|
||||
+ pthread_mutex_unlock(&stream->parser->mutex);
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
static void CDECL wg_parser_stream_notify_qos(struct wg_parser_stream *stream,
|
||||
bool underflow, double proportion, int64_t diff, uint64_t timestamp)
|
||||
{
|
||||
@@ -1071,14 +1152,27 @@ static gboolean sink_query_cb(GstPad *pad, GstObject *parent, GstQuery *query)
|
||||
static struct wg_parser_stream *create_stream(struct wg_parser *parser)
|
||||
{
|
||||
struct wg_parser_stream *stream, **new_array;
|
||||
+ unsigned int i;
|
||||
char pad_name[19];
|
||||
|
||||
- if (!(new_array = realloc(parser->streams, (parser->stream_count + 1) * sizeof(*parser->streams))))
|
||||
- return NULL;
|
||||
- parser->streams = new_array;
|
||||
+ for (i = 0; i < parser->expected_stream_count; i++)
|
||||
+ {
|
||||
+ if (!parser->streams[i]->parser)
|
||||
+ {
|
||||
+ stream = parser->streams[i];
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
|
||||
- if (!(stream = calloc(1, sizeof(*stream))))
|
||||
- return NULL;
|
||||
+ if (i == parser->expected_stream_count)
|
||||
+ {
|
||||
+ if (!(new_array = realloc(parser->streams, (parser->stream_count + 1) * sizeof(*parser->streams))))
|
||||
+ return NULL;
|
||||
+ parser->streams = new_array;
|
||||
+
|
||||
+ if (!(stream = calloc(1, sizeof(*stream))))
|
||||
+ return NULL;
|
||||
+ }
|
||||
|
||||
gst_segment_init(&stream->segment, GST_FORMAT_UNDEFINED);
|
||||
|
||||
@@ -1118,7 +1212,7 @@ static void pad_added_cb(GstElement *element, GstPad *pad, gpointer user)
|
||||
|
||||
if (!strcmp(name, "video/x-raw"))
|
||||
{
|
||||
- GstElement *deinterlace, *vconv, *flip, *vconv2;
|
||||
+ GstElement *deinterlace, *vconv, *flip, *videobox, *vconv2;
|
||||
|
||||
/* DirectShow can express interlaced video, but downstream filters can't
|
||||
* necessarily consume it. In particular, the video renderer can't. */
|
||||
@@ -1147,6 +1241,13 @@ static void pad_added_cb(GstElement *element, GstPad *pad, gpointer user)
|
||||
goto out;
|
||||
}
|
||||
|
||||
+ if (!(videobox = gst_element_factory_make("videobox", NULL)))
|
||||
+ {
|
||||
+ fprintf(stderr, "winegstreamer: failed to create videobox, are %u-bit GStreamer \"base\" plugins installed?\n",
|
||||
+ 8 * (int)sizeof(void *));
|
||||
+ goto out;
|
||||
+ }
|
||||
+
|
||||
/* videoflip does not support 15 and 16-bit RGB so add a second videoconvert
|
||||
* to do the final conversion. */
|
||||
if (!(vconv2 = gst_element_factory_make("videoconvert", NULL)))
|
||||
@@ -1156,6 +1257,18 @@ static void pad_added_cb(GstElement *element, GstPad *pad, gpointer user)
|
||||
goto out;
|
||||
}
|
||||
|
||||
+ if (!parser->seekable)
|
||||
+ {
|
||||
+ if (stream->aperture.left)
|
||||
+ g_object_set(G_OBJECT(videobox), "left", -stream->aperture.left, NULL);
|
||||
+ if (stream->aperture.bottom)
|
||||
+ g_object_set(G_OBJECT(videobox), "top", -stream->aperture.top, NULL);
|
||||
+ if (stream->aperture.right)
|
||||
+ g_object_set(G_OBJECT(videobox), "right", stream->aperture.right - stream->current_format.u.video.width, NULL);
|
||||
+ if (stream->aperture.bottom)
|
||||
+ g_object_set(G_OBJECT(videobox), "bottom", stream->aperture.bottom - stream->current_format.u.video.height, NULL);
|
||||
+ }
|
||||
+
|
||||
/* The bin takes ownership of these elements. */
|
||||
gst_bin_add(GST_BIN(parser->container), deinterlace);
|
||||
gst_element_sync_state_with_parent(deinterlace);
|
||||
@@ -1163,16 +1276,20 @@ static void pad_added_cb(GstElement *element, GstPad *pad, gpointer user)
|
||||
gst_element_sync_state_with_parent(vconv);
|
||||
gst_bin_add(GST_BIN(parser->container), flip);
|
||||
gst_element_sync_state_with_parent(flip);
|
||||
+ gst_bin_add(GST_BIN(parser->container), videobox);
|
||||
+ gst_element_sync_state_with_parent(videobox);
|
||||
gst_bin_add(GST_BIN(parser->container), vconv2);
|
||||
gst_element_sync_state_with_parent(vconv2);
|
||||
|
||||
gst_element_link(deinterlace, vconv);
|
||||
gst_element_link(vconv, flip);
|
||||
- gst_element_link(flip, vconv2);
|
||||
+ gst_element_link(flip, videobox);
|
||||
+ gst_element_link(videobox, vconv2);
|
||||
|
||||
stream->post_sink = gst_element_get_static_pad(deinterlace, "sink");
|
||||
stream->post_src = gst_element_get_static_pad(vconv2, "src");
|
||||
stream->flip = flip;
|
||||
+ stream->box = videobox;
|
||||
}
|
||||
else if (!strcmp(name, "audio/x-raw"))
|
||||
{
|
||||
@@ -1260,23 +1377,25 @@ static void pad_removed_cb(GstElement *element, GstPad *pad, gpointer user)
|
||||
g_free(name);
|
||||
}
|
||||
|
||||
-static GstFlowReturn src_getrange_cb(GstPad *pad, GstObject *parent,
|
||||
- guint64 offset, guint size, GstBuffer **buffer)
|
||||
+static GstFlowReturn pull_data(struct wg_parser *parser, guint64 offset, guint size, guint *size_read, GstBuffer **buffer)
|
||||
{
|
||||
- struct wg_parser *parser = gst_pad_get_element_private(pad);
|
||||
GstBuffer *new_buffer = NULL;
|
||||
+ enum wg_read_result ret;
|
||||
GstMapInfo map_info;
|
||||
- bool ret;
|
||||
+ unsigned int i;
|
||||
|
||||
- GST_LOG("pad %p, offset %" G_GINT64_MODIFIER "u, length %u, buffer %p.", pad, offset, size, *buffer);
|
||||
+ GST_LOG("pad %p, offset %" G_GINT64_MODIFIER "u, length %u, buffer %p.", parser->my_src, offset, size, *buffer);
|
||||
|
||||
if (offset == GST_BUFFER_OFFSET_NONE)
|
||||
offset = parser->next_pull_offset;
|
||||
parser->next_pull_offset = offset + size;
|
||||
- if (offset >= parser->file_size)
|
||||
- return GST_FLOW_EOS;
|
||||
- if (offset + size >= parser->file_size)
|
||||
- size = parser->file_size - offset;
|
||||
+ if (parser->seekable)
|
||||
+ {
|
||||
+ if (offset >= parser->file_size)
|
||||
+ return GST_FLOW_EOS;
|
||||
+ if (offset + size >= parser->file_size)
|
||||
+ size = parser->file_size - offset;
|
||||
+ }
|
||||
|
||||
if (!*buffer)
|
||||
*buffer = new_buffer = gst_buffer_new_and_alloc(size);
|
||||
@@ -1285,6 +1404,14 @@ static GstFlowReturn src_getrange_cb(GstPad *pad, GstObject *parent,
|
||||
|
||||
pthread_mutex_lock(&parser->mutex);
|
||||
|
||||
+ if (parser->draining)
|
||||
+ {
|
||||
+ gst_pad_peer_query(parser->my_src, gst_query_new_drain());
|
||||
+ parser->draining = false;
|
||||
+ for (i = 0; i < parser->stream_count; i++)
|
||||
+ pthread_cond_signal(&parser->streams[i]->event_cond);
|
||||
+ }
|
||||
+
|
||||
assert(!parser->read_request.data);
|
||||
parser->read_request.data = map_info.data;
|
||||
parser->read_request.offset = offset;
|
||||
@@ -1296,8 +1423,36 @@ static GstFlowReturn src_getrange_cb(GstPad *pad, GstObject *parent,
|
||||
* the upstream pin to flush if necessary. We should never be blocked on
|
||||
* read_thread() not running. */
|
||||
|
||||
- while (!parser->read_request.done)
|
||||
+ while (!parser->read_request.done && !parser->draining)
|
||||
+ {
|
||||
pthread_cond_wait(&parser->read_done_cond, &parser->mutex);
|
||||
+ if (parser->draining)
|
||||
+ {
|
||||
+ gst_pad_peer_query(parser->my_src, gst_query_new_drain());
|
||||
+ parser->draining = false;
|
||||
+ for (i = 0; i < parser->stream_count; i++)
|
||||
+ pthread_cond_signal(&parser->streams[i]->event_cond);
|
||||
+ }
|
||||
+ if (size != parser->read_request.size && parser->read_request.data)
|
||||
+ {
|
||||
+ if (size_read)
|
||||
+ {
|
||||
+ *size_read = size - parser->read_request.size;
|
||||
+ parser->read_request.done = true;
|
||||
+ break;
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ parser->read_request.done = false;
|
||||
+ pthread_cond_signal(&parser->read_cond);
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ parser->read_request.data = NULL;
|
||||
+
|
||||
+ if (size_read && parser->read_request.size > size)
|
||||
+ *size_read = parser->read_request.size;
|
||||
|
||||
ret = parser->read_request.ret;
|
||||
|
||||
@@ -1305,12 +1460,29 @@ static GstFlowReturn src_getrange_cb(GstPad *pad, GstObject *parent,
|
||||
|
||||
gst_buffer_unmap(*buffer, &map_info);
|
||||
|
||||
+ if (size_read)
|
||||
+ size = min(*size_read, size);
|
||||
+
|
||||
+ gst_buffer_set_size(*buffer, size);
|
||||
+
|
||||
GST_LOG("Request returned %d.", ret);
|
||||
|
||||
- if (!ret && new_buffer)
|
||||
+ if (ret != WG_READ_SUCCESS && new_buffer)
|
||||
gst_buffer_unref(new_buffer);
|
||||
|
||||
- return ret ? GST_FLOW_OK : GST_FLOW_ERROR;
|
||||
+ return ret == WG_READ_SUCCESS ? GST_FLOW_OK :
|
||||
+ ret == WG_READ_FAILURE ? GST_FLOW_ERROR :
|
||||
+ ret == WG_READ_FLUSHING ? GST_FLOW_FLUSHING :
|
||||
+ ret == WG_READ_EOS ? GST_FLOW_EOS :
|
||||
+ GST_FLOW_ERROR;
|
||||
+}
|
||||
+
|
||||
+static GstFlowReturn src_getrange_cb(GstPad *pad, GstObject *parent,
|
||||
+ guint64 offset, guint size, GstBuffer **buffer)
|
||||
+{
|
||||
+ struct wg_parser *parser = gst_pad_get_element_private(pad);
|
||||
+
|
||||
+ return pull_data(parser, offset, size, NULL, buffer);
|
||||
}
|
||||
|
||||
static gboolean src_query_cb(GstPad *pad, GstObject *parent, GstQuery *query)
|
||||
@@ -1329,7 +1501,7 @@ static gboolean src_query_cb(GstPad *pad, GstObject *parent, GstQuery *query)
|
||||
gst_query_set_duration(query, GST_FORMAT_PERCENT, GST_FORMAT_PERCENT_MAX);
|
||||
return TRUE;
|
||||
}
|
||||
- else if (format == GST_FORMAT_BYTES)
|
||||
+ else if (format == GST_FORMAT_BYTES && parser->seekable)
|
||||
{
|
||||
gst_query_set_duration(query, GST_FORMAT_BYTES, parser->file_size);
|
||||
return TRUE;
|
||||
@@ -1343,15 +1515,42 @@ static gboolean src_query_cb(GstPad *pad, GstObject *parent, GstQuery *query)
|
||||
GST_WARNING("Cannot seek using format \"%s\".", gst_format_get_name(format));
|
||||
return FALSE;
|
||||
}
|
||||
+ if (!parser->seekable)
|
||||
+ return FALSE;
|
||||
gst_query_set_seeking(query, GST_FORMAT_BYTES, 1, 0, parser->file_size);
|
||||
return TRUE;
|
||||
|
||||
case GST_QUERY_SCHEDULING:
|
||||
- gst_query_set_scheduling(query, GST_SCHEDULING_FLAG_SEEKABLE, 1, -1, 0);
|
||||
+ gst_query_set_scheduling(query, parser->seekable ? GST_SCHEDULING_FLAG_SEEKABLE : GST_SCHEDULING_FLAG_SEQUENTIAL, 1, -1, 0);
|
||||
gst_query_add_scheduling_mode(query, GST_PAD_MODE_PUSH);
|
||||
gst_query_add_scheduling_mode(query, GST_PAD_MODE_PULL);
|
||||
return TRUE;
|
||||
|
||||
+ case GST_QUERY_CAPS:
|
||||
+ {
|
||||
+ GstCaps *caps, *filter, *temp;
|
||||
+
|
||||
+ gst_query_parse_caps(query, &filter);
|
||||
+
|
||||
+ if (parser->input_format.major_type)
|
||||
+ caps = wg_format_to_caps(&parser->input_format);
|
||||
+ else
|
||||
+ caps = gst_caps_new_any();
|
||||
+ if (!caps)
|
||||
+ return FALSE;
|
||||
+
|
||||
+ if (filter)
|
||||
+ {
|
||||
+ temp = gst_caps_intersect(caps, filter);
|
||||
+ gst_caps_unref(caps);
|
||||
+ caps = temp;
|
||||
+ }
|
||||
+
|
||||
+ gst_query_set_caps_result(query, caps);
|
||||
+ gst_caps_unref(caps);
|
||||
+ return TRUE;
|
||||
+ }
|
||||
+
|
||||
default:
|
||||
GST_WARNING("Unhandled query type %s.", GST_QUERY_TYPE_NAME(query));
|
||||
return FALSE;
|
||||
@@ -1361,42 +1560,115 @@ static gboolean src_query_cb(GstPad *pad, GstObject *parent, GstQuery *query)
|
||||
static void *push_data(void *arg)
|
||||
{
|
||||
struct wg_parser *parser = arg;
|
||||
- GstBuffer *buffer;
|
||||
+ GstBuffer *last_buffer = NULL;
|
||||
+ ULONG alloc_size = 16384;
|
||||
GstSegment *segment;
|
||||
guint max_size;
|
||||
|
||||
GST_DEBUG("Starting push thread.");
|
||||
|
||||
- if (!(buffer = gst_buffer_new_allocate(NULL, 16384, NULL)))
|
||||
- {
|
||||
- GST_ERROR("Failed to allocate memory.");
|
||||
- return NULL;
|
||||
- }
|
||||
-
|
||||
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"));
|
||||
|
||||
+ if (parser->input_format.major_type)
|
||||
+ gst_pad_push_event(parser->my_src, gst_event_new_caps(wg_format_to_caps(&parser->input_format)));
|
||||
+
|
||||
segment = gst_segment_new();
|
||||
gst_segment_init(segment, GST_FORMAT_BYTES);
|
||||
gst_pad_push_event(parser->my_src, gst_event_new_segment(segment));
|
||||
|
||||
+ assert(!(GST_PAD_IS_FLUSHING(parser->my_src)));
|
||||
+
|
||||
for (;;)
|
||||
{
|
||||
+ GstBuffer *buffer = NULL;
|
||||
+ unsigned int i;
|
||||
ULONG size;
|
||||
int ret;
|
||||
|
||||
if (parser->next_offset >= max_size)
|
||||
break;
|
||||
- size = min(16384, max_size - parser->next_offset);
|
||||
+ size = min(alloc_size, max_size - parser->next_offset);
|
||||
|
||||
- if ((ret = src_getrange_cb(parser->my_src, NULL, parser->next_offset, size, &buffer)) < 0)
|
||||
+ ret = pull_data(parser, parser->next_offset, size, &size, &buffer);
|
||||
+
|
||||
+ /* When we are in unseekable push mode, the pushing pad is responsible for handling flushing. */
|
||||
+ if (!parser->seekable && ret == GST_FLOW_FLUSHING)
|
||||
{
|
||||
+ if (last_buffer)
|
||||
+ {
|
||||
+ gst_buffer_unref(last_buffer);
|
||||
+ last_buffer = NULL;
|
||||
+ }
|
||||
+
|
||||
+ gst_pad_push_event(parser->my_src, gst_event_new_seek(1.0f,
|
||||
+ GST_FORMAT_BYTES, GST_SEEK_FLAG_FLUSH, GST_SEEK_TYPE_NONE, 0, GST_SEEK_TYPE_NONE, 0));
|
||||
+
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ if (!parser->seekable && ret == GST_FLOW_EOS)
|
||||
+ {
|
||||
+ if (last_buffer)
|
||||
+ {
|
||||
+ gst_buffer_unref(last_buffer);
|
||||
+ last_buffer = NULL;
|
||||
+ }
|
||||
+
|
||||
+ gst_pad_push_event(parser->my_src, gst_event_new_eos());
|
||||
+ pthread_mutex_lock(&parser->mutex);
|
||||
+ for (i = 0; i < parser->stream_count; i++)
|
||||
+ {
|
||||
+ if (!parser->streams[i]->enabled)
|
||||
+ continue;
|
||||
+ while (!parser->streams[i]->flushing && !parser->streams[i]->eos)
|
||||
+ pthread_cond_wait(&parser->streams[i]->event_empty_cond, &parser->mutex);
|
||||
+ parser->streams[i]->eos = false;
|
||||
+ }
|
||||
+
|
||||
+ if (parser->flushing)
|
||||
+ {
|
||||
+ pthread_mutex_unlock(&parser->mutex);
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ pthread_mutex_unlock(&parser->mutex);
|
||||
+
|
||||
+ segment = gst_segment_new();
|
||||
+ gst_segment_init(segment, GST_FORMAT_BYTES);
|
||||
+ gst_pad_push_event(parser->my_src, gst_event_new_segment(segment));
|
||||
+
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ if (ret < 0)
|
||||
+ {
|
||||
+ if (last_buffer)
|
||||
+ {
|
||||
+ gst_buffer_unref(last_buffer);
|
||||
+ last_buffer = NULL;
|
||||
+ }
|
||||
+
|
||||
GST_ERROR("Failed to read data, ret %s.", gst_flow_get_name(ret));
|
||||
break;
|
||||
}
|
||||
|
||||
- parser->next_offset += size;
|
||||
+ parser->next_offset += gst_buffer_get_size(buffer);
|
||||
+
|
||||
+ if (last_buffer)
|
||||
+ {
|
||||
+ buffer = gst_buffer_append(last_buffer, buffer);
|
||||
+ last_buffer = NULL;
|
||||
+ assert(alloc_size >= size);
|
||||
+ }
|
||||
+
|
||||
+ if (size > gst_buffer_get_size(buffer))
|
||||
+ {
|
||||
+ last_buffer = buffer;
|
||||
+ alloc_size = (size + 0xfff) & ~0xfff;
|
||||
+ continue;
|
||||
+ }
|
||||
|
||||
buffer->duration = buffer->pts = -1;
|
||||
if ((ret = gst_pad_push(parser->my_src, buffer)) < 0)
|
||||
@@ -1406,8 +1678,6 @@ static void *push_data(void *arg)
|
||||
}
|
||||
}
|
||||
|
||||
- gst_buffer_unref(buffer);
|
||||
-
|
||||
gst_pad_push_event(parser->my_src, gst_event_new_eos());
|
||||
|
||||
GST_DEBUG("Stopping push thread.");
|
||||
@@ -1423,6 +1693,12 @@ static gboolean activate_push(GstPad *pad, gboolean activate)
|
||||
{
|
||||
if (parser->push_thread)
|
||||
{
|
||||
+ pthread_mutex_lock(&parser->mutex);
|
||||
+ parser->read_request.ret = WG_READ_FAILURE;
|
||||
+ parser->read_request.data = NULL;
|
||||
+ parser->read_request.done = true;
|
||||
+ pthread_mutex_unlock(&parser->mutex);
|
||||
+ pthread_cond_signal(&parser->read_done_cond);
|
||||
pthread_join(parser->push_thread, NULL);
|
||||
parser->push_thread = 0;
|
||||
}
|
||||
@@ -1608,13 +1884,11 @@ static LONGLONG query_duration(GstPad *pad)
|
||||
return 0;
|
||||
}
|
||||
|
||||
-static HRESULT CDECL wg_parser_connect(struct wg_parser *parser, uint64_t file_size)
|
||||
+static HRESULT wg_parser_connect_inner(struct wg_parser *parser)
|
||||
{
|
||||
GstStaticPadTemplate src_template = GST_STATIC_PAD_TEMPLATE("quartz_src",
|
||||
GST_PAD_SRC, GST_PAD_ALWAYS, GST_STATIC_CAPS_ANY);
|
||||
- unsigned int i;
|
||||
|
||||
- parser->file_size = file_size;
|
||||
parser->sink_connected = true;
|
||||
|
||||
if (!parser->bus)
|
||||
@@ -1636,6 +1910,20 @@ static HRESULT CDECL wg_parser_connect(struct wg_parser *parser, uint64_t file_s
|
||||
parser->start_offset = parser->next_offset = parser->stop_offset = 0;
|
||||
parser->next_pull_offset = 0;
|
||||
|
||||
+ return S_OK;
|
||||
+}
|
||||
+
|
||||
+static HRESULT CDECL wg_parser_connect(struct wg_parser *parser, uint64_t file_size)
|
||||
+{
|
||||
+ unsigned int i;
|
||||
+ HRESULT hr;
|
||||
+
|
||||
+ parser->seekable = true;
|
||||
+ parser->file_size = file_size;
|
||||
+
|
||||
+ if ((hr = wg_parser_connect_inner(parser)))
|
||||
+ return hr;
|
||||
+
|
||||
if (!parser->init_gst(parser))
|
||||
return E_FAIL;
|
||||
|
||||
@@ -1666,6 +1954,43 @@ static HRESULT CDECL wg_parser_connect(struct wg_parser *parser, uint64_t file_s
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
+static HRESULT CDECL wg_parser_connect_unseekable(struct wg_parser *parser,
|
||||
+ const struct wg_format *in_format, uint32_t stream_count, const struct wg_format *out_formats, const struct wg_rect *apertures)
|
||||
+{
|
||||
+ unsigned int i;
|
||||
+ HRESULT hr;
|
||||
+
|
||||
+ parser->seekable = false;
|
||||
+ parser->flushing = false;
|
||||
+ /* since typefind is not available here, we must have an input_format */
|
||||
+ parser->input_format = *in_format;
|
||||
+
|
||||
+ if ((hr = wg_parser_connect_inner(parser)))
|
||||
+ return hr;
|
||||
+
|
||||
+ parser->stop_offset = -1;
|
||||
+
|
||||
+ parser->expected_stream_count = stream_count;
|
||||
+ parser->streams = calloc(stream_count, sizeof(*parser->streams));
|
||||
+
|
||||
+ for (i = 0; i < stream_count; i++)
|
||||
+ {
|
||||
+ parser->streams[i] = calloc(1, sizeof(*parser->streams[i]));
|
||||
+ parser->streams[i]->current_format = out_formats[i];
|
||||
+ if (apertures)
|
||||
+ parser->streams[i]->aperture = apertures[i];
|
||||
+ parser->streams[i]->enabled = true;
|
||||
+ }
|
||||
+
|
||||
+ if (!parser->init_gst(parser))
|
||||
+ return E_FAIL;
|
||||
+
|
||||
+ if (parser->stream_count < parser->expected_stream_count)
|
||||
+ return E_FAIL;
|
||||
+
|
||||
+ return S_OK;
|
||||
+}
|
||||
+
|
||||
static void free_stream(struct wg_parser_stream *stream)
|
||||
{
|
||||
if (stream->their_src)
|
||||
@@ -1740,6 +2065,9 @@ static BOOL decodebin_parser_init_gst(struct wg_parser *parser)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
+ if (parser->input_format.major_type)
|
||||
+ g_object_set(G_OBJECT(element), "sink-caps", wg_format_to_caps(&parser->input_format), NULL);
|
||||
+
|
||||
gst_bin_add(GST_BIN(parser->container), element);
|
||||
parser->decodebin = element;
|
||||
|
||||
@@ -2016,6 +2344,7 @@ static const struct unix_funcs funcs =
|
||||
wg_parser_destroy,
|
||||
|
||||
wg_parser_connect,
|
||||
+ wg_parser_connect_unseekable,
|
||||
wg_parser_disconnect,
|
||||
|
||||
wg_parser_begin_flush,
|
||||
@@ -2040,6 +2369,7 @@ static const struct unix_funcs funcs =
|
||||
|
||||
wg_parser_stream_get_duration,
|
||||
wg_parser_stream_seek,
|
||||
+ wg_parser_stream_drain,
|
||||
};
|
||||
|
||||
NTSTATUS CDECL __wine_init_unix_lib(HMODULE module, DWORD reason, const void *ptr_in, void *ptr_out)
|
||||
--
|
||||
2.30.2
|
||||
|
@ -0,0 +1,648 @@
|
||||
From 316e739c324ef33e31987f0d5abd7b28db21e89a Mon Sep 17 00:00:00 2001
|
||||
From: Derek Lesho <dlesho@codeweavers.com>
|
||||
Date: Fri, 19 Mar 2021 16:53:02 -0400
|
||||
Subject: [PATCH 10/39] winegstreamer: Implement ::Process(Input/Output) for
|
||||
decoder transform.
|
||||
|
||||
Signed-off-by: Derek Lesho <dlesho@codeweavers.com>
|
||||
---
|
||||
dlls/winegstreamer/decode_transform.c | 532 +++++++++++++++++++++++++-
|
||||
1 file changed, 526 insertions(+), 6 deletions(-)
|
||||
|
||||
diff --git a/dlls/winegstreamer/decode_transform.c b/dlls/winegstreamer/decode_transform.c
|
||||
index dadd161bcc9..c30780ba7ff 100644
|
||||
--- a/dlls/winegstreamer/decode_transform.c
|
||||
+++ b/dlls/winegstreamer/decode_transform.c
|
||||
@@ -51,14 +51,47 @@ static struct decoder_desc
|
||||
},
|
||||
};
|
||||
|
||||
+struct pipeline_event
|
||||
+{
|
||||
+ enum
|
||||
+ {
|
||||
+ PIPELINE_EVENT_NONE,
|
||||
+ PIPELINE_EVENT_PARSER_STARTED,
|
||||
+ PIPELINE_EVENT_READ_REQUEST,
|
||||
+ } type;
|
||||
+ union
|
||||
+ {
|
||||
+ struct
|
||||
+ {
|
||||
+ struct wg_parser_stream *stream;
|
||||
+ } parser_started;
|
||||
+ } u;
|
||||
+};
|
||||
+
|
||||
struct mf_decoder
|
||||
{
|
||||
IMFTransform IMFTransform_iface;
|
||||
LONG refcount;
|
||||
enum decoder_type type;
|
||||
IMFMediaType *input_type, *output_type;
|
||||
- CRITICAL_SECTION cs;
|
||||
- BOOL video;
|
||||
+ CRITICAL_SECTION cs, help_cs, event_cs;
|
||||
+ CONDITION_VARIABLE help_cv, event_cv;
|
||||
+ BOOL flushing, draining, eos, helper_thread_shutdown, video;
|
||||
+ HANDLE helper_thread, read_thread;
|
||||
+ uint64_t offset_tracker;
|
||||
+ struct wg_parser *wg_parser;
|
||||
+ struct wg_parser_stream *wg_stream;
|
||||
+
|
||||
+ struct
|
||||
+ {
|
||||
+ enum
|
||||
+ {
|
||||
+ HELP_REQ_NONE,
|
||||
+ HELP_REQ_START_PARSER,
|
||||
+ } type;
|
||||
+ } help_request;
|
||||
+
|
||||
+ struct pipeline_event event;
|
||||
};
|
||||
|
||||
static struct mf_decoder *impl_mf_decoder_from_IMFTransform(IMFTransform *iface)
|
||||
@@ -114,7 +147,15 @@ static ULONG WINAPI mf_decoder_Release(IMFTransform *iface)
|
||||
decoder->output_type = NULL;
|
||||
}
|
||||
|
||||
+ if (decoder->wg_stream)
|
||||
+ unix_funcs->wg_parser_disconnect(decoder->wg_parser);
|
||||
+
|
||||
+ if (decoder->wg_parser)
|
||||
+ unix_funcs->wg_parser_destroy(decoder->wg_parser);
|
||||
+
|
||||
DeleteCriticalSection(&decoder->cs);
|
||||
+ DeleteCriticalSection(&decoder->help_cs);
|
||||
+ DeleteCriticalSection(&decoder->event_cs);
|
||||
|
||||
heap_free(decoder);
|
||||
}
|
||||
@@ -341,6 +382,12 @@ static HRESULT WINAPI mf_decoder_SetInputType(IMFTransform *iface, DWORD id, IMF
|
||||
|
||||
EnterCriticalSection(&decoder->cs);
|
||||
|
||||
+ if (decoder->wg_stream)
|
||||
+ {
|
||||
+ decoder->wg_stream = NULL;
|
||||
+ unix_funcs->wg_parser_disconnect(decoder->wg_parser);
|
||||
+ }
|
||||
+
|
||||
if (decoder->input_type)
|
||||
{
|
||||
IMFMediaType_Release(decoder->input_type);
|
||||
@@ -379,6 +426,12 @@ static HRESULT WINAPI mf_decoder_SetInputType(IMFTransform *iface, DWORD id, IMF
|
||||
|
||||
hr = S_OK;
|
||||
|
||||
+ if (decoder->wg_stream)
|
||||
+ {
|
||||
+ decoder->wg_stream = NULL;
|
||||
+ unix_funcs->wg_parser_disconnect(decoder->wg_parser);
|
||||
+ }
|
||||
+
|
||||
if (!decoder->input_type)
|
||||
hr = MFCreateMediaType(&decoder->input_type);
|
||||
|
||||
@@ -388,6 +441,16 @@ static HRESULT WINAPI mf_decoder_SetInputType(IMFTransform *iface, DWORD id, IMF
|
||||
decoder->input_type = NULL;
|
||||
}
|
||||
|
||||
+ if (decoder->input_type && decoder->output_type)
|
||||
+ {
|
||||
+ EnterCriticalSection(&decoder->help_cs);
|
||||
+ while(decoder->help_request.type != HELP_REQ_NONE)
|
||||
+ SleepConditionVariableCS(&decoder->help_cv, &decoder->help_cs, INFINITE);
|
||||
+ decoder->help_request.type = HELP_REQ_START_PARSER;
|
||||
+ LeaveCriticalSection(&decoder->help_cs);
|
||||
+ WakeAllConditionVariable(&decoder->help_cv);
|
||||
+ }
|
||||
+
|
||||
LeaveCriticalSection(&decoder->cs);
|
||||
return hr;
|
||||
}
|
||||
@@ -412,6 +475,12 @@ static HRESULT WINAPI mf_decoder_SetOutputType(IMFTransform *iface, DWORD id, IM
|
||||
|
||||
EnterCriticalSection(&decoder->cs);
|
||||
|
||||
+ if (decoder->wg_stream)
|
||||
+ {
|
||||
+ decoder->wg_stream = NULL;
|
||||
+ unix_funcs->wg_parser_disconnect(decoder->wg_parser);
|
||||
+ }
|
||||
+
|
||||
if (decoder->output_type)
|
||||
{
|
||||
IMFMediaType_Release(decoder->output_type);
|
||||
@@ -450,6 +519,12 @@ static HRESULT WINAPI mf_decoder_SetOutputType(IMFTransform *iface, DWORD id, IM
|
||||
|
||||
hr = S_OK;
|
||||
|
||||
+ if (decoder->wg_stream)
|
||||
+ {
|
||||
+ decoder->wg_stream = NULL;
|
||||
+ unix_funcs->wg_parser_disconnect(decoder->wg_parser);
|
||||
+ }
|
||||
+
|
||||
if (!decoder->output_type)
|
||||
hr = MFCreateMediaType(&decoder->output_type);
|
||||
|
||||
@@ -459,6 +534,16 @@ static HRESULT WINAPI mf_decoder_SetOutputType(IMFTransform *iface, DWORD id, IM
|
||||
decoder->output_type = NULL;
|
||||
}
|
||||
|
||||
+ if (decoder->input_type && decoder->output_type)
|
||||
+ {
|
||||
+ EnterCriticalSection(&decoder->help_cs);
|
||||
+ while(decoder->help_request.type != HELP_REQ_NONE)
|
||||
+ SleepConditionVariableCS(&decoder->help_cv, &decoder->help_cs, INFINITE);
|
||||
+ decoder->help_request.type = HELP_REQ_START_PARSER;
|
||||
+ LeaveCriticalSection(&decoder->help_cs);
|
||||
+ WakeAllConditionVariable(&decoder->help_cv);
|
||||
+ }
|
||||
+
|
||||
LeaveCriticalSection(&decoder->cs);
|
||||
return hr;
|
||||
}
|
||||
@@ -505,6 +590,124 @@ static HRESULT WINAPI mf_decoder_ProcessEvent(IMFTransform *iface, DWORD id, IMF
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
+static DWORD CALLBACK helper_thread_func(PVOID ctx)
|
||||
+{
|
||||
+ struct mf_decoder *decoder = (struct mf_decoder *)ctx;
|
||||
+
|
||||
+ for(;;)
|
||||
+ {
|
||||
+ EnterCriticalSection(&decoder->help_cs);
|
||||
+
|
||||
+ while(!decoder->helper_thread_shutdown && decoder->help_request.type == HELP_REQ_NONE)
|
||||
+ SleepConditionVariableCS(&decoder->help_cv, &decoder->help_cs, INFINITE);
|
||||
+ if (decoder->helper_thread_shutdown)
|
||||
+ return 0;
|
||||
+
|
||||
+ switch(decoder->help_request.type)
|
||||
+ {
|
||||
+ case HELP_REQ_START_PARSER:
|
||||
+ {
|
||||
+ struct wg_format input_format, output_format;
|
||||
+ struct wg_rect wg_aperture = {0};
|
||||
+ MFVideoArea *aperture = NULL;
|
||||
+ UINT32 aperture_size;
|
||||
+
|
||||
+ decoder->help_request.type = HELP_REQ_NONE;
|
||||
+ LeaveCriticalSection(&decoder->help_cs);
|
||||
+
|
||||
+ mf_media_type_to_wg_format(decoder->input_type, &input_format);
|
||||
+ mf_media_type_to_wg_format(decoder->output_type, &output_format);
|
||||
+
|
||||
+ if (SUCCEEDED(IMFMediaType_GetAllocatedBlob(decoder->output_type,
|
||||
+ &MF_MT_MINIMUM_DISPLAY_APERTURE, (UINT8 **) &aperture, &aperture_size)))
|
||||
+ {
|
||||
+ TRACE("Decoded media's aperture: x: %u %u/65536, y: %u %u/65536, area: %u x %u\n",
|
||||
+ aperture->OffsetX.value, aperture->OffsetX.fract,
|
||||
+ aperture->OffsetY.value, aperture->OffsetY.fract, aperture->Area.cx, aperture->Area.cy);
|
||||
+
|
||||
+ /* TODO: verify aperture params? */
|
||||
+
|
||||
+ wg_aperture.left = aperture->OffsetX.value;
|
||||
+ wg_aperture.top = aperture->OffsetY.value;
|
||||
+ wg_aperture.right = aperture->Area.cx;
|
||||
+ wg_aperture.bottom = aperture->Area.cy;
|
||||
+
|
||||
+ CoTaskMemFree(aperture);
|
||||
+ }
|
||||
+
|
||||
+ unix_funcs->wg_parser_connect_unseekable(decoder->wg_parser,
|
||||
+ &input_format, 1, &output_format, aperture ? &wg_aperture : NULL);
|
||||
+
|
||||
+ EnterCriticalSection(&decoder->event_cs);
|
||||
+ while (decoder->event.type != PIPELINE_EVENT_NONE)
|
||||
+ SleepConditionVariableCS(&decoder->event_cv, &decoder->event_cs, INFINITE);
|
||||
+
|
||||
+ decoder->event.type = PIPELINE_EVENT_PARSER_STARTED;
|
||||
+ decoder->event.u.parser_started.stream = unix_funcs->wg_parser_get_stream(decoder->wg_parser, 0);
|
||||
+
|
||||
+ LeaveCriticalSection(&decoder->event_cs);
|
||||
+ WakeAllConditionVariable(&decoder->event_cv);
|
||||
+
|
||||
+ break;
|
||||
+ }
|
||||
+ default:
|
||||
+ assert(0);
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+/* We use a separate thread to wait for reads, as we may want to wait to WAIT_ANY
|
||||
+ on a read and another event. */
|
||||
+static DWORD CALLBACK read_thread_func(PVOID ctx)
|
||||
+{
|
||||
+ struct mf_decoder *decoder = (struct mf_decoder *)ctx;
|
||||
+ void *data;
|
||||
+ uint64_t offset;
|
||||
+ uint32_t size;
|
||||
+
|
||||
+ for (;;)
|
||||
+ {
|
||||
+ if (!unix_funcs->wg_parser_get_read_request(decoder->wg_parser, &data, &offset, &size))
|
||||
+ continue;
|
||||
+
|
||||
+ if (decoder->helper_thread_shutdown)
|
||||
+ break;
|
||||
+
|
||||
+ EnterCriticalSection(&decoder->event_cs);
|
||||
+ while (decoder->event.type != PIPELINE_EVENT_NONE)
|
||||
+ SleepConditionVariableCS(&decoder->event_cv, &decoder->event_cs, INFINITE);
|
||||
+
|
||||
+ decoder->event.type = PIPELINE_EVENT_READ_REQUEST;
|
||||
+ WakeAllConditionVariable(&decoder->event_cv);
|
||||
+ while (decoder->event.type == PIPELINE_EVENT_READ_REQUEST)
|
||||
+ SleepConditionVariableCS(&decoder->event_cv, &decoder->event_cs, INFINITE);
|
||||
+ LeaveCriticalSection(&decoder->event_cs);
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static struct pipeline_event get_pipeline_event(struct mf_decoder *decoder)
|
||||
+{
|
||||
+ struct pipeline_event ret;
|
||||
+
|
||||
+ EnterCriticalSection(&decoder->event_cs);
|
||||
+ while(decoder->event.type == PIPELINE_EVENT_NONE)
|
||||
+ SleepConditionVariableCS(&decoder->event_cv, &decoder->event_cs, INFINITE);
|
||||
+
|
||||
+ ret = decoder->event;
|
||||
+
|
||||
+ if (ret.type != PIPELINE_EVENT_READ_REQUEST)
|
||||
+ {
|
||||
+ decoder->event.type = PIPELINE_EVENT_NONE;
|
||||
+ WakeAllConditionVariable(&decoder->event_cv);
|
||||
+ }
|
||||
+
|
||||
+ LeaveCriticalSection(&decoder->event_cs);
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
static HRESULT WINAPI mf_decoder_ProcessMessage(IMFTransform *iface, MFT_MESSAGE_TYPE message, ULONG_PTR param)
|
||||
{
|
||||
FIXME("%p, %u %lu.\n", iface, message, param);
|
||||
@@ -514,17 +717,318 @@ static HRESULT WINAPI mf_decoder_ProcessMessage(IMFTransform *iface, MFT_MESSAGE
|
||||
|
||||
static HRESULT WINAPI mf_decoder_ProcessInput(IMFTransform *iface, DWORD id, IMFSample *sample, DWORD flags)
|
||||
{
|
||||
- FIXME("%p, %u, %p, %#x.\n", iface, id, sample, flags);
|
||||
+ struct mf_decoder *decoder = impl_mf_decoder_from_IMFTransform(iface);
|
||||
+ struct pipeline_event pip_event;
|
||||
+ IMFMediaBuffer *buffer = NULL;
|
||||
+ HRESULT hr = S_OK;
|
||||
+ BYTE *buffer_data;
|
||||
+ DWORD buffer_size;
|
||||
+ uint32_t size = 0;
|
||||
+ uint64_t offset;
|
||||
+ void *data;
|
||||
|
||||
- return E_NOTIMPL;
|
||||
+ TRACE("%p, %u, %p, %#x.\n", decoder, id, sample, flags);
|
||||
+
|
||||
+ if (flags)
|
||||
+ WARN("Unsupported flags %#x\n", flags);
|
||||
+
|
||||
+ if (id != 0)
|
||||
+ return MF_E_INVALIDSTREAMNUMBER;
|
||||
+
|
||||
+ EnterCriticalSection(&decoder->cs);
|
||||
+
|
||||
+ if (!decoder->input_type || !decoder->output_type)
|
||||
+ {
|
||||
+ LeaveCriticalSection(&decoder->cs);
|
||||
+ return MF_E_TRANSFORM_TYPE_NOT_SET;
|
||||
+ }
|
||||
+
|
||||
+ if (decoder->draining)
|
||||
+ {
|
||||
+ LeaveCriticalSection(&decoder->cs);
|
||||
+ return MF_E_NOTACCEPTING;
|
||||
+ }
|
||||
+
|
||||
+ if (!decoder->wg_stream)
|
||||
+ {
|
||||
+ pip_event = get_pipeline_event(decoder);
|
||||
+
|
||||
+ switch (pip_event.type)
|
||||
+ {
|
||||
+ case PIPELINE_EVENT_PARSER_STARTED:
|
||||
+ decoder->wg_stream = pip_event.u.parser_started.stream;
|
||||
+ break;
|
||||
+ case PIPELINE_EVENT_READ_REQUEST:
|
||||
+ break;
|
||||
+ default:
|
||||
+ assert(0);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (decoder->wg_stream && !unix_funcs->wg_parser_stream_drain(decoder->wg_stream))
|
||||
+ {
|
||||
+ LeaveCriticalSection(&decoder->cs);
|
||||
+ return MF_E_NOTACCEPTING;
|
||||
+ }
|
||||
+
|
||||
+ /* At this point, we either have a pre-init read request, or drained pipeline */
|
||||
+
|
||||
+ if (FAILED(hr = IMFSample_ConvertToContiguousBuffer(sample, &buffer)))
|
||||
+ goto done;
|
||||
+
|
||||
+ if (FAILED(hr = IMFMediaBuffer_Lock(buffer, &buffer_data, NULL, &buffer_size)))
|
||||
+ goto done;
|
||||
+
|
||||
+ pip_event = get_pipeline_event(decoder);
|
||||
+ assert(pip_event.type == PIPELINE_EVENT_READ_REQUEST);
|
||||
+
|
||||
+ for(;;)
|
||||
+ {
|
||||
+ uint32_t copy_size;
|
||||
+
|
||||
+ if (!unix_funcs->wg_parser_get_read_request(decoder->wg_parser, &data, &offset, &size))
|
||||
+ continue;
|
||||
+
|
||||
+ copy_size = min(size, buffer_size);
|
||||
+
|
||||
+ if (offset != decoder->offset_tracker)
|
||||
+ {
|
||||
+ ERR("A seek is needed, MFTs don't support this!\n");
|
||||
+ unix_funcs->wg_parser_complete_read_request(decoder->wg_parser, WG_READ_FAILURE, 0);
|
||||
+ IMFMediaBuffer_Unlock(buffer);
|
||||
+ hr = E_FAIL;
|
||||
+ goto done;
|
||||
+ }
|
||||
+
|
||||
+ memcpy(data, buffer_data, copy_size);
|
||||
+
|
||||
+ unix_funcs->wg_parser_complete_read_request(decoder->wg_parser, WG_READ_SUCCESS, buffer_size);
|
||||
+
|
||||
+ decoder->offset_tracker += copy_size;
|
||||
+
|
||||
+ if (buffer_size <= size)
|
||||
+ break;
|
||||
+
|
||||
+ buffer_data += copy_size;
|
||||
+ buffer_size -= copy_size;
|
||||
+
|
||||
+ WARN("Input sample split into multiple read requests\n");
|
||||
+ }
|
||||
+
|
||||
+ EnterCriticalSection(&decoder->event_cs);
|
||||
+ decoder->event.type = PIPELINE_EVENT_NONE;
|
||||
+ LeaveCriticalSection(&decoder->event_cs);
|
||||
+ WakeAllConditionVariable(&decoder->event_cv);
|
||||
+
|
||||
+ IMFMediaBuffer_Unlock(buffer);
|
||||
+
|
||||
+ done:
|
||||
+ if (buffer)
|
||||
+ IMFMediaBuffer_Release(buffer);
|
||||
+ LeaveCriticalSection(&decoder->cs);
|
||||
+ return hr;
|
||||
}
|
||||
|
||||
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);
|
||||
+ struct mf_decoder *decoder = impl_mf_decoder_from_IMFTransform(iface);
|
||||
+ MFT_OUTPUT_DATA_BUFFER *relevant_buffer = NULL;
|
||||
+ struct wg_parser_event event;
|
||||
+ struct pipeline_event pip_event;
|
||||
+ IMFMediaBuffer *buffer;
|
||||
+ DWORD buffer_len;
|
||||
+ unsigned int i;
|
||||
+ BYTE *data;
|
||||
+ HRESULT hr;
|
||||
|
||||
- return E_NOTIMPL;
|
||||
+ TRACE("%p, %#x, %u, %p, %p.\n", iface, flags, count, samples, status);
|
||||
+
|
||||
+ if (flags)
|
||||
+ WARN("Unsupported flags %#x\n", flags);
|
||||
+
|
||||
+ for (i = 0; i < count; i++)
|
||||
+ {
|
||||
+ MFT_OUTPUT_DATA_BUFFER *out_buffer = &samples[i];
|
||||
+
|
||||
+ if (out_buffer->dwStreamID != 0)
|
||||
+ return MF_E_INVALIDSTREAMNUMBER;
|
||||
+
|
||||
+ if (relevant_buffer)
|
||||
+ return MF_E_INVALIDSTREAMNUMBER;
|
||||
+
|
||||
+ relevant_buffer = out_buffer;
|
||||
+ }
|
||||
+
|
||||
+ if (!relevant_buffer)
|
||||
+ return S_OK;
|
||||
+
|
||||
+ EnterCriticalSection(&decoder->cs);
|
||||
+
|
||||
+ if (!decoder->input_type || !decoder->output_type)
|
||||
+ {
|
||||
+ LeaveCriticalSection(&decoder->cs);
|
||||
+ return MF_E_TRANSFORM_TYPE_NOT_SET;
|
||||
+ }
|
||||
+
|
||||
+ if (!decoder->wg_stream)
|
||||
+ {
|
||||
+ pip_event = get_pipeline_event(decoder);
|
||||
+
|
||||
+ switch (pip_event.type)
|
||||
+ {
|
||||
+ case PIPELINE_EVENT_PARSER_STARTED:
|
||||
+ decoder->wg_stream = pip_event.u.parser_started.stream;
|
||||
+ break;
|
||||
+ case PIPELINE_EVENT_READ_REQUEST:
|
||||
+ LeaveCriticalSection(&decoder->cs);
|
||||
+ return MF_E_TRANSFORM_NEED_MORE_INPUT;
|
||||
+ default:
|
||||
+ assert(0);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (unix_funcs->wg_parser_stream_drain(decoder->wg_stream))
|
||||
+ {
|
||||
+ /* this would be unexpected, as we should get the EOS-event when a drain command completes. */
|
||||
+ //assert (!decoder->draining);
|
||||
+
|
||||
+ LeaveCriticalSection(&decoder->cs);
|
||||
+ return MF_E_TRANSFORM_NEED_MORE_INPUT;
|
||||
+ }
|
||||
+
|
||||
+ for (;;)
|
||||
+ {
|
||||
+ if (!unix_funcs->wg_parser_stream_get_event(decoder->wg_stream, &event))
|
||||
+ {
|
||||
+ LeaveCriticalSection(&decoder->cs);
|
||||
+ return E_FAIL;
|
||||
+ }
|
||||
+
|
||||
+ if (event.type == WG_PARSER_EVENT_BUFFER)
|
||||
+ break;
|
||||
+
|
||||
+ if (event.type == WG_PARSER_EVENT_EOS)
|
||||
+ {
|
||||
+ if (!decoder->draining)
|
||||
+ {
|
||||
+ LeaveCriticalSection(&decoder->cs);
|
||||
+ WARN("Received EOS event while not draining\n");
|
||||
+ return E_FAIL;
|
||||
+ }
|
||||
+ decoder->draining = FALSE;
|
||||
+ LeaveCriticalSection(&decoder->cs);
|
||||
+ return MF_E_TRANSFORM_NEED_MORE_INPUT;
|
||||
+ }
|
||||
+
|
||||
+ assert(event.type != WG_PARSER_EVENT_NONE);
|
||||
+ }
|
||||
+
|
||||
+ if (relevant_buffer->pSample)
|
||||
+ {
|
||||
+ if (FAILED(hr = IMFSample_ConvertToContiguousBuffer(relevant_buffer->pSample, &buffer)))
|
||||
+ {
|
||||
+ ERR("Failed to get buffer from sample, hr %#x.\n", hr);
|
||||
+ LeaveCriticalSection(&decoder->cs);
|
||||
+ return hr;
|
||||
+ }
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ if (FAILED(hr = MFCreateMemoryBuffer(event.u.buffer.size, &buffer)))
|
||||
+ {
|
||||
+ ERR("Failed to create buffer, hr %#x.\n", hr);
|
||||
+ LeaveCriticalSection(&decoder->cs);
|
||||
+ return hr;
|
||||
+ }
|
||||
+
|
||||
+ if (FAILED(hr = MFCreateSample(&relevant_buffer->pSample)))
|
||||
+ {
|
||||
+ ERR("Failed to create sample, hr %#x.\n", hr);
|
||||
+ LeaveCriticalSection(&decoder->cs);
|
||||
+ IMFMediaBuffer_Release(buffer);
|
||||
+ return hr;
|
||||
+ }
|
||||
+
|
||||
+ if (FAILED(hr = IMFSample_AddBuffer(relevant_buffer->pSample, buffer)))
|
||||
+ {
|
||||
+ ERR("Failed to add buffer, hr %#x.\n", hr);
|
||||
+ goto out;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (FAILED(hr = IMFMediaBuffer_GetMaxLength(buffer, &buffer_len)))
|
||||
+ {
|
||||
+ ERR("Failed to get buffer size, hr %#x.\n", hr);
|
||||
+ goto out;
|
||||
+ }
|
||||
+
|
||||
+ if (buffer_len < event.u.buffer.size)
|
||||
+ {
|
||||
+ WARN("Client's buffer is smaller (%u bytes) than the output sample (%u bytes)\n",
|
||||
+ buffer_len, event.u.buffer.size);
|
||||
+
|
||||
+ if (FAILED(hr = IMFMediaBuffer_SetCurrentLength(buffer, buffer_len)))
|
||||
+ {
|
||||
+ ERR("Failed to set size, hr %#x.\n", hr);
|
||||
+ goto out;
|
||||
+ }
|
||||
+ }
|
||||
+ else if (FAILED(hr = IMFMediaBuffer_SetCurrentLength(buffer, event.u.buffer.size)))
|
||||
+ {
|
||||
+ ERR("Failed to set size, hr %#x.\n", hr);
|
||||
+ goto out;
|
||||
+ }
|
||||
+
|
||||
+
|
||||
+ if (FAILED(hr = IMFMediaBuffer_Lock(buffer, &data, NULL, NULL)))
|
||||
+ {
|
||||
+ ERR("Failed to lock buffer, hr %#x.\n", hr);
|
||||
+ goto out;
|
||||
+ }
|
||||
+
|
||||
+ if (!unix_funcs->wg_parser_stream_copy_buffer(decoder->wg_stream, data, 0, min(buffer_len, event.u.buffer.size)))
|
||||
+ {
|
||||
+ hr = E_FAIL;
|
||||
+ goto out;
|
||||
+ }
|
||||
+
|
||||
+ if (FAILED(hr = IMFMediaBuffer_Unlock(buffer)))
|
||||
+ {
|
||||
+ ERR("Failed to unlock buffer, hr %#x.\n", hr);
|
||||
+ goto out;
|
||||
+ }
|
||||
+
|
||||
+ if (FAILED(hr = IMFSample_SetSampleTime(relevant_buffer->pSample, event.u.buffer.pts)))
|
||||
+ {
|
||||
+ ERR("Failed to set sample time, hr %#x.\n", hr);
|
||||
+ goto out;
|
||||
+ }
|
||||
+
|
||||
+ if (FAILED(hr = IMFSample_SetSampleDuration(relevant_buffer->pSample, event.u.buffer.duration)))
|
||||
+ {
|
||||
+ ERR("Failed to set sample duration, hr %#x.\n", hr);
|
||||
+ goto out;
|
||||
+ }
|
||||
+
|
||||
+ relevant_buffer->dwStatus = 0;
|
||||
+ relevant_buffer->pEvents = NULL;
|
||||
+ *status = 0;
|
||||
+
|
||||
+ out:
|
||||
+ if (SUCCEEDED(hr))
|
||||
+ unix_funcs->wg_parser_stream_release_buffer(decoder->wg_stream);
|
||||
+ LeaveCriticalSection(&decoder->cs);
|
||||
+
|
||||
+ if (FAILED(hr))
|
||||
+ {
|
||||
+ IMFSample_Release(relevant_buffer->pSample);
|
||||
+ relevant_buffer->pSample = NULL;
|
||||
+ }
|
||||
+
|
||||
+ IMFMediaBuffer_Release(buffer);
|
||||
+
|
||||
+ return hr;
|
||||
}
|
||||
|
||||
static const IMFTransformVtbl mf_decoder_vtbl =
|
||||
@@ -560,6 +1064,7 @@ static const IMFTransformVtbl mf_decoder_vtbl =
|
||||
HRESULT decode_transform_create(REFIID riid, void **obj, enum decoder_type type)
|
||||
{
|
||||
struct mf_decoder *object;
|
||||
+ struct wg_parser *parser;
|
||||
|
||||
TRACE("%s, %p %u.\n", debugstr_guid(riid), obj, type);
|
||||
|
||||
@@ -573,6 +1078,21 @@ HRESULT decode_transform_create(REFIID riid, void **obj, enum decoder_type type)
|
||||
object->video = decoder_descs[type].major_type == &MFMediaType_Video;
|
||||
|
||||
InitializeCriticalSection(&object->cs);
|
||||
+ InitializeCriticalSection(&object->help_cs);
|
||||
+ InitializeCriticalSection(&object->event_cs);
|
||||
+ InitializeConditionVariable(&object->help_cv);
|
||||
+ InitializeConditionVariable(&object->event_cv);
|
||||
+
|
||||
+ object->helper_thread = CreateThread(NULL, 0, helper_thread_func, object, 0, NULL);
|
||||
+ object->read_thread = CreateThread(NULL, 0, read_thread_func, object, 0, NULL);
|
||||
+
|
||||
+ if (!(parser = unix_funcs->wg_decodebin_parser_create()))
|
||||
+ {
|
||||
+ ERR("Failed to create Decoder MFT type %u: Unspecified GStreamer error\n", type);
|
||||
+ IMFTransform_Release(&object->IMFTransform_iface);
|
||||
+ return E_OUTOFMEMORY;
|
||||
+ }
|
||||
+ object->wg_parser = parser;
|
||||
|
||||
*obj = &object->IMFTransform_iface;
|
||||
return S_OK;
|
||||
--
|
||||
2.30.2
|
||||
|
@ -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
|
||||
|
@ -1,99 +0,0 @@
|
||||
From 7bc3f13dd779e7b998a877012c83a8ca9e7aba4f Mon Sep 17 00:00:00 2001
|
||||
From: Derek Lesho <dlesho@codeweavers.com>
|
||||
Date: Thu, 3 Dec 2020 15:37:10 -0500
|
||||
Subject: [PATCH] winegstreamer: Implement Get*Attributes functions for color
|
||||
converter transform.
|
||||
|
||||
Signed-off-by: Derek Lesho <dlesho@codeweavers.com>
|
||||
---
|
||||
dlls/winegstreamer/colorconvert.c | 37 +++++++++++++++++++++++++++----
|
||||
1 file changed, 33 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/dlls/winegstreamer/colorconvert.c b/dlls/winegstreamer/colorconvert.c
|
||||
index 43b8dddeee7..9e6ece796f3 100644
|
||||
--- a/dlls/winegstreamer/colorconvert.c
|
||||
+++ b/dlls/winegstreamer/colorconvert.c
|
||||
@@ -52,6 +52,8 @@ struct color_converter
|
||||
{
|
||||
IMFTransform IMFTransform_iface;
|
||||
LONG refcount;
|
||||
+ IMFAttributes *attributes;
|
||||
+ IMFAttributes *output_attributes;
|
||||
IMFMediaType *input_type;
|
||||
IMFMediaType *output_type;
|
||||
CRITICAL_SECTION cs;
|
||||
@@ -102,6 +104,10 @@ static ULONG WINAPI color_converter_Release(IMFTransform *iface)
|
||||
{
|
||||
transform->cs.DebugInfo->Spare[0] = 0;
|
||||
DeleteCriticalSection(&transform->cs);
|
||||
+ if (transform->attributes)
|
||||
+ IMFAttributes_Release(transform->attributes);
|
||||
+ if (transform->output_attributes)
|
||||
+ IMFAttributes_Release(transform->output_attributes);
|
||||
gst_object_unref(transform->container);
|
||||
heap_free(transform);
|
||||
}
|
||||
@@ -167,9 +173,14 @@ static HRESULT WINAPI color_converter_GetOutputStreamInfo(IMFTransform *iface, D
|
||||
|
||||
static HRESULT WINAPI color_converter_GetAttributes(IMFTransform *iface, IMFAttributes **attributes)
|
||||
{
|
||||
- FIXME("%p, %p.\n", iface, attributes);
|
||||
+ struct color_converter *converter = impl_color_converter_from_IMFTransform(iface);
|
||||
|
||||
- return E_NOTIMPL;
|
||||
+ TRACE("%p, %p.\n", iface, attributes);
|
||||
+
|
||||
+ *attributes = converter->attributes;
|
||||
+ IMFAttributes_AddRef(*attributes);
|
||||
+
|
||||
+ return S_OK;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI color_converter_GetInputStreamAttributes(IMFTransform *iface, DWORD id,
|
||||
@@ -183,9 +194,14 @@ static HRESULT WINAPI color_converter_GetInputStreamAttributes(IMFTransform *ifa
|
||||
static HRESULT WINAPI color_converter_GetOutputStreamAttributes(IMFTransform *iface, DWORD id,
|
||||
IMFAttributes **attributes)
|
||||
{
|
||||
- FIXME("%p, %u, %p.\n", iface, id, attributes);
|
||||
+ struct color_converter *converter = impl_color_converter_from_IMFTransform(iface);
|
||||
|
||||
- return E_NOTIMPL;
|
||||
+ TRACE("%p, %u, %p.\n", iface, id, attributes);
|
||||
+
|
||||
+ *attributes = converter->output_attributes;
|
||||
+ IMFAttributes_AddRef(*attributes);
|
||||
+
|
||||
+ return S_OK;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI color_converter_DeleteInputStream(IMFTransform *iface, DWORD id)
|
||||
@@ -639,6 +655,7 @@ static const IMFTransformVtbl color_converter_vtbl =
|
||||
HRESULT color_converter_create(REFIID riid, void **ret)
|
||||
{
|
||||
struct color_converter *object;
|
||||
+ HRESULT hr;
|
||||
|
||||
TRACE("%s %p\n", debugstr_guid(riid), ret);
|
||||
|
||||
@@ -651,6 +668,18 @@ HRESULT color_converter_create(REFIID riid, void **ret)
|
||||
InitializeCriticalSection(&object->cs);
|
||||
object->cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": color_converter_lock");
|
||||
|
||||
+ if (FAILED(hr = MFCreateAttributes(&object->attributes, 0)))
|
||||
+ {
|
||||
+ IMFTransform_Release(&object->IMFTransform_iface);
|
||||
+ return hr;
|
||||
+ }
|
||||
+
|
||||
+ if (FAILED(hr = MFCreateAttributes(&object->output_attributes, 0)))
|
||||
+ {
|
||||
+ IMFTransform_Release(&object->IMFTransform_iface);
|
||||
+ return hr;
|
||||
+ }
|
||||
+
|
||||
object->container = gst_bin_new(NULL);
|
||||
|
||||
if (!(object->appsrc = gst_element_factory_make("appsrc", NULL)))
|
||||
--
|
||||
2.29.2
|
||||
|
@ -0,0 +1,45 @@
|
||||
From 86115ed0d28a1abb007b0eedf0442dbdf2e2127d Mon Sep 17 00:00:00 2001
|
||||
From: Derek Lesho <dlesho@codeweavers.com>
|
||||
Date: Fri, 19 Mar 2021 17:00:51 -0400
|
||||
Subject: [PATCH 16/39] winegstreamer: Rename GStreamer objects to be more
|
||||
generic.
|
||||
|
||||
Signed-off-by: Derek Lesho <dlesho@codeweavers.com>
|
||||
---
|
||||
dlls/winegstreamer/wg_parser.c | 6 +++---
|
||||
1 file changed, 3 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/dlls/winegstreamer/wg_parser.c b/dlls/winegstreamer/wg_parser.c
|
||||
index 2a982576ef5..44d0c9b71f3 100644
|
||||
--- a/dlls/winegstreamer/wg_parser.c
|
||||
+++ b/dlls/winegstreamer/wg_parser.c
|
||||
@@ -1242,7 +1242,7 @@ static struct wg_parser_stream *create_stream(struct wg_parser *parser)
|
||||
pthread_cond_init(&stream->event_cond, NULL);
|
||||
pthread_cond_init(&stream->event_empty_cond, NULL);
|
||||
|
||||
- sprintf(pad_name, "qz_sink_%u", parser->stream_count);
|
||||
+ sprintf(pad_name, "wine_sink_%u", parser->stream_count);
|
||||
stream->my_sink = gst_pad_new(pad_name, GST_PAD_SINK);
|
||||
gst_pad_set_element_private(stream->my_sink, stream);
|
||||
gst_pad_set_chain_function(stream->my_sink, sink_chain_cb);
|
||||
@@ -1948,7 +1948,7 @@ static LONGLONG query_duration(GstPad *pad)
|
||||
|
||||
static HRESULT wg_parser_connect_inner(struct wg_parser *parser)
|
||||
{
|
||||
- GstStaticPadTemplate src_template = GST_STATIC_PAD_TEMPLATE("quartz_src",
|
||||
+ GstStaticPadTemplate src_template = GST_STATIC_PAD_TEMPLATE("wine_src",
|
||||
GST_PAD_SRC, GST_PAD_ALWAYS, GST_STATIC_CAPS_ANY);
|
||||
|
||||
parser->sink_connected = true;
|
||||
@@ -1962,7 +1962,7 @@ static HRESULT wg_parser_connect_inner(struct wg_parser *parser)
|
||||
parser->container = gst_bin_new(NULL);
|
||||
gst_element_set_bus(parser->container, parser->bus);
|
||||
|
||||
- parser->my_src = gst_pad_new_from_static_template(&src_template, "quartz-src");
|
||||
+ parser->my_src = gst_pad_new_from_static_template(&src_template, "wine-src");
|
||||
gst_pad_set_getrange_function(parser->my_src, src_getrange_cb);
|
||||
gst_pad_set_query_function(parser->my_src, src_query_cb);
|
||||
gst_pad_set_activatemode_function(parser->my_src, src_activate_mode_cb);
|
||||
--
|
||||
2.30.2
|
||||
|
@ -1,89 +0,0 @@
|
||||
From 54919766d0ad2cf17e8cc6a8783794312964677c Mon Sep 17 00:00:00 2001
|
||||
From: Derek Lesho <dlesho@codeweavers.com>
|
||||
Date: Thu, 3 Dec 2020 15:43:21 -0500
|
||||
Subject: [PATCH] winegstreamer: Implement Get(Input/Output)CurrentType
|
||||
functions for color converter transform.
|
||||
|
||||
Signed-off-by: Derek Lesho <dlesho@codeweavers.com>
|
||||
---
|
||||
dlls/winegstreamer/colorconvert.c | 58 ++++++++++++++++++++++++++++---
|
||||
1 file changed, 54 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/dlls/winegstreamer/colorconvert.c b/dlls/winegstreamer/colorconvert.c
|
||||
index 9e6ece796f3..c7b1fae393f 100644
|
||||
--- a/dlls/winegstreamer/colorconvert.c
|
||||
+++ b/dlls/winegstreamer/colorconvert.c
|
||||
@@ -466,16 +466,66 @@ static HRESULT WINAPI color_converter_SetOutputType(IMFTransform *iface, DWORD i
|
||||
|
||||
static HRESULT WINAPI color_converter_GetInputCurrentType(IMFTransform *iface, DWORD id, IMFMediaType **type)
|
||||
{
|
||||
- FIXME("%p, %u, %p.\n", iface, id, type);
|
||||
+ IMFMediaType *ret;
|
||||
+ HRESULT hr;
|
||||
|
||||
- return E_NOTIMPL;
|
||||
+ struct color_converter *converter = impl_color_converter_from_IMFTransform(iface);
|
||||
+
|
||||
+ TRACE("%p, %u, %p.\n", converter, id, type);
|
||||
+
|
||||
+ if (id != 0)
|
||||
+ return MF_E_INVALIDSTREAMNUMBER;
|
||||
+
|
||||
+ if (FAILED(hr = MFCreateMediaType(&ret)))
|
||||
+ return hr;
|
||||
+
|
||||
+ EnterCriticalSection(&converter->cs);
|
||||
+
|
||||
+ if (converter->input_type)
|
||||
+ hr = IMFMediaType_CopyAllItems(converter->input_type, (IMFAttributes *)ret);
|
||||
+ else
|
||||
+ hr = MF_E_TRANSFORM_TYPE_NOT_SET;
|
||||
+
|
||||
+ LeaveCriticalSection(&converter->cs);
|
||||
+
|
||||
+ if (SUCCEEDED(hr))
|
||||
+ *type = ret;
|
||||
+ else
|
||||
+ IMFMediaType_Release(ret);
|
||||
+
|
||||
+ return hr;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI color_converter_GetOutputCurrentType(IMFTransform *iface, DWORD id, IMFMediaType **type)
|
||||
{
|
||||
- FIXME("%p, %u, %p.\n", iface, id, type);
|
||||
+ IMFMediaType *ret;
|
||||
+ HRESULT hr;
|
||||
|
||||
- return E_NOTIMPL;
|
||||
+ struct color_converter *converter = impl_color_converter_from_IMFTransform(iface);
|
||||
+
|
||||
+ TRACE("%p, %u, %p.\n", converter, id, type);
|
||||
+
|
||||
+ if (id != 0)
|
||||
+ return MF_E_INVALIDSTREAMNUMBER;
|
||||
+
|
||||
+ if (FAILED(hr = MFCreateMediaType(&ret)))
|
||||
+ return hr;
|
||||
+
|
||||
+ EnterCriticalSection(&converter->cs);
|
||||
+
|
||||
+ if (converter->output_type)
|
||||
+ hr = IMFMediaType_CopyAllItems(converter->output_type, (IMFAttributes *)ret);
|
||||
+ else
|
||||
+ hr = MF_E_TRANSFORM_TYPE_NOT_SET;
|
||||
+
|
||||
+ LeaveCriticalSection(&converter->cs);
|
||||
+
|
||||
+ if (SUCCEEDED(hr))
|
||||
+ *type = ret;
|
||||
+ else
|
||||
+ IMFMediaType_Release(ret);
|
||||
+
|
||||
+ return hr;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI color_converter_GetInputStatus(IMFTransform *iface, DWORD id, DWORD *flags)
|
||||
--
|
||||
2.29.2
|
||||
|
@ -0,0 +1,27 @@
|
||||
From 2451bb53540b32568e404f8ed2399b8b2a58e64d Mon Sep 17 00:00:00 2001
|
||||
From: Derek Lesho <dlesho@codeweavers.com>
|
||||
Date: Fri, 19 Mar 2021 17:01:54 -0400
|
||||
Subject: [PATCH 17/39] winegstreamer: Report streams backwards in media
|
||||
source.
|
||||
|
||||
Signed-off-by: Derek Lesho <dlesho@codeweavers.com>
|
||||
---
|
||||
dlls/winegstreamer/media_source.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/dlls/winegstreamer/media_source.c b/dlls/winegstreamer/media_source.c
|
||||
index f658cc0a5fc..b0c4220cc00 100644
|
||||
--- a/dlls/winegstreamer/media_source.c
|
||||
+++ b/dlls/winegstreamer/media_source.c
|
||||
@@ -1363,7 +1363,7 @@ static HRESULT media_source_constructor(IMFByteStream *bytestream, struct media_
|
||||
descriptors = malloc(object->stream_count * sizeof(IMFStreamDescriptor *));
|
||||
for (i = 0; i < object->stream_count; i++)
|
||||
{
|
||||
- IMFMediaStream_GetStreamDescriptor(&object->streams[i]->IMFMediaStream_iface, &descriptors[i]);
|
||||
+ IMFMediaStream_GetStreamDescriptor(&object->streams[i]->IMFMediaStream_iface, &descriptors[object->stream_count - 1 - i]);
|
||||
}
|
||||
|
||||
if (FAILED(hr = MFCreatePresentationDescriptor(object->stream_count, descriptors, &object->pres_desc)))
|
||||
--
|
||||
2.30.2
|
||||
|
@ -1,81 +0,0 @@
|
||||
From 1472041682ce09e0e8bdda78ed0366fba6aa41a0 Mon Sep 17 00:00:00 2001
|
||||
From: Derek Lesho <dlesho@codeweavers.com>
|
||||
Date: Thu, 7 May 2020 13:09:47 -0500
|
||||
Subject: [PATCH] winegstreamer: Implement IMFMediaSource::Stop.
|
||||
|
||||
Signed-off-by: Derek Lesho <dlesho@codeweavers.com>
|
||||
---
|
||||
dlls/winegstreamer/media_source.c | 31 +++++++++++++++++++++++++++++--
|
||||
1 file changed, 29 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/dlls/winegstreamer/media_source.c b/dlls/winegstreamer/media_source.c
|
||||
index 5c502cf3ed5..655e765fee7 100644
|
||||
--- a/dlls/winegstreamer/media_source.c
|
||||
+++ b/dlls/winegstreamer/media_source.c
|
||||
@@ -64,6 +64,7 @@ struct media_stream
|
||||
enum source_async_op
|
||||
{
|
||||
SOURCE_ASYNC_START,
|
||||
+ SOURCE_ASYNC_STOP,
|
||||
SOURCE_ASYNC_REQUEST_SAMPLE,
|
||||
};
|
||||
|
||||
@@ -343,6 +344,24 @@ static void start_pipeline(struct media_source *source, struct source_async_comm
|
||||
gst_element_set_state(source->container, GST_STATE_PLAYING);
|
||||
}
|
||||
|
||||
+static void stop_pipeline(struct media_source *source)
|
||||
+{
|
||||
+ unsigned int i;
|
||||
+
|
||||
+ gst_element_set_state(source->container, GST_STATE_PAUSED);
|
||||
+
|
||||
+ for (i = 0; i < source->stream_count; i++)
|
||||
+ {
|
||||
+ struct media_stream *stream = source->streams[i];
|
||||
+ if (stream->state != STREAM_INACTIVE)
|
||||
+ IMFMediaEventQueue_QueueEventParamVar(stream->event_queue, MEStreamStopped, &GUID_NULL, S_OK, NULL);
|
||||
+ }
|
||||
+
|
||||
+ IMFMediaEventQueue_QueueEventParamVar(source->event_queue, MESourceStopped, &GUID_NULL, S_OK, NULL);
|
||||
+
|
||||
+ source->state = SOURCE_STOPPED;
|
||||
+}
|
||||
+
|
||||
static void dispatch_end_of_presentation(struct media_source *source)
|
||||
{
|
||||
PROPVARIANT empty = {.vt = VT_EMPTY};
|
||||
@@ -417,6 +436,9 @@ static HRESULT WINAPI source_async_commands_Invoke(IMFAsyncCallback *iface, IMFA
|
||||
case SOURCE_ASYNC_START:
|
||||
start_pipeline(source, command);
|
||||
break;
|
||||
+ case SOURCE_ASYNC_STOP:
|
||||
+ stop_pipeline(source);
|
||||
+ break;
|
||||
case SOURCE_ASYNC_REQUEST_SAMPLE:
|
||||
wait_on_sample(command->u.request_sample.stream, command->u.request_sample.token);
|
||||
break;
|
||||
@@ -1087,13 +1109,18 @@ static HRESULT WINAPI media_source_Start(IMFMediaSource *iface, IMFPresentationD
|
||||
static HRESULT WINAPI media_source_Stop(IMFMediaSource *iface)
|
||||
{
|
||||
struct media_source *source = impl_from_IMFMediaSource(iface);
|
||||
+ struct source_async_command *command;
|
||||
+ HRESULT hr;
|
||||
|
||||
- FIXME("(%p): stub\n", source);
|
||||
+ TRACE("(%p)\n", source);
|
||||
|
||||
if (source->state == SOURCE_SHUTDOWN)
|
||||
return MF_E_SHUTDOWN;
|
||||
|
||||
- return E_NOTIMPL;
|
||||
+ if (SUCCEEDED(hr = source_create_async_op(SOURCE_ASYNC_STOP, &command)))
|
||||
+ hr = MFPutWorkItem(source->async_commands_queue, &source->async_commands_callback, &command->IUnknown_iface);
|
||||
+
|
||||
+ return hr;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI media_source_Pause(IMFMediaSource *iface)
|
||||
--
|
||||
2.29.2
|
||||
|
@ -0,0 +1,528 @@
|
||||
From 6f1c7d5735bc793ccfc059c22071ee546db0133a Mon Sep 17 00:00:00 2001
|
||||
From: Derek Lesho <dlesho@codeweavers.com>
|
||||
Date: Wed, 17 Mar 2021 14:07:52 -0400
|
||||
Subject: [PATCH 18/39] winegstreamer: Implement ::Process(Input/Output) for
|
||||
audio conversion transform.
|
||||
|
||||
Signed-off-by: Derek Lesho <dlesho@codeweavers.com>
|
||||
---
|
||||
dlls/winegstreamer/audioconvert.c | 280 +++++++++++++++++++++++++++++-
|
||||
dlls/winegstreamer/gst_private.h | 1 +
|
||||
dlls/winegstreamer/wg_parser.c | 93 ++++++++++
|
||||
3 files changed, 367 insertions(+), 7 deletions(-)
|
||||
|
||||
diff --git a/dlls/winegstreamer/audioconvert.c b/dlls/winegstreamer/audioconvert.c
|
||||
index 33350fb3566..8405f3bedc5 100644
|
||||
--- a/dlls/winegstreamer/audioconvert.c
|
||||
+++ b/dlls/winegstreamer/audioconvert.c
|
||||
@@ -35,6 +35,10 @@ struct audio_converter
|
||||
IMFMediaType *input_type;
|
||||
IMFMediaType *output_type;
|
||||
CRITICAL_SECTION cs;
|
||||
+ BOOL buffer_inflight;
|
||||
+ LONGLONG buffer_pts, buffer_dur;
|
||||
+ struct wg_parser *parser;
|
||||
+ struct wg_parser_stream *stream;
|
||||
};
|
||||
|
||||
static struct audio_converter *impl_audio_converter_from_IMFTransform(IMFTransform *iface)
|
||||
@@ -80,6 +84,10 @@ static ULONG WINAPI audio_converter_Release(IMFTransform *iface)
|
||||
{
|
||||
transform->cs.DebugInfo->Spare[0] = 0;
|
||||
DeleteCriticalSection(&transform->cs);
|
||||
+ if (transform->stream)
|
||||
+ unix_funcs->wg_parser_disconnect(transform->parser);
|
||||
+ if (transform->parser)
|
||||
+ unix_funcs->wg_parser_destroy(transform->parser);
|
||||
free(transform);
|
||||
}
|
||||
|
||||
@@ -272,6 +280,7 @@ fail:
|
||||
static HRESULT WINAPI audio_converter_SetInputType(IMFTransform *iface, DWORD id, IMFMediaType *type, DWORD flags)
|
||||
{
|
||||
GUID major_type, subtype;
|
||||
+ struct wg_format format;
|
||||
DWORD unused;
|
||||
HRESULT hr;
|
||||
|
||||
@@ -291,6 +300,11 @@ static HRESULT WINAPI audio_converter_SetInputType(IMFTransform *iface, DWORD id
|
||||
|
||||
if (converter->input_type)
|
||||
{
|
||||
+ if (converter->stream)
|
||||
+ {
|
||||
+ unix_funcs->wg_parser_disconnect(converter->parser);
|
||||
+ converter->stream = NULL;
|
||||
+ }
|
||||
IMFMediaType_Release(converter->input_type);
|
||||
converter->input_type = NULL;
|
||||
}
|
||||
@@ -317,6 +331,10 @@ static HRESULT WINAPI audio_converter_SetInputType(IMFTransform *iface, DWORD id
|
||||
if (!IsEqualGUID(&subtype, &MFAudioFormat_PCM) && !IsEqualGUID(&subtype, &MFAudioFormat_Float))
|
||||
return MF_E_INVALIDTYPE;
|
||||
|
||||
+ mf_media_type_to_wg_format(type, &format);
|
||||
+ if (!format.major_type)
|
||||
+ return MF_E_INVALIDTYPE;
|
||||
+
|
||||
if (flags & MFT_SET_TYPE_TEST_ONLY)
|
||||
return S_OK;
|
||||
|
||||
@@ -336,6 +354,21 @@ static HRESULT WINAPI audio_converter_SetInputType(IMFTransform *iface, DWORD id
|
||||
converter->input_type = NULL;
|
||||
}
|
||||
|
||||
+ if (converter->stream)
|
||||
+ {
|
||||
+ unix_funcs->wg_parser_disconnect(converter->parser);
|
||||
+ converter->stream = NULL;
|
||||
+ }
|
||||
+
|
||||
+ if (converter->input_type && converter->output_type)
|
||||
+ {
|
||||
+ struct wg_format output_format;
|
||||
+ mf_media_type_to_wg_format(converter->output_type, &output_format);
|
||||
+
|
||||
+ if (SUCCEEDED(hr = unix_funcs->wg_parser_connect_unseekable(converter->parser, &format, 1, &output_format, NULL)))
|
||||
+ converter->stream = unix_funcs->wg_parser_get_stream(converter->parser, 0);
|
||||
+ }
|
||||
+
|
||||
LeaveCriticalSection(&converter->cs);
|
||||
|
||||
return hr;
|
||||
@@ -345,6 +378,7 @@ static HRESULT WINAPI audio_converter_SetOutputType(IMFTransform *iface, DWORD i
|
||||
{
|
||||
struct audio_converter *converter = impl_audio_converter_from_IMFTransform(iface);
|
||||
GUID major_type, subtype;
|
||||
+ struct wg_format format;
|
||||
DWORD unused;
|
||||
HRESULT hr;
|
||||
|
||||
@@ -353,9 +387,6 @@ static HRESULT WINAPI audio_converter_SetOutputType(IMFTransform *iface, DWORD i
|
||||
if (id != 0)
|
||||
return MF_E_INVALIDSTREAMNUMBER;
|
||||
|
||||
- if (!converter->input_type)
|
||||
- return MF_E_TRANSFORM_TYPE_NOT_SET;
|
||||
-
|
||||
if (!type)
|
||||
{
|
||||
if (flags & MFT_SET_TYPE_TEST_ONLY)
|
||||
@@ -365,6 +396,11 @@ static HRESULT WINAPI audio_converter_SetOutputType(IMFTransform *iface, DWORD i
|
||||
|
||||
if (converter->output_type)
|
||||
{
|
||||
+ if (converter->stream)
|
||||
+ {
|
||||
+ unix_funcs->wg_parser_disconnect(converter->parser);
|
||||
+ converter->stream = NULL;
|
||||
+ }
|
||||
IMFMediaType_Release(converter->output_type);
|
||||
converter->output_type = NULL;
|
||||
}
|
||||
@@ -391,6 +427,10 @@ static HRESULT WINAPI audio_converter_SetOutputType(IMFTransform *iface, DWORD i
|
||||
if (!IsEqualGUID(&subtype, &MFAudioFormat_PCM) && !IsEqualGUID(&subtype, &MFAudioFormat_Float))
|
||||
return MF_E_INVALIDTYPE;
|
||||
|
||||
+ mf_media_type_to_wg_format(type, &format);
|
||||
+ if (!format.major_type)
|
||||
+ return MF_E_INVALIDTYPE;
|
||||
+
|
||||
if (flags & MFT_SET_TYPE_TEST_ONLY)
|
||||
return S_OK;
|
||||
|
||||
@@ -410,6 +450,21 @@ static HRESULT WINAPI audio_converter_SetOutputType(IMFTransform *iface, DWORD i
|
||||
converter->output_type = NULL;
|
||||
}
|
||||
|
||||
+ if (converter->stream)
|
||||
+ {
|
||||
+ unix_funcs->wg_parser_disconnect(converter->parser);
|
||||
+ converter->stream = NULL;
|
||||
+ }
|
||||
+
|
||||
+ if (converter->input_type && converter->output_type)
|
||||
+ {
|
||||
+ struct wg_format input_format;
|
||||
+ mf_media_type_to_wg_format(converter->input_type, &input_format);
|
||||
+
|
||||
+ if (SUCCEEDED(hr = unix_funcs->wg_parser_connect_unseekable(converter->parser, &input_format, 1, &format, NULL)))
|
||||
+ converter->stream = unix_funcs->wg_parser_get_stream(converter->parser, 0);
|
||||
+ }
|
||||
+
|
||||
LeaveCriticalSection(&converter->cs);
|
||||
|
||||
return hr;
|
||||
@@ -521,17 +576,221 @@ 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);
|
||||
+ struct audio_converter *converter = impl_audio_converter_from_IMFTransform(iface);
|
||||
+ IMFMediaBuffer *buffer = NULL;
|
||||
+ unsigned char *buffer_data;
|
||||
+ DWORD buffer_size;
|
||||
+ uint64_t offset;
|
||||
+ uint32_t size;
|
||||
+ void *data;
|
||||
+ HRESULT hr;
|
||||
|
||||
- return E_NOTIMPL;
|
||||
+ 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->stream)
|
||||
+ {
|
||||
+ hr = MF_E_TRANSFORM_TYPE_NOT_SET;
|
||||
+ goto done;
|
||||
+ }
|
||||
+
|
||||
+ if (converter->buffer_inflight)
|
||||
+ {
|
||||
+ hr = MF_E_NOTACCEPTING;
|
||||
+ goto done;
|
||||
+ }
|
||||
+
|
||||
+ if (FAILED(hr = IMFSample_ConvertToContiguousBuffer(sample, &buffer)))
|
||||
+ goto done;
|
||||
+
|
||||
+ if (FAILED(hr = IMFMediaBuffer_Lock(buffer, &buffer_data, NULL, &buffer_size)))
|
||||
+ goto done;
|
||||
+
|
||||
+ for (;;)
|
||||
+ {
|
||||
+ if (!unix_funcs->wg_parser_get_read_request(converter->parser, &data, &offset, &size))
|
||||
+ continue;
|
||||
+
|
||||
+ memcpy(data, buffer_data, min(buffer_size, size));
|
||||
+
|
||||
+ unix_funcs->wg_parser_complete_read_request(converter->parser, WG_READ_SUCCESS, buffer_size);
|
||||
+
|
||||
+ if (buffer_size <= size)
|
||||
+ break;
|
||||
+
|
||||
+ buffer_data += size;
|
||||
+ buffer_size -= size;
|
||||
+ }
|
||||
+
|
||||
+ IMFMediaBuffer_Unlock(buffer);
|
||||
+ converter->buffer_inflight = TRUE;
|
||||
+ if (FAILED(IMFSample_GetSampleTime(sample, &converter->buffer_pts)))
|
||||
+ converter->buffer_pts = -1;
|
||||
+ if (FAILED(IMFSample_GetSampleDuration(sample, &converter->buffer_dur)))
|
||||
+ converter->buffer_dur = -1;
|
||||
+
|
||||
+done:
|
||||
+ if (buffer)
|
||||
+ IMFMediaBuffer_Release(buffer);
|
||||
+ LeaveCriticalSection(&converter->cs);
|
||||
+ return hr;
|
||||
}
|
||||
|
||||
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);
|
||||
+ struct audio_converter *converter = impl_audio_converter_from_IMFTransform(iface);
|
||||
+ IMFSample *allocated_sample = NULL;
|
||||
+ IMFMediaBuffer *buffer = NULL;
|
||||
+ struct wg_parser_event event;
|
||||
+ unsigned char *buffer_data;
|
||||
+ DWORD buffer_len;
|
||||
+ HRESULT hr = S_OK;
|
||||
|
||||
- return E_NOTIMPL;
|
||||
+ 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->stream)
|
||||
+ {
|
||||
+ hr = MF_E_TRANSFORM_TYPE_NOT_SET;
|
||||
+ goto done;
|
||||
+ }
|
||||
+
|
||||
+ if (!converter->buffer_inflight)
|
||||
+ {
|
||||
+ hr = MF_E_TRANSFORM_NEED_MORE_INPUT;
|
||||
+ goto done;
|
||||
+ }
|
||||
+
|
||||
+ for (;;)
|
||||
+ {
|
||||
+ unix_funcs->wg_parser_stream_get_event(converter->stream, &event);
|
||||
+
|
||||
+ switch (event.type)
|
||||
+ {
|
||||
+ case WG_PARSER_EVENT_BUFFER:
|
||||
+ break;
|
||||
+
|
||||
+ case WG_PARSER_EVENT_SEGMENT:
|
||||
+ continue;
|
||||
+
|
||||
+ default:
|
||||
+ WARN("Unexpected event, %u\n", event.type);
|
||||
+ continue;
|
||||
+ }
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ if (!samples[0].pSample)
|
||||
+ {
|
||||
+ if (FAILED(hr = MFCreateMemoryBuffer(event.u.buffer.size, &buffer)))
|
||||
+ {
|
||||
+ ERR("Failed to create buffer, hr %#x.\n", hr);
|
||||
+ goto done;
|
||||
+ }
|
||||
+
|
||||
+ if (FAILED(hr = MFCreateSample(&allocated_sample)))
|
||||
+ {
|
||||
+ ERR("Failed to create sample, hr %#x.\n", hr);
|
||||
+ goto done;
|
||||
+ }
|
||||
+
|
||||
+ samples[0].pSample = allocated_sample;
|
||||
+
|
||||
+ if (FAILED(hr = IMFSample_AddBuffer(samples[0].pSample, buffer)))
|
||||
+ {
|
||||
+ ERR("Failed to add buffer, hr %#x.\n", hr);
|
||||
+ goto done;
|
||||
+ }
|
||||
+
|
||||
+ IMFMediaBuffer_Release(buffer);
|
||||
+ buffer = NULL;
|
||||
+ }
|
||||
+
|
||||
+ if (FAILED(hr = IMFSample_ConvertToContiguousBuffer(samples[0].pSample, &buffer)))
|
||||
+ {
|
||||
+ ERR("Failed to get buffer from sample, hr %#x.\n", hr);
|
||||
+ goto done;
|
||||
+ }
|
||||
+
|
||||
+ if (FAILED(hr = IMFMediaBuffer_GetMaxLength(buffer, &buffer_len)))
|
||||
+ {
|
||||
+ ERR("Failed to get buffer size, hr %#x.\n", hr);
|
||||
+ goto done;
|
||||
+ }
|
||||
+
|
||||
+ if (buffer_len < event.u.buffer.size)
|
||||
+ {
|
||||
+ WARN("Client's buffer is smaller (%u bytes) than the output sample (%u bytes)\n",
|
||||
+ buffer_len, event.u.buffer.size);
|
||||
+
|
||||
+ hr = MF_E_BUFFERTOOSMALL;
|
||||
+ goto done;
|
||||
+ }
|
||||
+
|
||||
+ if (FAILED(hr = IMFMediaBuffer_SetCurrentLength(buffer, event.u.buffer.size)))
|
||||
+ {
|
||||
+ ERR("Failed to set size, hr %#x.\n", hr);
|
||||
+ goto done;
|
||||
+ }
|
||||
+
|
||||
+ if (FAILED(hr = IMFMediaBuffer_Lock(buffer, &buffer_data, NULL, NULL)))
|
||||
+ {
|
||||
+ ERR("Failed to lock buffer hr %#x.\n", hr);
|
||||
+ goto done;
|
||||
+ }
|
||||
+
|
||||
+ if (!unix_funcs->wg_parser_stream_copy_buffer(converter->stream, buffer_data, 0, event.u.buffer.size))
|
||||
+ {
|
||||
+ ERR("Failed to copy buffer.\n");
|
||||
+ IMFMediaBuffer_Unlock(buffer);
|
||||
+ hr = E_FAIL;
|
||||
+ goto done;
|
||||
+ }
|
||||
+
|
||||
+ IMFMediaBuffer_Unlock(buffer);
|
||||
+
|
||||
+ unix_funcs->wg_parser_stream_release_buffer(converter->stream);
|
||||
+ converter->buffer_inflight = FALSE;
|
||||
+
|
||||
+ if (converter->buffer_pts != -1)
|
||||
+ IMFSample_SetSampleTime(samples[0].pSample, converter->buffer_pts);
|
||||
+ if (converter->buffer_dur != -1)
|
||||
+ IMFSample_SetSampleDuration(samples[0].pSample, converter->buffer_dur);
|
||||
+
|
||||
+ samples[0].dwStatus = 0;
|
||||
+ samples[0].pEvents = NULL;
|
||||
+
|
||||
+ done:
|
||||
+ if (buffer)
|
||||
+ IMFMediaBuffer_Release(buffer);
|
||||
+ if (allocated_sample && FAILED(hr))
|
||||
+ {
|
||||
+ IMFSample_Release(allocated_sample);
|
||||
+ samples[0].pSample = NULL;
|
||||
+ }
|
||||
+ LeaveCriticalSection(&converter->cs);
|
||||
+ return hr;
|
||||
}
|
||||
|
||||
static const IMFTransformVtbl audio_converter_vtbl =
|
||||
@@ -579,6 +838,13 @@ HRESULT audio_converter_create(REFIID riid, void **ret)
|
||||
InitializeCriticalSection(&object->cs);
|
||||
object->cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": audio_converter_lock");
|
||||
|
||||
+ if (!(object->parser = unix_funcs->wg_raw_media_converter_create()))
|
||||
+ {
|
||||
+ ERR("Failed to create audio converter due to GStreamer error.\n");
|
||||
+ IMFTransform_Release(&object->IMFTransform_iface);
|
||||
+ return E_OUTOFMEMORY;
|
||||
+ }
|
||||
+
|
||||
*ret = &object->IMFTransform_iface;
|
||||
return S_OK;
|
||||
}
|
||||
diff --git a/dlls/winegstreamer/gst_private.h b/dlls/winegstreamer/gst_private.h
|
||||
index 6407aff484c..ee6d19e74b6 100644
|
||||
--- a/dlls/winegstreamer/gst_private.h
|
||||
+++ b/dlls/winegstreamer/gst_private.h
|
||||
@@ -203,6 +203,7 @@ struct unix_funcs
|
||||
struct wg_parser *(CDECL *wg_avi_parser_create)(void);
|
||||
struct wg_parser *(CDECL *wg_mpeg_audio_parser_create)(void);
|
||||
struct wg_parser *(CDECL *wg_wave_parser_create)(void);
|
||||
+ struct wg_parser *(CDECL *wg_raw_media_converter_create)(void);
|
||||
void (CDECL *wg_parser_destroy)(struct wg_parser *parser);
|
||||
|
||||
HRESULT (CDECL *wg_parser_connect)(struct wg_parser *parser, uint64_t file_size);
|
||||
diff --git a/dlls/winegstreamer/wg_parser.c b/dlls/winegstreamer/wg_parser.c
|
||||
index 44d0c9b71f3..6f4dd28082b 100644
|
||||
--- a/dlls/winegstreamer/wg_parser.c
|
||||
+++ b/dlls/winegstreamer/wg_parser.c
|
||||
@@ -2328,6 +2328,89 @@ static BOOL wave_parser_init_gst(struct wg_parser *parser)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
+static BOOL raw_media_converter_init_gst(struct wg_parser *parser)
|
||||
+{
|
||||
+ BOOL video = parser->input_format.major_type == WG_MAJOR_TYPE_VIDEO;
|
||||
+ struct wg_parser_stream *stream;
|
||||
+ GstElement *convert, *resampler;
|
||||
+ GstPad *their_src;
|
||||
+ int ret;
|
||||
+
|
||||
+ if (parser->seekable)
|
||||
+ return FALSE;
|
||||
+
|
||||
+ if (parser->expected_stream_count != 1)
|
||||
+ return FALSE;
|
||||
+
|
||||
+ if (video)
|
||||
+ {
|
||||
+ if (!(convert = gst_element_factory_make("videoconvert", NULL)))
|
||||
+ {
|
||||
+ ERR("Failed to create videoconvert; are %u-bit GStreamer \"base\" plugins installed?\n",
|
||||
+ 8 * (int)sizeof(void*));
|
||||
+ return FALSE;
|
||||
+ }
|
||||
+
|
||||
+ gst_bin_add(GST_BIN(parser->container), convert);
|
||||
+
|
||||
+ parser->their_sink = gst_element_get_static_pad(convert, "sink");
|
||||
+ their_src = gst_element_get_static_pad(convert, "src");
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ if (!(convert = gst_element_factory_make("audioconvert", NULL)))
|
||||
+ {
|
||||
+ ERR("Failed to create audioconvert; are %u-bit GStreamer \"base\" plugins installed?\n",
|
||||
+ 8 * (int)sizeof(void*));
|
||||
+ return FALSE;
|
||||
+ }
|
||||
+
|
||||
+ gst_bin_add(GST_BIN(parser->container), convert);
|
||||
+
|
||||
+ 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*));
|
||||
+ return FALSE;
|
||||
+ }
|
||||
+
|
||||
+ gst_bin_add(GST_BIN(parser->container), resampler);
|
||||
+
|
||||
+ gst_element_link(convert, resampler);
|
||||
+ parser->their_sink = gst_element_get_static_pad(convert, "sink");
|
||||
+ their_src = gst_element_get_static_pad(resampler, "src");
|
||||
+ }
|
||||
+
|
||||
+ if ((ret = gst_pad_link(parser->my_src, parser->their_sink)) < 0)
|
||||
+ {
|
||||
+ ERR("Failed to link sink pads, error %d.\n", ret);
|
||||
+ return FALSE;
|
||||
+ }
|
||||
+
|
||||
+ if (!(stream = create_stream(parser)))
|
||||
+ return FALSE;
|
||||
+
|
||||
+ stream->their_src = their_src;
|
||||
+ gst_object_ref(stream->their_src);
|
||||
+ if ((ret = gst_pad_link(stream->their_src, stream->my_sink)) < 0)
|
||||
+ {
|
||||
+ ERR("Failed to link source pads, error %d.\n", ret);
|
||||
+ return FALSE;
|
||||
+ }
|
||||
+
|
||||
+ gst_pad_set_active(stream->my_sink, 1);
|
||||
+ gst_element_set_state(parser->container, GST_STATE_PAUSED);
|
||||
+ gst_pad_set_active(parser->my_src, 1);
|
||||
+ ret = gst_element_get_state(parser->container, NULL, NULL, -1);
|
||||
+ if (ret == GST_STATE_CHANGE_FAILURE)
|
||||
+ {
|
||||
+ ERR("Failed to play stream.\n");
|
||||
+ return FALSE;
|
||||
+ }
|
||||
+
|
||||
+ return TRUE;
|
||||
+}
|
||||
+
|
||||
static struct wg_parser *wg_parser_create(void)
|
||||
{
|
||||
struct wg_parser *parser;
|
||||
@@ -2381,6 +2464,15 @@ static struct wg_parser * CDECL wg_wave_parser_create(void)
|
||||
return parser;
|
||||
}
|
||||
|
||||
+static struct wg_parser * CDECL wg_raw_media_converter_create(void)
|
||||
+{
|
||||
+ struct wg_parser *parser;
|
||||
+
|
||||
+ if ((parser = wg_parser_create()))
|
||||
+ parser->init_gst = raw_media_converter_init_gst;
|
||||
+ return parser;
|
||||
+}
|
||||
+
|
||||
static void CDECL wg_parser_destroy(struct wg_parser *parser)
|
||||
{
|
||||
if (parser->bus)
|
||||
@@ -2403,6 +2495,7 @@ static const struct unix_funcs funcs =
|
||||
wg_avi_parser_create,
|
||||
wg_mpeg_audio_parser_create,
|
||||
wg_wave_parser_create,
|
||||
+ wg_raw_media_converter_create,
|
||||
wg_parser_destroy,
|
||||
|
||||
wg_parser_connect,
|
||||
--
|
||||
2.30.2
|
||||
|
@ -1,26 +1,28 @@
|
||||
From 13e0d5671caaeae69bde747e547a5bd4524dd2ff Mon Sep 17 00:00:00 2001
|
||||
From b3906f3a8faa32710b99a80e374bca70087c5c19 Mon Sep 17 00:00:00 2001
|
||||
From: Derek Lesho <dlesho@codeweavers.com>
|
||||
Date: Wed, 18 Nov 2020 14:32:27 -0600
|
||||
Subject: [PATCH] winegstreamer: Implement ::Get(Input/Output)StreamInfo for
|
||||
audio conversion transform.
|
||||
Date: Wed, 17 Mar 2021 15:12:20 -0400
|
||||
Subject: [PATCH 19/39] winegstreamer: Implement ::Get(Input/Output)StreamInfo
|
||||
for audio conversion transform.
|
||||
|
||||
Signed-off-by: Derek Lesho <dlesho@codeweavers.com>
|
||||
---
|
||||
dlls/winegstreamer/audioconvert.c | 23 +++++++++++++++++++----
|
||||
1 file changed, 19 insertions(+), 4 deletions(-)
|
||||
dlls/winegstreamer/audioconvert.c | 42 ++++++++++++++++++++++++++++---
|
||||
1 file changed, 38 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/dlls/winegstreamer/audioconvert.c b/dlls/winegstreamer/audioconvert.c
|
||||
index 631c57d6d55..d204d9582ba 100644
|
||||
index 8405f3bedc5..4ad64d58e47 100644
|
||||
--- a/dlls/winegstreamer/audioconvert.c
|
||||
+++ b/dlls/winegstreamer/audioconvert.c
|
||||
@@ -123,16 +123,31 @@ static HRESULT WINAPI audio_converter_GetStreamIDs(IMFTransform *iface, DWORD in
|
||||
@@ -123,16 +123,50 @@ static HRESULT WINAPI audio_converter_GetStreamIDs(IMFTransform *iface, DWORD in
|
||||
|
||||
static HRESULT WINAPI audio_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);
|
||||
+ struct audio_converter *converter = impl_audio_converter_from_IMFTransform(iface);
|
||||
|
||||
- return E_NOTIMPL;
|
||||
+ TRACE("%p %u %p.\n", iface, id, info);
|
||||
+
|
||||
+ if (id != 0)
|
||||
+ return MF_E_INVALIDSTREAMNUMBER;
|
||||
+
|
||||
@ -28,6 +30,14 @@ index 631c57d6d55..d204d9582ba 100644
|
||||
+ info->cbMaxLookahead = 0;
|
||||
+ info->cbAlignment = 0;
|
||||
+ info->hnsMaxLatency = 0;
|
||||
+ info->cbSize = 0;
|
||||
+
|
||||
+ EnterCriticalSection(&converter->cs);
|
||||
+
|
||||
+ if (converter->input_type)
|
||||
+ IMFMediaType_GetUINT32(converter->input_type, &MF_MT_AUDIO_BLOCK_ALIGNMENT, &info->cbSize);
|
||||
+
|
||||
+ LeaveCriticalSection(&converter->cs);
|
||||
+
|
||||
+ return S_OK;
|
||||
}
|
||||
@ -35,20 +45,29 @@ index 631c57d6d55..d204d9582ba 100644
|
||||
static HRESULT WINAPI audio_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);
|
||||
+ struct audio_converter *converter = impl_audio_converter_from_IMFTransform(iface);
|
||||
|
||||
- return E_NOTIMPL;
|
||||
+ TRACE("%p %u %p.\n", iface, id, info);
|
||||
+
|
||||
+ if (id != 0)
|
||||
+ return MF_E_INVALIDSTREAMNUMBER;
|
||||
+
|
||||
+ info->dwFlags = MFT_OUTPUT_STREAM_PROVIDES_SAMPLES;
|
||||
+ info->cbSize = 0;
|
||||
+ info->dwFlags = MFT_OUTPUT_STREAM_CAN_PROVIDE_SAMPLES | MFT_OUTPUT_STREAM_WHOLE_SAMPLES;
|
||||
+ info->cbAlignment = 0;
|
||||
+ info->cbSize = 0;
|
||||
+
|
||||
+ EnterCriticalSection(&converter->cs);
|
||||
+
|
||||
+ if (converter->output_type)
|
||||
+ IMFMediaType_GetUINT32(converter->output_type, &MF_MT_AUDIO_BLOCK_ALIGNMENT, &info->cbSize);
|
||||
+
|
||||
+ LeaveCriticalSection(&converter->cs);
|
||||
+
|
||||
+ return S_OK;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI audio_converter_GetAttributes(IMFTransform *iface, IMFAttributes **attributes)
|
||||
--
|
||||
2.29.2
|
||||
2.30.2
|
||||
|
@ -1,54 +0,0 @@
|
||||
From 539f0ad63d83dd1f60a9a54063f3cb108d71f794 Mon Sep 17 00:00:00 2001
|
||||
From: Derek Lesho <dlesho@codeweavers.com>
|
||||
Date: Mon, 30 Nov 2020 11:56:48 -0500
|
||||
Subject: [PATCH] mf: Add invalid connect method test.
|
||||
|
||||
Nikolay stripped out this test in his updated version of the patchset, which is fine. But I think it's useful to have it somewhere.
|
||||
|
||||
Signed-off-by: Derek Lesho <dlesho@codeweavers.com>
|
||||
---
|
||||
dlls/mf/tests/mf.c | 28 ++++++++++++++++++++++++++++
|
||||
1 file changed, 28 insertions(+)
|
||||
|
||||
diff --git a/dlls/mf/tests/mf.c b/dlls/mf/tests/mf.c
|
||||
index 8272064466f..32ae84b837b 100644
|
||||
--- a/dlls/mf/tests/mf.c
|
||||
+++ b/dlls/mf/tests/mf.c
|
||||
@@ -1824,6 +1824,34 @@ static void test_topology_loader(void)
|
||||
LOADER_TODO,
|
||||
},
|
||||
|
||||
+ {
|
||||
+ /* MP3 -> PCM */
|
||||
+ &MFMediaType_Audio,
|
||||
+ {
|
||||
+ {
|
||||
+ { &MF_MT_SUBTYPE, WAVE_FORMAT_MPEGLAYER3 },
|
||||
+ { &MF_MT_AUDIO_NUM_CHANNELS, 2 },
|
||||
+ { &MF_MT_AUDIO_SAMPLES_PER_SECOND, 44100 },
|
||||
+ { &MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 16000 },
|
||||
+ { &MF_MT_AUDIO_BLOCK_ALIGNMENT, 1 },
|
||||
+ }
|
||||
+ },
|
||||
+ {
|
||||
+ {
|
||||
+ { &MF_MT_SUBTYPE, WAVE_FORMAT_PCM },
|
||||
+ { &MF_MT_AUDIO_NUM_CHANNELS, 1 },
|
||||
+ { &MF_MT_AUDIO_SAMPLES_PER_SECOND, 44100 },
|
||||
+ { &MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 44100 },
|
||||
+ { &MF_MT_AUDIO_BLOCK_ALIGNMENT, 1 },
|
||||
+ { &MF_MT_AUDIO_BITS_PER_SAMPLE, 8 },
|
||||
+ }
|
||||
+ },
|
||||
+
|
||||
+ MF_CONNECT_ALLOW_DECODER &~ MF_CONNECT_ALLOW_CONVERTER,
|
||||
+ MF_E_INVALIDMEDIATYPE,
|
||||
+ LOADER_TODO,
|
||||
+ },
|
||||
+
|
||||
{
|
||||
/* MP3 -> PCM */
|
||||
&MFMediaType_Audio,
|
||||
--
|
||||
2.29.2
|
||||
|
@ -1,29 +1,27 @@
|
||||
From a7ae40f14dc926f02fca792b11b7374550dbd7ef Mon Sep 17 00:00:00 2001
|
||||
From: Derek Lesho <dlesho@codeweavers.com>
|
||||
Subject: [PATCH resend 5/5] winegstreamer: Semi-stub Get*Attributes functions for audio converter transform.
|
||||
Message-Id: <20210118193047.267366-5-dlesho@codeweavers.com>
|
||||
Date: Mon, 18 Jan 2021 14:30:47 -0500
|
||||
In-Reply-To: <20210118193047.267366-1-dlesho@codeweavers.com>
|
||||
References: <20210118193047.267366-1-dlesho@codeweavers.com>
|
||||
Date: Wed, 17 Mar 2021 15:19:32 -0400
|
||||
Subject: [PATCH 20/39] winegstreamer: Semi-stub Get*Attributes functions for
|
||||
audio converter transform.
|
||||
|
||||
Signed-off-by: Derek Lesho <dlesho@codeweavers.com>
|
||||
---
|
||||
dlls/winegstreamer/audioconvert.c | 37 +++++++++++++++++++++++++++----
|
||||
1 file changed, 33 insertions(+), 4 deletions(-)
|
||||
dlls/winegstreamer/audioconvert.c | 39 +++++++++++++++++++++++++++----
|
||||
1 file changed, 35 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/dlls/winegstreamer/audioconvert.c b/dlls/winegstreamer/audioconvert.c
|
||||
index a95fc5506e7..2a5f87fec94 100644
|
||||
index 4ad64d58e47..43fe8b04e64 100644
|
||||
--- a/dlls/winegstreamer/audioconvert.c
|
||||
+++ b/dlls/winegstreamer/audioconvert.c
|
||||
@@ -37,6 +37,8 @@ struct audio_converter
|
||||
{
|
||||
IMFTransform IMFTransform_iface;
|
||||
LONG refcount;
|
||||
+ IMFAttributes *attributes;
|
||||
+ IMFAttributes *output_attributes;
|
||||
IMFMediaType *input_type;
|
||||
IMFMediaType *output_type;
|
||||
CRITICAL_SECTION cs;
|
||||
@@ -87,6 +89,10 @@ static ULONG WINAPI audio_converter_Release(IMFTransform *iface)
|
||||
@@ -39,6 +39,7 @@ struct audio_converter
|
||||
LONGLONG buffer_pts, buffer_dur;
|
||||
struct wg_parser *parser;
|
||||
struct wg_parser_stream *stream;
|
||||
+ IMFAttributes *attributes, *output_attributes;
|
||||
};
|
||||
|
||||
static struct audio_converter *impl_audio_converter_from_IMFTransform(IMFTransform *iface)
|
||||
@@ -84,6 +85,10 @@ static ULONG WINAPI audio_converter_Release(IMFTransform *iface)
|
||||
{
|
||||
transform->cs.DebugInfo->Spare[0] = 0;
|
||||
DeleteCriticalSection(&transform->cs);
|
||||
@ -31,10 +29,10 @@ index a95fc5506e7..2a5f87fec94 100644
|
||||
+ IMFAttributes_Release(transform->attributes);
|
||||
+ if (transform->output_attributes)
|
||||
+ IMFAttributes_Release(transform->output_attributes);
|
||||
gst_object_unref(transform->container);
|
||||
heap_free(transform);
|
||||
}
|
||||
@@ -155,9 +161,14 @@ static HRESULT WINAPI audio_converter_GetOutputStreamInfo(IMFTransform *iface, D
|
||||
if (transform->stream)
|
||||
unix_funcs->wg_parser_disconnect(transform->parser);
|
||||
if (transform->parser)
|
||||
@@ -171,9 +176,14 @@ static HRESULT WINAPI audio_converter_GetOutputStreamInfo(IMFTransform *iface, D
|
||||
|
||||
static HRESULT WINAPI audio_converter_GetAttributes(IMFTransform *iface, IMFAttributes **attributes)
|
||||
{
|
||||
@ -51,7 +49,7 @@ index a95fc5506e7..2a5f87fec94 100644
|
||||
}
|
||||
|
||||
static HRESULT WINAPI audio_converter_GetInputStreamAttributes(IMFTransform *iface, DWORD id,
|
||||
@@ -171,9 +182,14 @@ static HRESULT WINAPI audio_converter_GetInputStreamAttributes(IMFTransform *ifa
|
||||
@@ -187,9 +197,17 @@ static HRESULT WINAPI audio_converter_GetInputStreamAttributes(IMFTransform *ifa
|
||||
static HRESULT WINAPI audio_converter_GetOutputStreamAttributes(IMFTransform *iface, DWORD id,
|
||||
IMFAttributes **attributes)
|
||||
{
|
||||
@ -61,6 +59,9 @@ index a95fc5506e7..2a5f87fec94 100644
|
||||
- return E_NOTIMPL;
|
||||
+ TRACE("%p, %u, %p.\n", iface, id, attributes);
|
||||
+
|
||||
+ if (id != 0)
|
||||
+ return MF_E_INVALIDSTREAMNUMBER;
|
||||
+
|
||||
+ *attributes = converter->output_attributes;
|
||||
+ IMFAttributes_AddRef(*attributes);
|
||||
+
|
||||
@ -68,15 +69,15 @@ index a95fc5506e7..2a5f87fec94 100644
|
||||
}
|
||||
|
||||
static HRESULT WINAPI audio_converter_DeleteInputStream(IMFTransform *iface, DWORD id)
|
||||
@@ -715,6 +731,7 @@ HRESULT audio_converter_create(REFIID riid, void **ret)
|
||||
@@ -860,6 +878,7 @@ static const IMFTransformVtbl audio_converter_vtbl =
|
||||
HRESULT audio_converter_create(REFIID riid, void **ret)
|
||||
{
|
||||
GstElement *audioconvert, *resampler;
|
||||
struct audio_converter *object;
|
||||
+ HRESULT hr;
|
||||
|
||||
TRACE("%s %p\n", debugstr_guid(riid), ret);
|
||||
|
||||
@@ -727,6 +744,18 @@ HRESULT audio_converter_create(REFIID riid, void **ret)
|
||||
@@ -872,6 +891,18 @@ HRESULT audio_converter_create(REFIID riid, void **ret)
|
||||
InitializeCriticalSection(&object->cs);
|
||||
object->cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": audio_converter_lock");
|
||||
|
||||
@ -92,10 +93,9 @@ index a95fc5506e7..2a5f87fec94 100644
|
||||
+ return hr;
|
||||
+ }
|
||||
+
|
||||
object->container = gst_bin_new(NULL);
|
||||
|
||||
if (!(object->appsrc = gst_element_factory_make("appsrc", NULL)))
|
||||
|
||||
if (!(object->parser = unix_funcs->wg_raw_media_converter_create()))
|
||||
{
|
||||
ERR("Failed to create audio converter due to GStreamer error.\n");
|
||||
--
|
||||
2.30.0
|
||||
2.30.2
|
||||
|
@ -1,71 +0,0 @@
|
||||
From dd7243f4ee9f7bee1019621c974f98737b760905 Mon Sep 17 00:00:00 2001
|
||||
From: Derek Lesho <dlesho@codeweavers.com>
|
||||
Date: Wed, 2 Dec 2020 17:12:22 -0500
|
||||
Subject: [PATCH] Allow for compressed types.
|
||||
|
||||
---
|
||||
dlls/winegstreamer/mfplat.c | 28 ++++++++++++++++++----------
|
||||
1 file changed, 18 insertions(+), 10 deletions(-)
|
||||
|
||||
diff --git a/dlls/winegstreamer/mfplat.c b/dlls/winegstreamer/mfplat.c
|
||||
index f4a0c5b00f0..8d2d8996f22 100644
|
||||
--- a/dlls/winegstreamer/mfplat.c
|
||||
+++ b/dlls/winegstreamer/mfplat.c
|
||||
@@ -779,22 +779,20 @@ GstCaps *caps_from_mf_media_type(IMFMediaType *type)
|
||||
{
|
||||
DWORD rate = -1, channels = -1, channel_mask = -1;
|
||||
|
||||
- if (FAILED(IMFMediaType_GetUINT32(type, &MF_MT_AUDIO_SAMPLES_PER_SECOND, &rate)))
|
||||
- {
|
||||
- ERR("Sample rate not set.\n");
|
||||
- return NULL;
|
||||
- }
|
||||
- if (FAILED(IMFMediaType_GetUINT32(type, &MF_MT_AUDIO_NUM_CHANNELS, &channels)))
|
||||
- {
|
||||
- ERR("Channel count not set.\n");
|
||||
- return NULL;
|
||||
- }
|
||||
+ IMFMediaType_GetUINT32(type, &MF_MT_AUDIO_SAMPLES_PER_SECOND, &rate);
|
||||
+ IMFMediaType_GetUINT32(type, &MF_MT_AUDIO_NUM_CHANNELS, &channels);
|
||||
IMFMediaType_GetUINT32(type, &MF_MT_AUDIO_CHANNEL_MASK, &channel_mask);
|
||||
|
||||
if (IsEqualGUID(&subtype, &MFAudioFormat_Float))
|
||||
{
|
||||
GstAudioInfo float_info;
|
||||
|
||||
+ if (rate == -1 || channels == -1)
|
||||
+ {
|
||||
+ ERR("Incomplete media type.\n");
|
||||
+ return NULL;
|
||||
+ }
|
||||
+
|
||||
gst_audio_info_set_format(&float_info, GST_AUDIO_FORMAT_F32LE, rate, channels, NULL);
|
||||
output = gst_audio_info_to_caps(&float_info);
|
||||
}
|
||||
@@ -804,6 +802,12 @@ GstCaps *caps_from_mf_media_type(IMFMediaType *type)
|
||||
GstAudioInfo pcm_info;
|
||||
DWORD bits_per_sample;
|
||||
|
||||
+ if (rate == -1 || channels == -1)
|
||||
+ {
|
||||
+ ERR("Incomplete media type.\n");
|
||||
+ return NULL;
|
||||
+ }
|
||||
+
|
||||
if (SUCCEEDED(IMFMediaType_GetUINT32(type, &MF_MT_AUDIO_BITS_PER_SAMPLE, &bits_per_sample)))
|
||||
{
|
||||
pcm_format = gst_audio_format_build_integer(bits_per_sample > 8, G_LITTLE_ENDIAN, bits_per_sample, bits_per_sample);
|
||||
@@ -823,6 +827,10 @@ GstCaps *caps_from_mf_media_type(IMFMediaType *type)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
+ if (rate != -1)
|
||||
+ gst_caps_set_simple(output, "rate", G_TYPE_INT, rate, NULL);
|
||||
+ if (channels != -1)
|
||||
+ gst_caps_set_simple(output, "channels", G_TYPE_INT, channels, NULL);
|
||||
if (channel_mask != -1)
|
||||
gst_caps_set_simple(output, "channel-mask", GST_TYPE_BITMASK, (guint64) channel_mask, NULL);
|
||||
|
||||
--
|
||||
2.29.2
|
||||
|
@ -1,38 +1,39 @@
|
||||
From b5316e74275511a63372473cb6bb10b8f2f8d2e1 Mon Sep 17 00:00:00 2001
|
||||
From 08d022a3705763c3d1ab3ffc6700c702cc6aed7b Mon Sep 17 00:00:00 2001
|
||||
From: Derek Lesho <dlesho@codeweavers.com>
|
||||
Date: Tue, 1 Dec 2020 13:16:27 -0500
|
||||
Subject: [PATCH] winegstreamer: Introduce color conversion transform.
|
||||
Date: Wed, 17 Mar 2021 15:35:20 -0400
|
||||
Subject: [PATCH 21/39] winegstreamer: Introduce color conversion transform.
|
||||
|
||||
Serves as a wrapper of videoconvert, and roughly fills the roll of Windows' CColorConverterDMO.
|
||||
Serves as a wrapper of videoconvert, and exposes the CColorConverterDMO MFT interface.
|
||||
|
||||
Signed-off-by: Derek Lesho <dlesho@codeweavers.com>
|
||||
---
|
||||
dlls/winegstreamer/Makefile.in | 1 +
|
||||
dlls/winegstreamer/colorconvert.c | 302 +++++++++++++++++++
|
||||
dlls/winegstreamer/colorconvert.c | 298 +++++++++++++++++++
|
||||
dlls/winegstreamer/gst_private.h | 1 +
|
||||
dlls/winegstreamer/mfplat.c | 3 +
|
||||
dlls/winegstreamer/mfplat.c | 2 +
|
||||
dlls/winegstreamer/winegstreamer_classes.idl | 6 +
|
||||
5 files changed, 313 insertions(+)
|
||||
include/wmcodecdsp.idl | 5 +
|
||||
6 files changed, 313 insertions(+)
|
||||
create mode 100644 dlls/winegstreamer/colorconvert.c
|
||||
|
||||
diff --git a/dlls/winegstreamer/Makefile.in b/dlls/winegstreamer/Makefile.in
|
||||
index 0b3229160b9..5395d6fd501 100644
|
||||
index 7459cccf7e4..ec688f4425b 100644
|
||||
--- a/dlls/winegstreamer/Makefile.in
|
||||
+++ b/dlls/winegstreamer/Makefile.in
|
||||
@@ -7,6 +7,7 @@ PARENTSRC = ../strmbase
|
||||
@@ -8,6 +8,7 @@ EXTRADLLFLAGS = -mno-cygwin
|
||||
|
||||
C_SRCS = \
|
||||
audioconvert.c \
|
||||
+ colorconvert.c \
|
||||
filter.c \
|
||||
gst_cbs.c \
|
||||
gstdemux.c \
|
||||
decode_transform.c \
|
||||
main.c \
|
||||
media_source.c \
|
||||
diff --git a/dlls/winegstreamer/colorconvert.c b/dlls/winegstreamer/colorconvert.c
|
||||
new file mode 100644
|
||||
index 00000000000..8d0823fc0dc
|
||||
index 00000000000..1f0d061a30c
|
||||
--- /dev/null
|
||||
+++ b/dlls/winegstreamer/colorconvert.c
|
||||
@@ -0,0 +1,302 @@
|
||||
@@ -0,0 +1,298 @@
|
||||
+/* GStreamer Color Converter
|
||||
+ *
|
||||
+ * Copyright 2020 Derek Lesho
|
||||
@ -52,16 +53,12 @@ index 00000000000..8d0823fc0dc
|
||||
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
+ */
|
||||
+
|
||||
+#include "config.h"
|
||||
+
|
||||
+#include "gst_private.h"
|
||||
+
|
||||
+#include "mfapi.h"
|
||||
+#include "mferror.h"
|
||||
+#include "mfidl.h"
|
||||
+
|
||||
+#include "wine/debug.h"
|
||||
+#include "wine/heap.h"
|
||||
+
|
||||
+WINE_DEFAULT_DEBUG_CHANNEL(mfplat);
|
||||
+
|
||||
@ -80,8 +77,8 @@ index 00000000000..8d0823fc0dc
|
||||
+{
|
||||
+ TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), obj);
|
||||
+
|
||||
+ if (IsEqualIID(riid, &IID_IMFTransform) ||
|
||||
+ IsEqualIID(riid, &IID_IUnknown))
|
||||
+ if (IsEqualGUID(riid, &IID_IMFTransform) ||
|
||||
+ IsEqualGUID(riid, &IID_IUnknown))
|
||||
+ {
|
||||
+ *obj = iface;
|
||||
+ IMFTransform_AddRef(iface);
|
||||
@ -112,7 +109,7 @@ index 00000000000..8d0823fc0dc
|
||||
+
|
||||
+ if (!refcount)
|
||||
+ {
|
||||
+ heap_free(transform);
|
||||
+ free(transform);
|
||||
+ }
|
||||
+
|
||||
+ return refcount;
|
||||
@ -326,7 +323,7 @@ index 00000000000..8d0823fc0dc
|
||||
+
|
||||
+ TRACE("%s %p\n", debugstr_guid(riid), ret);
|
||||
+
|
||||
+ if (!(object = heap_alloc_zero(sizeof(*object))))
|
||||
+ if (!(object = calloc(1, sizeof(*object))))
|
||||
+ return E_OUTOFMEMORY;
|
||||
+
|
||||
+ object->IMFTransform_iface.lpVtbl = &color_converter_vtbl;
|
||||
@ -336,51 +333,64 @@ index 00000000000..8d0823fc0dc
|
||||
+ return S_OK;
|
||||
+}
|
||||
diff --git a/dlls/winegstreamer/gst_private.h b/dlls/winegstreamer/gst_private.h
|
||||
index 14b6a011ac2..075e0ce1f0f 100644
|
||||
index ee6d19e74b6..0827f70112f 100644
|
||||
--- a/dlls/winegstreamer/gst_private.h
|
||||
+++ b/dlls/winegstreamer/gst_private.h
|
||||
@@ -87,5 +87,6 @@ GstBuffer *gst_buffer_from_mf_sample(IMFSample *in) DECLSPEC_HIDDEN;
|
||||
@@ -269,6 +269,7 @@ void mf_media_type_to_wg_format(IMFMediaType *type, struct wg_format *format) DE
|
||||
HRESULT winegstreamer_stream_handler_create(REFIID riid, void **obj) DECLSPEC_HIDDEN;
|
||||
|
||||
HRESULT audio_converter_create(REFIID riid, void **ret) DECLSPEC_HIDDEN;
|
||||
+HRESULT color_converter_create(REFIID riid, void **ret) DECLSPEC_HIDDEN;
|
||||
|
||||
#endif /* __GST_PRIVATE_INCLUDED__ */
|
||||
enum decoder_type
|
||||
{
|
||||
diff --git a/dlls/winegstreamer/mfplat.c b/dlls/winegstreamer/mfplat.c
|
||||
index 883084b2d89..288b79997cd 100644
|
||||
index 28b45893b1b..60e594b5d6c 100644
|
||||
--- a/dlls/winegstreamer/mfplat.c
|
||||
+++ b/dlls/winegstreamer/mfplat.c
|
||||
@@ -407,6 +407,8 @@ static const GUID CLSID_GStreamerByteStreamHandler = {0x317df618, 0x5e5a, 0x468a
|
||||
@@ -22,6 +22,7 @@
|
||||
#include "mfapi.h"
|
||||
#include "ks.h"
|
||||
#include "ksmedia.h"
|
||||
+#include "wmcodecdsp.h"
|
||||
|
||||
static const GUID CLSID_WINEAudioConverter = {0x6a170414,0xaad9,0x4693,{0xb8,0x06,0x3a,0x0c,0x47,0xc5,0x70,0xd6}};
|
||||
#include "wine/debug.h"
|
||||
|
||||
+static GUID CLSID_WINEColorConverter = {0x2be8b27f,0xcd60,0x4b8a,{0x95,0xae,0xd1,0x74,0xcc,0x5c,0xba,0xa7}};
|
||||
+
|
||||
static const struct class_object
|
||||
{
|
||||
const GUID *clsid;
|
||||
@@ -417,6 +419,7 @@ class_objects[] =
|
||||
@@ -422,6 +423,7 @@ class_objects[] =
|
||||
{ &CLSID_VideoProcessorMFT, &video_processor_create },
|
||||
{ &CLSID_GStreamerByteStreamHandler, &winegstreamer_stream_handler_create },
|
||||
{ &CLSID_WINEAudioConverter, &audio_converter_create },
|
||||
+ { &CLSID_WINEColorConverter, &color_converter_create },
|
||||
+ { &CLSID_CColorConvertDMO, &color_converter_create },
|
||||
{ &CLSID_CMSH264DecoderMFT, &h264_decoder_create },
|
||||
{ &CLSID_CMSAACDecMFT, &aac_decoder_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 cf1fc69f38a..47c10a09cf0 100644
|
||||
index 4c58d83403b..093fca3521e 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)
|
||||
@@ -79,3 +79,9 @@ coclass CMSH264DecoderMFT { }
|
||||
uuid(32d186a7-218f-4c75-8876-dd77273a8999)
|
||||
]
|
||||
coclass WINEAudioConverter { }
|
||||
coclass CMSAACDecMFT { }
|
||||
+
|
||||
+[
|
||||
+ threading(both),
|
||||
+ uuid(2be8b27f-cd60-4b8a-95ae-d174cc5cbaa7)
|
||||
+ uuid(98230571-0087-4204-b020-3282538e57d3)
|
||||
+]
|
||||
+coclass WINEColorConverter { }
|
||||
+coclass CColorConvertDMO { }
|
||||
diff --git a/include/wmcodecdsp.idl b/include/wmcodecdsp.idl
|
||||
index 61381bee6d4..87305422332 100644
|
||||
--- a/include/wmcodecdsp.idl
|
||||
+++ b/include/wmcodecdsp.idl
|
||||
@@ -30,3 +30,8 @@ coclass CMP3DecMediaObject {}
|
||||
uuid(f447b69e-1884-4a7e-8055-346f74d6edb3)
|
||||
]
|
||||
coclass CResamplerMediaObject {}
|
||||
+
|
||||
+[
|
||||
+ uuid(98230571-0087-4204-b020-3282538e57d3)
|
||||
+]
|
||||
+coclass CColorConvertDMO {}
|
||||
--
|
||||
2.29.2
|
||||
2.30.2
|
||||
|
@ -1,32 +0,0 @@
|
||||
From 3b4148fbc1338e6a202d852491eba1362c905bfc Mon Sep 17 00:00:00 2001
|
||||
From: Derek Lesho <dlesho@codeweavers.com>
|
||||
Date: Wed, 14 Oct 2020 11:07:05 -0500
|
||||
Subject: [PATCH] mf/session: Unconditionally deliver NULL (EOS) samples.
|
||||
|
||||
Signed-off-by: Derek Lesho <dlesho@codeweavers.com>
|
||||
---
|
||||
dlls/mf/session.c | 5 +++--
|
||||
1 file changed, 3 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/dlls/mf/session.c b/dlls/mf/session.c
|
||||
index 1a7439a13c3..07e29cd013f 100644
|
||||
--- a/dlls/mf/session.c
|
||||
+++ b/dlls/mf/session.c
|
||||
@@ -2858,11 +2858,12 @@ static void session_deliver_sample_to_node(struct media_session *session, IMFTop
|
||||
LIST_FOR_EACH_ENTRY_SAFE(sample_entry, sample_entry2, &topo_node->u.transform.outputs[i].samples,
|
||||
struct sample, entry)
|
||||
{
|
||||
- if (!topo_node->u.transform.outputs[i].requests)
|
||||
+ if (!topo_node->u.transform.outputs[i].requests && sample_entry->sample)
|
||||
break;
|
||||
|
||||
session_deliver_sample_to_node(session, downstream_node, downstream_input, sample_entry->sample);
|
||||
- topo_node->u.transform.outputs[i].requests--;
|
||||
+ if (sample_entry->sample)
|
||||
+ topo_node->u.transform.outputs[i].requests--;
|
||||
|
||||
transform_release_sample(sample_entry);
|
||||
}
|
||||
--
|
||||
2.29.2
|
||||
|
@ -1,23 +1,23 @@
|
||||
From 18799e737ff065a62ea1c92c9a684940053d9dfb Mon Sep 17 00:00:00 2001
|
||||
From 9ce58d1f3f2f7be32bc61ed29149ba32c154170a Mon Sep 17 00:00:00 2001
|
||||
From: Derek Lesho <dlesho@codeweavers.com>
|
||||
Date: Thu, 3 Dec 2020 12:45:48 -0500
|
||||
Subject: [PATCH] winegstreamer: Register the color conversion transform.
|
||||
Date: Wed, 17 Mar 2021 15:37:17 -0400
|
||||
Subject: [PATCH 22/39] winegstreamer: Register the color conversion transform.
|
||||
|
||||
Signed-off-by: Derek Lesho <dlesho@codeweavers.com>
|
||||
---
|
||||
dlls/winegstreamer/mfplat.c | 34 +++++++++++++++++++++++++++++++++-
|
||||
1 file changed, 33 insertions(+), 1 deletion(-)
|
||||
dlls/winegstreamer/mfplat.c | 33 ++++++++++++++++++++++++++++++++-
|
||||
1 file changed, 32 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/dlls/winegstreamer/mfplat.c b/dlls/winegstreamer/mfplat.c
|
||||
index 288b79997cd..1b19c43d991 100644
|
||||
index 60e594b5d6c..251ab021073 100644
|
||||
--- a/dlls/winegstreamer/mfplat.c
|
||||
+++ b/dlls/winegstreamer/mfplat.c
|
||||
@@ -455,6 +455,26 @@ static const GUID *audio_converter_supported_types[] =
|
||||
@@ -461,6 +461,26 @@ static const GUID *audio_converter_supported_types[] =
|
||||
&MFAudioFormat_Float,
|
||||
};
|
||||
|
||||
+static WCHAR color_converterW[] = {'C','o','l','o','r',' ','C','o','n','v','e','r','t','e','r',0};
|
||||
+const GUID *color_converter_supported_types[] =
|
||||
+static WCHAR color_converterW[] = L"Color Converter";
|
||||
+static const GUID *color_converter_supported_types[] =
|
||||
+{
|
||||
+ &MFVideoFormat_RGB24,
|
||||
+ &MFVideoFormat_RGB32,
|
||||
@ -36,15 +36,15 @@ index 288b79997cd..1b19c43d991 100644
|
||||
+ &MFVideoFormat_YVYU,
|
||||
+};
|
||||
+
|
||||
static const struct mft
|
||||
static WCHAR h264_decoderW[] = L"H.264 Decoder";
|
||||
static const GUID *h264_decoder_input_types[] =
|
||||
{
|
||||
const GUID *clsid;
|
||||
@@ -482,13 +502,25 @@ mfts[] =
|
||||
@@ -511,6 +531,17 @@ mfts[] =
|
||||
ARRAY_SIZE(audio_converter_supported_types),
|
||||
audio_converter_supported_types,
|
||||
NULL
|
||||
},
|
||||
+ {
|
||||
+ &CLSID_WINEColorConverter,
|
||||
+ &CLSID_CColorConvertDMO,
|
||||
+ &MFT_CATEGORY_VIDEO_EFFECT,
|
||||
+ color_converterW,
|
||||
+ MFT_ENUM_FLAG_SYNCMFT,
|
||||
@ -53,11 +53,11 @@ index 288b79997cd..1b19c43d991 100644
|
||||
+ color_converter_supported_types,
|
||||
+ ARRAY_SIZE(color_converter_supported_types),
|
||||
+ color_converter_supported_types,
|
||||
+ NULL
|
||||
+ },
|
||||
};
|
||||
|
||||
HRESULT mfplat_DllRegisterServer(void)
|
||||
{
|
||||
&CLSID_CMSH264DecoderMFT,
|
||||
&MFT_CATEGORY_VIDEO_DECODER,
|
||||
@@ -539,7 +570,7 @@ HRESULT mfplat_DllRegisterServer(void)
|
||||
{
|
||||
unsigned int i, j;
|
||||
HRESULT hr;
|
||||
@ -67,5 +67,5 @@ index 288b79997cd..1b19c43d991 100644
|
||||
for (i = 0; i < ARRAY_SIZE(mfts); i++)
|
||||
{
|
||||
--
|
||||
2.29.2
|
||||
2.30.2
|
||||
|
@ -1,42 +0,0 @@
|
||||
From e1c9fe73263c2220be53482d195264832842279e Mon Sep 17 00:00:00 2001
|
||||
From: Derek Lesho <dlesho@codeweavers.com>
|
||||
Date: Thu, 2 Apr 2020 15:42:18 -0500
|
||||
Subject: [PATCH] mf/session: Request more samples when a transform needs them.
|
||||
|
||||
Signed-off-by: Derek Lesho <dlesho@codeweavers.com>
|
||||
---
|
||||
dlls/mf/session.c | 11 ++++++++++-
|
||||
1 file changed, 10 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/dlls/mf/session.c b/dlls/mf/session.c
|
||||
index 07e29cd013f..5a08a2eb6c6 100644
|
||||
--- a/dlls/mf/session.c
|
||||
+++ b/dlls/mf/session.c
|
||||
@@ -2759,6 +2759,8 @@ static HRESULT transform_node_pull_samples(const struct media_session *session,
|
||||
return hr;
|
||||
}
|
||||
|
||||
+static HRESULT session_request_sample_from_node(struct media_session *session, IMFTopologyNode *node, DWORD output);
|
||||
+
|
||||
static void session_deliver_sample_to_node(struct media_session *session, IMFTopologyNode *node, unsigned int input,
|
||||
IMFSample *sample)
|
||||
{
|
||||
@@ -2834,7 +2836,14 @@ static void session_deliver_sample_to_node(struct media_session *session, IMFTop
|
||||
WARN("Drain command failed for transform, hr %#x.\n", hr);
|
||||
}
|
||||
|
||||
- transform_node_pull_samples(session, topo_node);
|
||||
+ if (transform_node_pull_samples(session, topo_node) == MF_E_TRANSFORM_NEED_MORE_INPUT && !drain)
|
||||
+ {
|
||||
+ IMFTopologyNode *upstream_node;
|
||||
+ DWORD upstream_output;
|
||||
+
|
||||
+ if (SUCCEEDED(IMFTopologyNode_GetInput(node, input, &upstream_node, &upstream_output)))
|
||||
+ session_request_sample_from_node(session, upstream_node, upstream_output);
|
||||
+ }
|
||||
|
||||
/* Remaining unprocessed input has been discarded, now queue markers for every output. */
|
||||
if (drain)
|
||||
--
|
||||
2.29.2
|
||||
|
@ -1,8 +1,8 @@
|
||||
From 15b54cf08d296483e6d4c211eeae50db62f70804 Mon Sep 17 00:00:00 2001
|
||||
From 03498a3854a6a8fbe055354c1cde8c03119208dc Mon Sep 17 00:00:00 2001
|
||||
From: Derek Lesho <dlesho@codeweavers.com>
|
||||
Date: Thu, 3 Dec 2020 12:55:14 -0500
|
||||
Subject: [PATCH] winegstreamer: Implement ::GetInputAvailableType for color
|
||||
conversion transform.
|
||||
Date: Wed, 17 Mar 2021 15:41:33 -0400
|
||||
Subject: [PATCH 23/39] winegstreamer: Implement ::GetInputAvailableType for
|
||||
color conversion transform.
|
||||
|
||||
Signed-off-by: Derek Lesho <dlesho@codeweavers.com>
|
||||
---
|
||||
@ -10,10 +10,10 @@ Signed-off-by: Derek Lesho <dlesho@codeweavers.com>
|
||||
1 file changed, 46 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/dlls/winegstreamer/colorconvert.c b/dlls/winegstreamer/colorconvert.c
|
||||
index 8d0823fc0dc..9a1d2880234 100644
|
||||
index 1f0d061a30c..078782daaed 100644
|
||||
--- a/dlls/winegstreamer/colorconvert.c
|
||||
+++ b/dlls/winegstreamer/colorconvert.c
|
||||
@@ -30,6 +30,24 @@
|
||||
@@ -26,6 +26,24 @@
|
||||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(mfplat);
|
||||
|
||||
@ -38,7 +38,7 @@ index 8d0823fc0dc..9a1d2880234 100644
|
||||
struct color_converter
|
||||
{
|
||||
IMFTransform IMFTransform_iface;
|
||||
@@ -164,9 +182,35 @@ static HRESULT WINAPI color_converter_AddInputStreams(IMFTransform *iface, DWORD
|
||||
@@ -160,9 +178,35 @@ static HRESULT WINAPI color_converter_AddInputStreams(IMFTransform *iface, DWORD
|
||||
static HRESULT WINAPI color_converter_GetInputAvailableType(IMFTransform *iface, DWORD id, DWORD index,
|
||||
IMFMediaType **type)
|
||||
{
|
||||
@ -77,5 +77,5 @@ index 8d0823fc0dc..9a1d2880234 100644
|
||||
|
||||
static HRESULT WINAPI color_converter_GetOutputAvailableType(IMFTransform *iface, DWORD id, DWORD index,
|
||||
--
|
||||
2.29.2
|
||||
2.30.2
|
||||
|
@ -1,27 +0,0 @@
|
||||
From b25ab6a73f44bdab1a4ce782a27a8b3f1213cf64 Mon Sep 17 00:00:00 2001
|
||||
From: Derek Lesho <dlesho@codeweavers.com>
|
||||
Date: Thu, 15 Oct 2020 12:18:10 -0500
|
||||
Subject: [PATCH] HACK: Flush decoder when changing times.
|
||||
|
||||
---
|
||||
dlls/mf/session.c | 3 +++
|
||||
1 file changed, 3 insertions(+)
|
||||
|
||||
diff --git a/dlls/mf/session.c b/dlls/mf/session.c
|
||||
index 5a08a2eb6c6..a6bc7803390 100644
|
||||
--- a/dlls/mf/session.c
|
||||
+++ b/dlls/mf/session.c
|
||||
@@ -2326,7 +2326,10 @@ static void session_set_presentation_clock(struct media_session *session)
|
||||
LIST_FOR_EACH_ENTRY(node, &session->presentation.nodes, struct topo_node, entry)
|
||||
{
|
||||
if (node->type == MF_TOPOLOGY_TRANSFORM_NODE)
|
||||
+ {
|
||||
+ IMFTransform_ProcessMessage(node->object.transform, MFT_MESSAGE_COMMAND_FLUSH, 0);
|
||||
IMFTransform_ProcessMessage(node->object.transform, MFT_MESSAGE_NOTIFY_START_OF_STREAM, 0);
|
||||
+ }
|
||||
}
|
||||
|
||||
if (!(session->presentation.flags & SESSION_FLAG_PRESENTATION_CLOCK_SET))
|
||||
--
|
||||
2.29.2
|
||||
|
@ -1,19 +1,19 @@
|
||||
From 096a5070ac3ce917e6c8ae010e8e80c8ffbde3c4 Mon Sep 17 00:00:00 2001
|
||||
From 5c6e2cc11f047f728e8cb1100a7044398a1b5898 Mon Sep 17 00:00:00 2001
|
||||
From: Derek Lesho <dlesho@codeweavers.com>
|
||||
Date: Thu, 3 Dec 2020 14:34:07 -0500
|
||||
Subject: [PATCH] winegstreamer: Implement ::SetInputType for color conversion
|
||||
transform.
|
||||
Date: Wed, 17 Mar 2021 16:01:18 -0400
|
||||
Subject: [PATCH 24/39] winegstreamer: Implement ::SetInputType for color
|
||||
conversion transform.
|
||||
|
||||
Signed-off-by: Derek Lesho <dlesho@codeweavers.com>
|
||||
---
|
||||
dlls/winegstreamer/colorconvert.c | 76 ++++++++++++++++++++++++++++++-
|
||||
1 file changed, 74 insertions(+), 2 deletions(-)
|
||||
dlls/winegstreamer/colorconvert.c | 75 ++++++++++++++++++++++++++++++-
|
||||
1 file changed, 73 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/dlls/winegstreamer/colorconvert.c b/dlls/winegstreamer/colorconvert.c
|
||||
index 9a1d2880234..5dd48188147 100644
|
||||
index 078782daaed..06186ed7846 100644
|
||||
--- a/dlls/winegstreamer/colorconvert.c
|
||||
+++ b/dlls/winegstreamer/colorconvert.c
|
||||
@@ -52,6 +52,8 @@ struct color_converter
|
||||
@@ -48,6 +48,8 @@ struct color_converter
|
||||
{
|
||||
IMFTransform IMFTransform_iface;
|
||||
LONG refcount;
|
||||
@ -22,59 +22,66 @@ index 9a1d2880234..5dd48188147 100644
|
||||
};
|
||||
|
||||
static struct color_converter *impl_color_converter_from_IMFTransform(IMFTransform *iface)
|
||||
@@ -95,6 +97,8 @@ static ULONG WINAPI color_converter_Release(IMFTransform *iface)
|
||||
@@ -91,6 +93,8 @@ static ULONG WINAPI color_converter_Release(IMFTransform *iface)
|
||||
|
||||
if (!refcount)
|
||||
{
|
||||
+ transform->cs.DebugInfo->Spare[0] = 0;
|
||||
+ DeleteCriticalSection(&transform->cs);
|
||||
heap_free(transform);
|
||||
free(transform);
|
||||
}
|
||||
|
||||
@@ -223,9 +227,74 @@ static HRESULT WINAPI color_converter_GetOutputAvailableType(IMFTransform *iface
|
||||
@@ -219,9 +223,73 @@ static HRESULT WINAPI color_converter_GetOutputAvailableType(IMFTransform *iface
|
||||
|
||||
static HRESULT WINAPI color_converter_SetInputType(IMFTransform *iface, DWORD id, IMFMediaType *type, DWORD flags)
|
||||
{
|
||||
- FIXME("%p, %u, %p, %#x.\n", iface, id, type, flags);
|
||||
+ GstCaps *input_caps;
|
||||
+ struct color_converter *converter = impl_color_converter_from_IMFTransform(iface);
|
||||
+ GUID major_type, subtype;
|
||||
+ 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)
|
||||
+ if (!type)
|
||||
+ {
|
||||
+ GUID major_type, subtype;
|
||||
+ if (flags & MFT_SET_TYPE_TEST_ONLY)
|
||||
+ 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;
|
||||
+ EnterCriticalSection(&converter->cs);
|
||||
+
|
||||
+ if (!(IsEqualGUID(&major_type, &MFMediaType_Video)))
|
||||
+ return MF_E_INVALIDTYPE;
|
||||
+
|
||||
+ for (i = 0; i < ARRAY_SIZE(raw_types); i++)
|
||||
+ if (converter->input_type)
|
||||
+ {
|
||||
+ if (IsEqualGUID(&subtype, raw_types[i]))
|
||||
+ break;
|
||||
+ IMFMediaType_Release(converter->input_type);
|
||||
+ converter->input_type = NULL;
|
||||
+ }
|
||||
+
|
||||
+ if (i == ARRAY_SIZE(raw_types))
|
||||
+ return MF_E_INVALIDTYPE;
|
||||
+ LeaveCriticalSection(&converter->cs);
|
||||
+
|
||||
+ if (!(input_caps = caps_from_mf_media_type(type)))
|
||||
+ return MF_E_INVALIDTYPE;
|
||||
+
|
||||
+ gst_caps_unref(input_caps);
|
||||
+ 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, &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 (flags & MFT_SET_TYPE_TEST_ONLY)
|
||||
+ return S_OK;
|
||||
+
|
||||
@ -82,21 +89,13 @@ index 9a1d2880234..5dd48188147 100644
|
||||
+
|
||||
+ hr = S_OK;
|
||||
+
|
||||
+ if (type)
|
||||
+ {
|
||||
+ if (!converter->input_type)
|
||||
+ hr = MFCreateMediaType(&converter->input_type);
|
||||
+ if (!converter->input_type)
|
||||
+ hr = MFCreateMediaType(&converter->input_type);
|
||||
+
|
||||
+ if (SUCCEEDED(hr))
|
||||
+ hr = IMFMediaType_CopyAllItems(type, (IMFAttributes *) converter->input_type);
|
||||
+ if (SUCCEEDED(hr))
|
||||
+ hr = IMFMediaType_CopyAllItems(type, (IMFAttributes *) converter->input_type);
|
||||
+
|
||||
+ if (FAILED(hr))
|
||||
+ {
|
||||
+ IMFMediaType_Release(converter->input_type);
|
||||
+ converter->input_type = NULL;
|
||||
+ }
|
||||
+ }
|
||||
+ else
|
||||
+ if (FAILED(hr))
|
||||
+ {
|
||||
+ IMFMediaType_Release(converter->input_type);
|
||||
+ converter->input_type = NULL;
|
||||
@ -108,7 +107,7 @@ index 9a1d2880234..5dd48188147 100644
|
||||
}
|
||||
|
||||
static HRESULT WINAPI color_converter_SetOutputType(IMFTransform *iface, DWORD id, IMFMediaType *type, DWORD flags)
|
||||
@@ -341,6 +410,9 @@ HRESULT color_converter_create(REFIID riid, void **ret)
|
||||
@@ -337,6 +405,9 @@ HRESULT color_converter_create(REFIID riid, void **ret)
|
||||
object->IMFTransform_iface.lpVtbl = &color_converter_vtbl;
|
||||
object->refcount = 1;
|
||||
|
||||
@ -119,5 +118,5 @@ index 9a1d2880234..5dd48188147 100644
|
||||
return S_OK;
|
||||
}
|
||||
--
|
||||
2.29.2
|
||||
2.30.2
|
||||
|
@ -1,163 +0,0 @@
|
||||
From 8b681e5bd589b330790a0e887f5dbcd380e84a05 Mon Sep 17 00:00:00 2001
|
||||
From: Derek Lesho <dlesho@codeweavers.com>
|
||||
Date: Mon, 2 Nov 2020 09:56:54 -0600
|
||||
Subject: [PATCH] winegstreamer: Add IMFSeekInfo::GetNearestKeyFrames stub.
|
||||
|
||||
Signed-off-by: Derek Lesho <dlesho@codeweavers.com>
|
||||
---
|
||||
dlls/winegstreamer/media_source.c | 111 ++++++++++++++++++++++++++++++
|
||||
1 file changed, 111 insertions(+)
|
||||
|
||||
diff --git a/dlls/winegstreamer/media_source.c b/dlls/winegstreamer/media_source.c
|
||||
index 655e765fee7..a0bce3cfe9d 100644
|
||||
--- a/dlls/winegstreamer/media_source.c
|
||||
+++ b/dlls/winegstreamer/media_source.c
|
||||
@@ -92,6 +92,8 @@ struct source_async_command
|
||||
struct media_source
|
||||
{
|
||||
IMFMediaSource IMFMediaSource_iface;
|
||||
+ IMFGetService IMFGetService_iface;
|
||||
+ IMFSeekInfo IMFSeekInfo_iface;
|
||||
IMFAsyncCallback async_commands_callback;
|
||||
LONG ref;
|
||||
DWORD async_commands_queue;
|
||||
@@ -124,6 +126,16 @@ static inline struct media_source *impl_from_IMFMediaSource(IMFMediaSource *ifac
|
||||
return CONTAINING_RECORD(iface, struct media_source, IMFMediaSource_iface);
|
||||
}
|
||||
|
||||
+static inline struct media_source *impl_from_IMFGetService(IMFGetService *iface)
|
||||
+{
|
||||
+ return CONTAINING_RECORD(iface, struct media_source, IMFGetService_iface);
|
||||
+}
|
||||
+
|
||||
+static inline struct media_source *impl_from_IMFSeekInfo(IMFSeekInfo *iface)
|
||||
+{
|
||||
+ return CONTAINING_RECORD(iface, struct media_source, IMFSeekInfo_iface);
|
||||
+}
|
||||
+
|
||||
static inline struct media_source *impl_from_async_commands_callback_IMFAsyncCallback(IMFAsyncCallback *iface)
|
||||
{
|
||||
return CONTAINING_RECORD(iface, struct media_source, async_commands_callback);
|
||||
@@ -978,6 +990,10 @@ static HRESULT WINAPI media_source_QueryInterface(IMFMediaSource *iface, REFIID
|
||||
{
|
||||
*out = &source->IMFMediaSource_iface;
|
||||
}
|
||||
+ else if(IsEqualIID(riid, &IID_IMFGetService))
|
||||
+ {
|
||||
+ *out = &source->IMFGetService_iface;
|
||||
+ }
|
||||
else
|
||||
{
|
||||
FIXME("(%s, %p)\n", debugstr_guid(riid), out);
|
||||
@@ -1212,6 +1228,99 @@ static const IMFMediaSourceVtbl IMFMediaSource_vtbl =
|
||||
media_source_Shutdown,
|
||||
};
|
||||
|
||||
+static HRESULT WINAPI source_get_service_QueryInterface(IMFGetService *iface, REFIID riid, void **obj)
|
||||
+{
|
||||
+ struct media_source *source = impl_from_IMFGetService(iface);
|
||||
+ return IMFMediaSource_QueryInterface(&source->IMFMediaSource_iface, riid, obj);
|
||||
+}
|
||||
+
|
||||
+static ULONG WINAPI source_get_service_AddRef(IMFGetService *iface)
|
||||
+{
|
||||
+ struct media_source *source = impl_from_IMFGetService(iface);
|
||||
+ return IMFMediaSource_AddRef(&source->IMFMediaSource_iface);
|
||||
+}
|
||||
+
|
||||
+static ULONG WINAPI source_get_service_Release(IMFGetService *iface)
|
||||
+{
|
||||
+ struct media_source *source = impl_from_IMFGetService(iface);
|
||||
+ return IMFMediaSource_Release(&source->IMFMediaSource_iface);
|
||||
+}
|
||||
+
|
||||
+static HRESULT WINAPI source_get_service_GetService(IMFGetService *iface, REFGUID service, REFIID riid, void **obj)
|
||||
+{
|
||||
+ struct media_source *source = impl_from_IMFGetService(iface);
|
||||
+
|
||||
+ TRACE("(%p)->(%s, %s, %p)\n", source, debugstr_guid(service), debugstr_guid(riid), obj);
|
||||
+
|
||||
+ if (source->state == SOURCE_SHUTDOWN)
|
||||
+ return MF_E_SHUTDOWN;
|
||||
+
|
||||
+ *obj = NULL;
|
||||
+
|
||||
+ if (IsEqualIID(service, &MF_SCRUBBING_SERVICE))
|
||||
+ {
|
||||
+ if (IsEqualIID(riid, &IID_IMFSeekInfo))
|
||||
+ {
|
||||
+ *obj = &source->IMFSeekInfo_iface;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (*obj)
|
||||
+ IUnknown_AddRef((IUnknown*) *obj);
|
||||
+
|
||||
+ return *obj ? S_OK : E_NOINTERFACE;
|
||||
+}
|
||||
+
|
||||
+static const IMFGetServiceVtbl IMFGetService_vtbl =
|
||||
+{
|
||||
+ source_get_service_QueryInterface,
|
||||
+ source_get_service_AddRef,
|
||||
+ source_get_service_Release,
|
||||
+ source_get_service_GetService,
|
||||
+};
|
||||
+
|
||||
+static HRESULT WINAPI source_seek_info_QueryInterface(IMFSeekInfo *iface, REFIID riid, void **obj)
|
||||
+{
|
||||
+ struct media_source *source = impl_from_IMFSeekInfo(iface);
|
||||
+ return IMFMediaSource_QueryInterface(&source->IMFMediaSource_iface, riid, obj);
|
||||
+}
|
||||
+
|
||||
+static ULONG WINAPI source_seek_info_AddRef(IMFSeekInfo *iface)
|
||||
+{
|
||||
+ struct media_source *source = impl_from_IMFSeekInfo(iface);
|
||||
+ return IMFMediaSource_AddRef(&source->IMFMediaSource_iface);
|
||||
+}
|
||||
+
|
||||
+static ULONG WINAPI source_seek_info_Release(IMFSeekInfo *iface)
|
||||
+{
|
||||
+ struct media_source *source = impl_from_IMFSeekInfo(iface);
|
||||
+ return IMFMediaSource_Release(&source->IMFMediaSource_iface);
|
||||
+}
|
||||
+
|
||||
+static HRESULT WINAPI source_seek_info_GetNearestKeyFrames(IMFSeekInfo *iface, const GUID *format,
|
||||
+ const PROPVARIANT *position, PROPVARIANT *prev_frame, PROPVARIANT *next_frame)
|
||||
+{
|
||||
+ struct media_source *source = impl_from_IMFSeekInfo(iface);
|
||||
+
|
||||
+ FIXME("(%p)->(%s, %p, %p, %p) - semi-stub\n", source, debugstr_guid(format), position, prev_frame, next_frame);
|
||||
+
|
||||
+ if (source->state == SOURCE_SHUTDOWN)
|
||||
+ return MF_E_SHUTDOWN;
|
||||
+
|
||||
+ PropVariantCopy(prev_frame, position);
|
||||
+ PropVariantCopy(next_frame, position);
|
||||
+
|
||||
+ return S_OK;
|
||||
+}
|
||||
+
|
||||
+static const IMFSeekInfoVtbl IMFSeekInfo_vtbl =
|
||||
+{
|
||||
+ source_seek_info_QueryInterface,
|
||||
+ source_seek_info_AddRef,
|
||||
+ source_seek_info_Release,
|
||||
+ source_seek_info_GetNearestKeyFrames,
|
||||
+};
|
||||
+
|
||||
static void stream_added(GstElement *element, GstPad *pad, gpointer user)
|
||||
{
|
||||
struct media_source *source = user;
|
||||
@@ -1283,6 +1392,8 @@ static HRESULT media_source_constructor(IMFByteStream *bytestream, struct media_
|
||||
return E_OUTOFMEMORY;
|
||||
|
||||
object->IMFMediaSource_iface.lpVtbl = &IMFMediaSource_vtbl;
|
||||
+ object->IMFGetService_iface.lpVtbl = &IMFGetService_vtbl;
|
||||
+ object->IMFSeekInfo_iface.lpVtbl = &IMFSeekInfo_vtbl;
|
||||
object->async_commands_callback.lpVtbl = &source_async_commands_callback_vtbl;
|
||||
object->ref = 1;
|
||||
object->byte_stream = bytestream;
|
||||
--
|
||||
2.29.2
|
||||
|
@ -0,0 +1,64 @@
|
||||
From 70de073ef2395952f425411ef794e7238730ab52 Mon Sep 17 00:00:00 2001
|
||||
From: Derek Lesho <dlesho@codeweavers.com>
|
||||
Date: Wed, 17 Mar 2021 16:04:31 -0400
|
||||
Subject: [PATCH 25/39] winegstreamer: Implement ::GetOutputAvailableType for
|
||||
color conversion transform.
|
||||
|
||||
Signed-off-by: Derek Lesho <dlesho@codeweavers.com>
|
||||
---
|
||||
dlls/winegstreamer/colorconvert.c | 38 +++++++++++++++++++++++++++++--
|
||||
1 file changed, 36 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/dlls/winegstreamer/colorconvert.c b/dlls/winegstreamer/colorconvert.c
|
||||
index 06186ed7846..6d7064a4482 100644
|
||||
--- a/dlls/winegstreamer/colorconvert.c
|
||||
+++ b/dlls/winegstreamer/colorconvert.c
|
||||
@@ -216,9 +216,43 @@ static HRESULT WINAPI color_converter_GetInputAvailableType(IMFTransform *iface,
|
||||
static HRESULT WINAPI color_converter_GetOutputAvailableType(IMFTransform *iface, DWORD id, DWORD index,
|
||||
IMFMediaType **type)
|
||||
{
|
||||
- FIXME("%p, %u, %u, %p.\n", iface, id, index, type);
|
||||
+ struct color_converter *converter = impl_color_converter_from_IMFTransform(iface);
|
||||
+ IMFMediaType *ret;
|
||||
+ HRESULT hr;
|
||||
|
||||
- return E_NOTIMPL;
|
||||
+ TRACE("%p, %u, %u, %p.\n", iface, id, index, type);
|
||||
+
|
||||
+ if (id != 0)
|
||||
+ return MF_E_INVALIDSTREAMNUMBER;
|
||||
+
|
||||
+ if (index >= ARRAY_SIZE(raw_types))
|
||||
+ return MF_E_NO_MORE_TYPES;
|
||||
+
|
||||
+ if (FAILED(hr = MFCreateMediaType(&ret)))
|
||||
+ return hr;
|
||||
+
|
||||
+ EnterCriticalSection(&converter->cs);
|
||||
+
|
||||
+ if (converter->input_type)
|
||||
+ IMFMediaType_CopyAllItems(converter->input_type, (IMFAttributes *) ret);
|
||||
+
|
||||
+ LeaveCriticalSection(&converter->cs);
|
||||
+
|
||||
+ if (FAILED(hr = IMFMediaType_SetGUID(ret, &MF_MT_MAJOR_TYPE, &MFMediaType_Video)))
|
||||
+ {
|
||||
+ IMFMediaType_Release(ret);
|
||||
+ return hr;
|
||||
+ }
|
||||
+
|
||||
+ if (FAILED(hr = IMFMediaType_SetGUID(ret, &MF_MT_SUBTYPE, raw_types[index])))
|
||||
+ {
|
||||
+ IMFMediaType_Release(ret);
|
||||
+ return hr;
|
||||
+ }
|
||||
+
|
||||
+ *type = ret;
|
||||
+
|
||||
+ return S_OK;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI color_converter_SetInputType(IMFTransform *iface, DWORD id, IMFMediaType *type, DWORD flags)
|
||||
--
|
||||
2.30.2
|
||||
|
@ -1,122 +0,0 @@
|
||||
From 18dea0ccadf90b4ac523dc1073c3870fdd6bcf6a Mon Sep 17 00:00:00 2001
|
||||
From: Derek Lesho <dlesho@codeweavers.com>
|
||||
Date: Fri, 6 Nov 2020 10:06:23 -0600
|
||||
Subject: [PATCH] winegstreamer: Fixup raw audio caps to be compatible with
|
||||
IMFMediaType.
|
||||
|
||||
Signed-off-by: Derek Lesho <dlesho@codeweavers.com>
|
||||
---
|
||||
dlls/winegstreamer/gst_private.h | 1 +
|
||||
dlls/winegstreamer/media_source.c | 7 +++-
|
||||
dlls/winegstreamer/mfplat.c | 57 +++++++++++++++++++++++++++++++
|
||||
3 files changed, 64 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/dlls/winegstreamer/gst_private.h b/dlls/winegstreamer/gst_private.h
|
||||
index 075e0ce1f0f..dcf76554b6d 100644
|
||||
--- a/dlls/winegstreamer/gst_private.h
|
||||
+++ b/dlls/winegstreamer/gst_private.h
|
||||
@@ -79,6 +79,7 @@ extern HRESULT mfplat_get_class_object(REFCLSID rclsid, REFIID riid, void **obj)
|
||||
extern HRESULT mfplat_DllRegisterServer(void) DECLSPEC_HIDDEN;
|
||||
|
||||
HRESULT winegstreamer_stream_handler_create(REFIID riid, void **obj) DECLSPEC_HIDDEN;
|
||||
+GstCaps *make_mf_compatible_caps(GstCaps *caps) DECLSPEC_HIDDEN;
|
||||
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;
|
||||
diff --git a/dlls/winegstreamer/media_source.c b/dlls/winegstreamer/media_source.c
|
||||
index a0bce3cfe9d..5f3457e50b0 100644
|
||||
--- a/dlls/winegstreamer/media_source.c
|
||||
+++ b/dlls/winegstreamer/media_source.c
|
||||
@@ -891,15 +891,20 @@ fail:
|
||||
|
||||
static HRESULT media_stream_init_desc(struct media_stream *stream)
|
||||
{
|
||||
- GstCaps *current_caps = gst_pad_get_current_caps(stream->their_src);
|
||||
+ GstCaps *base_caps = gst_pad_get_current_caps(stream->their_src);
|
||||
IMFMediaTypeHandler *type_handler = NULL;
|
||||
IMFMediaType **stream_types = NULL;
|
||||
IMFMediaType *stream_type = NULL;
|
||||
+ GstCaps *current_caps = make_mf_compatible_caps(base_caps);
|
||||
DWORD type_count = 0;
|
||||
const gchar *major_type;
|
||||
unsigned int i;
|
||||
HRESULT hr;
|
||||
|
||||
+ gst_caps_unref(base_caps);
|
||||
+ if (!current_caps)
|
||||
+ return E_FAIL;
|
||||
+
|
||||
major_type = gst_structure_get_name(gst_caps_get_structure(current_caps, 0));
|
||||
|
||||
if (!strcmp(major_type, "video/x-raw"))
|
||||
diff --git a/dlls/winegstreamer/mfplat.c b/dlls/winegstreamer/mfplat.c
|
||||
index 8d2d8996f22..a2873907437 100644
|
||||
--- a/dlls/winegstreamer/mfplat.c
|
||||
+++ b/dlls/winegstreamer/mfplat.c
|
||||
@@ -710,6 +710,63 @@ IMFMediaType *mf_media_type_from_caps(const GstCaps *caps)
|
||||
return media_type;
|
||||
}
|
||||
|
||||
+GstCaps *make_mf_compatible_caps(GstCaps *caps)
|
||||
+{
|
||||
+ GstCaps *ret;
|
||||
+ IMFMediaType *media_type;
|
||||
+ GstStructure *structure;
|
||||
+ const char *mime_type;
|
||||
+
|
||||
+ if (gst_caps_get_size(caps) != 1)
|
||||
+ return NULL;
|
||||
+
|
||||
+ /* Optimization: Don't copy caps if no transformation is needed */
|
||||
+ if ((media_type = mf_media_type_from_caps(caps)))
|
||||
+ {
|
||||
+ IMFMediaType_Release(media_type);
|
||||
+ return gst_caps_ref(caps);
|
||||
+ }
|
||||
+
|
||||
+ ret = gst_caps_copy(caps);
|
||||
+ structure = gst_caps_get_structure(ret, 0);
|
||||
+ mime_type = gst_structure_get_name(structure);
|
||||
+
|
||||
+ if (!strcmp(mime_type, "audio/x-raw"))
|
||||
+ {
|
||||
+ const char *format;
|
||||
+ if ((format = gst_structure_get_string(structure, "format")))
|
||||
+ {
|
||||
+ char type;
|
||||
+ unsigned int bits_per_sample;
|
||||
+ char endian[2];
|
||||
+ char new_format[6];
|
||||
+
|
||||
+ if (strlen(format) <= 5 && (sscanf(format, "%c%u%2c", &type, &bits_per_sample, endian) >= 2))
|
||||
+ {
|
||||
+ if (type == 'U' || type == 'S')
|
||||
+ type = bits_per_sample == 8 ? 'U' : 'S';
|
||||
+
|
||||
+ if (endian[0] == 'B')
|
||||
+ endian[0] = 'L';
|
||||
+
|
||||
+ sprintf(new_format, "%c%u%.2s", type, bits_per_sample, bits_per_sample > 8 ? endian : 0);
|
||||
+ gst_caps_set_simple(caps, "format", G_TYPE_STRING, new_format, NULL);
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if ((media_type = mf_media_type_from_caps(ret)))
|
||||
+ IMFMediaType_Release(media_type);
|
||||
+
|
||||
+ if (!media_type)
|
||||
+ {
|
||||
+ gst_caps_unref(ret);
|
||||
+ return NULL;
|
||||
+ }
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
GstCaps *caps_from_mf_media_type(IMFMediaType *type)
|
||||
{
|
||||
GUID major_type;
|
||||
--
|
||||
2.29.2
|
||||
|
@ -0,0 +1,153 @@
|
||||
From d044e2fb2a690340a0011a8527592e7a90db2faa Mon Sep 17 00:00:00 2001
|
||||
From: Derek Lesho <dlesho@codeweavers.com>
|
||||
Date: Wed, 17 Mar 2021 16:26:28 -0400
|
||||
Subject: [PATCH 26/39] winegstreamer: Implement ::SetOutputType for color
|
||||
conversion transform.
|
||||
|
||||
Signed-off-by: Derek Lesho <dlesho@codeweavers.com>
|
||||
---
|
||||
dlls/winegstreamer/colorconvert.c | 99 ++++++++++++++++++++++++++++++-
|
||||
1 file changed, 97 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/dlls/winegstreamer/colorconvert.c b/dlls/winegstreamer/colorconvert.c
|
||||
index 6d7064a4482..e001c6c827e 100644
|
||||
--- a/dlls/winegstreamer/colorconvert.c
|
||||
+++ b/dlls/winegstreamer/colorconvert.c
|
||||
@@ -49,6 +49,7 @@ struct color_converter
|
||||
IMFTransform IMFTransform_iface;
|
||||
LONG refcount;
|
||||
IMFMediaType *input_type;
|
||||
+ IMFMediaType *output_type;
|
||||
CRITICAL_SECTION cs;
|
||||
};
|
||||
|
||||
@@ -95,6 +96,8 @@ static ULONG WINAPI color_converter_Release(IMFTransform *iface)
|
||||
{
|
||||
transform->cs.DebugInfo->Spare[0] = 0;
|
||||
DeleteCriticalSection(&transform->cs);
|
||||
+ if (transform->output_type)
|
||||
+ IMFMediaType_Release(transform->output_type);
|
||||
free(transform);
|
||||
}
|
||||
|
||||
@@ -258,6 +261,7 @@ static HRESULT WINAPI color_converter_GetOutputAvailableType(IMFTransform *iface
|
||||
static HRESULT WINAPI color_converter_SetInputType(IMFTransform *iface, DWORD id, IMFMediaType *type, DWORD flags)
|
||||
{
|
||||
struct color_converter *converter = impl_color_converter_from_IMFTransform(iface);
|
||||
+ UINT64 input_framesize, output_framesize;
|
||||
GUID major_type, subtype;
|
||||
unsigned int i;
|
||||
HRESULT hr;
|
||||
@@ -302,6 +306,19 @@ static HRESULT WINAPI color_converter_SetInputType(IMFTransform *iface, DWORD id
|
||||
if (i == ARRAY_SIZE(raw_types))
|
||||
return MF_E_INVALIDTYPE;
|
||||
|
||||
+ EnterCriticalSection(&converter->cs);
|
||||
+
|
||||
+ if(converter->output_type
|
||||
+ && SUCCEEDED(IMFMediaType_GetUINT64(converter->output_type, &MF_MT_FRAME_SIZE, &output_framesize))
|
||||
+ && SUCCEEDED(IMFMediaType_GetUINT64(type, &MF_MT_FRAME_SIZE, &input_framesize))
|
||||
+ && input_framesize != output_framesize)
|
||||
+ {
|
||||
+ LeaveCriticalSection(&converter->cs);
|
||||
+ return MF_E_INVALIDTYPE;
|
||||
+ }
|
||||
+
|
||||
+ LeaveCriticalSection(&converter->cs);
|
||||
+
|
||||
if (flags & MFT_SET_TYPE_TEST_ONLY)
|
||||
return S_OK;
|
||||
|
||||
@@ -328,9 +345,87 @@ 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);
|
||||
+ struct color_converter *converter = impl_color_converter_from_IMFTransform(iface);
|
||||
+ UINT64 input_framesize, output_framesize;
|
||||
+ GUID major_type, subtype;
|
||||
+ unsigned int i;
|
||||
+ HRESULT hr;
|
||||
|
||||
- return E_NOTIMPL;
|
||||
+ TRACE("%p, %u, %p, %#x.\n", iface, id, type, flags);
|
||||
+
|
||||
+ if (id != 0)
|
||||
+ return MF_E_INVALIDSTREAMNUMBER;
|
||||
+
|
||||
+ if (!type)
|
||||
+ {
|
||||
+ if (flags & MFT_SET_TYPE_TEST_ONLY)
|
||||
+ return S_OK;
|
||||
+
|
||||
+ EnterCriticalSection(&converter->cs);
|
||||
+
|
||||
+ if (converter->output_type)
|
||||
+ {
|
||||
+ IMFMediaType_Release(converter->output_type);
|
||||
+ converter->output_type = NULL;
|
||||
+ }
|
||||
+
|
||||
+ LeaveCriticalSection(&converter->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, &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;
|
||||
+
|
||||
+ EnterCriticalSection(&converter->cs);
|
||||
+
|
||||
+ if(converter->input_type
|
||||
+ && SUCCEEDED(IMFMediaType_GetUINT64(converter->input_type, &MF_MT_FRAME_SIZE, &input_framesize))
|
||||
+ && SUCCEEDED(IMFMediaType_GetUINT64(type, &MF_MT_FRAME_SIZE, &output_framesize))
|
||||
+ && input_framesize != output_framesize)
|
||||
+ {
|
||||
+ LeaveCriticalSection(&converter->cs);
|
||||
+ return MF_E_INVALIDTYPE;
|
||||
+ }
|
||||
+
|
||||
+ LeaveCriticalSection(&converter->cs);
|
||||
+
|
||||
+ if (flags & MFT_SET_TYPE_TEST_ONLY)
|
||||
+ return S_OK;
|
||||
+
|
||||
+ EnterCriticalSection(&converter->cs);
|
||||
+
|
||||
+ hr = S_OK;
|
||||
+
|
||||
+ 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;
|
||||
+ }
|
||||
+
|
||||
+ LeaveCriticalSection(&converter->cs);
|
||||
+
|
||||
+ return S_OK;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI color_converter_GetInputCurrentType(IMFTransform *iface, DWORD id, IMFMediaType **type)
|
||||
--
|
||||
2.30.2
|
||||
|
@ -0,0 +1,390 @@
|
||||
From 93e4d5996b5abedef39d4667363f42cabaaa8705 Mon Sep 17 00:00:00 2001
|
||||
From: Derek Lesho <dlesho@codeweavers.com>
|
||||
Date: Wed, 17 Mar 2021 16:49:13 -0400
|
||||
Subject: [PATCH 27/39] winegstreamer: Implement ::Process(Input/Output) for
|
||||
color conversion transform.
|
||||
|
||||
Signed-off-by: Derek Lesho <dlesho@codeweavers.com>
|
||||
---
|
||||
dlls/winegstreamer/colorconvert.c | 279 +++++++++++++++++++++++++++++-
|
||||
1 file changed, 274 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/dlls/winegstreamer/colorconvert.c b/dlls/winegstreamer/colorconvert.c
|
||||
index e001c6c827e..a543b9d77af 100644
|
||||
--- a/dlls/winegstreamer/colorconvert.c
|
||||
+++ b/dlls/winegstreamer/colorconvert.c
|
||||
@@ -51,6 +51,10 @@ struct color_converter
|
||||
IMFMediaType *input_type;
|
||||
IMFMediaType *output_type;
|
||||
CRITICAL_SECTION cs;
|
||||
+ BOOL buffer_inflight;
|
||||
+ LONGLONG buffer_pts, buffer_dur;
|
||||
+ struct wg_parser *parser;
|
||||
+ struct wg_parser_stream *stream;
|
||||
};
|
||||
|
||||
static struct color_converter *impl_color_converter_from_IMFTransform(IMFTransform *iface)
|
||||
@@ -98,6 +102,10 @@ static ULONG WINAPI color_converter_Release(IMFTransform *iface)
|
||||
DeleteCriticalSection(&transform->cs);
|
||||
if (transform->output_type)
|
||||
IMFMediaType_Release(transform->output_type);
|
||||
+ if (transform->stream)
|
||||
+ unix_funcs->wg_parser_disconnect(transform->parser);
|
||||
+ if (transform->parser)
|
||||
+ unix_funcs->wg_parser_destroy(transform->parser);
|
||||
free(transform);
|
||||
}
|
||||
|
||||
@@ -263,6 +271,7 @@ static HRESULT WINAPI color_converter_SetInputType(IMFTransform *iface, DWORD id
|
||||
struct color_converter *converter = impl_color_converter_from_IMFTransform(iface);
|
||||
UINT64 input_framesize, output_framesize;
|
||||
GUID major_type, subtype;
|
||||
+ struct wg_format format;
|
||||
unsigned int i;
|
||||
HRESULT hr;
|
||||
|
||||
@@ -280,6 +289,11 @@ static HRESULT WINAPI color_converter_SetInputType(IMFTransform *iface, DWORD id
|
||||
|
||||
if (converter->input_type)
|
||||
{
|
||||
+ if (converter->stream)
|
||||
+ {
|
||||
+ unix_funcs->wg_parser_disconnect(converter->parser);
|
||||
+ converter->stream = NULL;
|
||||
+ }
|
||||
IMFMediaType_Release(converter->input_type);
|
||||
converter->input_type = NULL;
|
||||
}
|
||||
@@ -319,6 +333,10 @@ static HRESULT WINAPI color_converter_SetInputType(IMFTransform *iface, DWORD id
|
||||
|
||||
LeaveCriticalSection(&converter->cs);
|
||||
|
||||
+ mf_media_type_to_wg_format(type, &format);
|
||||
+ if (!format.major_type)
|
||||
+ return MF_E_INVALIDTYPE;
|
||||
+
|
||||
if (flags & MFT_SET_TYPE_TEST_ONLY)
|
||||
return S_OK;
|
||||
|
||||
@@ -338,6 +356,21 @@ static HRESULT WINAPI color_converter_SetInputType(IMFTransform *iface, DWORD id
|
||||
converter->input_type = NULL;
|
||||
}
|
||||
|
||||
+ if (converter->stream)
|
||||
+ {
|
||||
+ unix_funcs->wg_parser_disconnect(converter->parser);
|
||||
+ converter->stream = NULL;
|
||||
+ }
|
||||
+
|
||||
+ if (converter->input_type && converter->output_type)
|
||||
+ {
|
||||
+ struct wg_format output_format;
|
||||
+ mf_media_type_to_wg_format(converter->output_type, &output_format);
|
||||
+
|
||||
+ if (SUCCEEDED(hr = unix_funcs->wg_parser_connect_unseekable(converter->parser, &format, 1, &output_format, NULL)))
|
||||
+ converter->stream = unix_funcs->wg_parser_get_stream(converter->parser, 0);
|
||||
+ }
|
||||
+
|
||||
LeaveCriticalSection(&converter->cs);
|
||||
|
||||
return hr;
|
||||
@@ -348,6 +381,7 @@ static HRESULT WINAPI color_converter_SetOutputType(IMFTransform *iface, DWORD i
|
||||
struct color_converter *converter = impl_color_converter_from_IMFTransform(iface);
|
||||
UINT64 input_framesize, output_framesize;
|
||||
GUID major_type, subtype;
|
||||
+ struct wg_format format;
|
||||
unsigned int i;
|
||||
HRESULT hr;
|
||||
|
||||
@@ -365,6 +399,11 @@ static HRESULT WINAPI color_converter_SetOutputType(IMFTransform *iface, DWORD i
|
||||
|
||||
if (converter->output_type)
|
||||
{
|
||||
+ if (converter->stream)
|
||||
+ {
|
||||
+ unix_funcs->wg_parser_disconnect(converter->parser);
|
||||
+ converter->stream = NULL;
|
||||
+ }
|
||||
IMFMediaType_Release(converter->output_type);
|
||||
converter->output_type = NULL;
|
||||
}
|
||||
@@ -404,6 +443,10 @@ static HRESULT WINAPI color_converter_SetOutputType(IMFTransform *iface, DWORD i
|
||||
|
||||
LeaveCriticalSection(&converter->cs);
|
||||
|
||||
+ mf_media_type_to_wg_format(type, &format);
|
||||
+ if (!format.major_type)
|
||||
+ return MF_E_INVALIDTYPE;
|
||||
+
|
||||
if (flags & MFT_SET_TYPE_TEST_ONLY)
|
||||
return S_OK;
|
||||
|
||||
@@ -423,9 +466,24 @@ static HRESULT WINAPI color_converter_SetOutputType(IMFTransform *iface, DWORD i
|
||||
converter->output_type = NULL;
|
||||
}
|
||||
|
||||
+ if (converter->stream)
|
||||
+ {
|
||||
+ unix_funcs->wg_parser_disconnect(converter->parser);
|
||||
+ converter->stream = NULL;
|
||||
+ }
|
||||
+
|
||||
+ if (converter->input_type && converter->output_type)
|
||||
+ {
|
||||
+ struct wg_format input_format;
|
||||
+ mf_media_type_to_wg_format(converter->input_type, &input_format);
|
||||
+
|
||||
+ if (SUCCEEDED(hr = unix_funcs->wg_parser_connect_unseekable(converter->parser, &input_format, 1, &format, NULL)))
|
||||
+ converter->stream = unix_funcs->wg_parser_get_stream(converter->parser, 0);
|
||||
+ }
|
||||
+
|
||||
LeaveCriticalSection(&converter->cs);
|
||||
|
||||
- return S_OK;
|
||||
+ return hr;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI color_converter_GetInputCurrentType(IMFTransform *iface, DWORD id, IMFMediaType **type)
|
||||
@@ -479,17 +537,221 @@ 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);
|
||||
+ struct color_converter *converter = impl_color_converter_from_IMFTransform(iface);
|
||||
+ IMFMediaBuffer *buffer = NULL;
|
||||
+ unsigned char *buffer_data;
|
||||
+ DWORD buffer_size;
|
||||
+ uint64_t offset;
|
||||
+ uint32_t size;
|
||||
+ void *data;
|
||||
+ HRESULT hr;
|
||||
|
||||
- return E_NOTIMPL;
|
||||
+ 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->stream)
|
||||
+ {
|
||||
+ hr = MF_E_TRANSFORM_TYPE_NOT_SET;
|
||||
+ goto done;
|
||||
+ }
|
||||
+
|
||||
+ if (converter->buffer_inflight)
|
||||
+ {
|
||||
+ hr = MF_E_NOTACCEPTING;
|
||||
+ goto done;
|
||||
+ }
|
||||
+
|
||||
+ if (FAILED(hr = IMFSample_ConvertToContiguousBuffer(sample, &buffer)))
|
||||
+ goto done;
|
||||
+
|
||||
+ if (FAILED(hr = IMFMediaBuffer_Lock(buffer, &buffer_data, NULL, &buffer_size)))
|
||||
+ goto done;
|
||||
+
|
||||
+ for (;;)
|
||||
+ {
|
||||
+ if (!unix_funcs->wg_parser_get_read_request(converter->parser, &data, &offset, &size))
|
||||
+ continue;
|
||||
+
|
||||
+ memcpy(data, buffer_data, min(buffer_size, size));
|
||||
+
|
||||
+ unix_funcs->wg_parser_complete_read_request(converter->parser, WG_READ_SUCCESS, buffer_size);
|
||||
+
|
||||
+ if (buffer_size <= size)
|
||||
+ break;
|
||||
+
|
||||
+ buffer_data += size;
|
||||
+ buffer_size -= size;
|
||||
+ }
|
||||
+
|
||||
+ IMFMediaBuffer_Unlock(buffer);
|
||||
+ converter->buffer_inflight = TRUE;
|
||||
+ if (FAILED(IMFSample_GetSampleTime(sample, &converter->buffer_pts)))
|
||||
+ converter->buffer_pts = -1;
|
||||
+ if (FAILED(IMFSample_GetSampleDuration(sample, &converter->buffer_dur)))
|
||||
+ converter->buffer_dur = -1;
|
||||
+
|
||||
+done:
|
||||
+ if (buffer)
|
||||
+ IMFMediaBuffer_Release(buffer);
|
||||
+ LeaveCriticalSection(&converter->cs);
|
||||
+ return hr;
|
||||
}
|
||||
|
||||
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);
|
||||
+ struct color_converter *converter = impl_color_converter_from_IMFTransform(iface);
|
||||
+ IMFSample *allocated_sample = NULL;
|
||||
+ IMFMediaBuffer *buffer = NULL;
|
||||
+ struct wg_parser_event event;
|
||||
+ unsigned char *buffer_data;
|
||||
+ DWORD buffer_len;
|
||||
+ HRESULT hr = S_OK;
|
||||
|
||||
- return E_NOTIMPL;
|
||||
+ 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->stream)
|
||||
+ {
|
||||
+ hr = MF_E_TRANSFORM_TYPE_NOT_SET;
|
||||
+ goto done;
|
||||
+ }
|
||||
+
|
||||
+ if (!converter->buffer_inflight)
|
||||
+ {
|
||||
+ hr = MF_E_TRANSFORM_NEED_MORE_INPUT;
|
||||
+ goto done;
|
||||
+ }
|
||||
+
|
||||
+ for (;;)
|
||||
+ {
|
||||
+ unix_funcs->wg_parser_stream_get_event(converter->stream, &event);
|
||||
+
|
||||
+ switch (event.type)
|
||||
+ {
|
||||
+ case WG_PARSER_EVENT_BUFFER:
|
||||
+ break;
|
||||
+
|
||||
+ case WG_PARSER_EVENT_SEGMENT:
|
||||
+ continue;
|
||||
+
|
||||
+ default:
|
||||
+ WARN("Unexpected event, %u\n", event.type);
|
||||
+ continue;
|
||||
+ }
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ if (!samples[0].pSample)
|
||||
+ {
|
||||
+ if (FAILED(hr = MFCreateMemoryBuffer(event.u.buffer.size, &buffer)))
|
||||
+ {
|
||||
+ ERR("Failed to create buffer, hr %#x.\n", hr);
|
||||
+ goto done;
|
||||
+ }
|
||||
+
|
||||
+ if (FAILED(hr = MFCreateSample(&allocated_sample)))
|
||||
+ {
|
||||
+ ERR("Failed to create sample, hr %#x.\n", hr);
|
||||
+ goto done;
|
||||
+ }
|
||||
+
|
||||
+ samples[0].pSample = allocated_sample;
|
||||
+
|
||||
+ if (FAILED(hr = IMFSample_AddBuffer(samples[0].pSample, buffer)))
|
||||
+ {
|
||||
+ ERR("Failed to add buffer, hr %#x.\n", hr);
|
||||
+ goto done;
|
||||
+ }
|
||||
+
|
||||
+ IMFMediaBuffer_Release(buffer);
|
||||
+ buffer = NULL;
|
||||
+ }
|
||||
+
|
||||
+ if (FAILED(hr = IMFSample_ConvertToContiguousBuffer(samples[0].pSample, &buffer)))
|
||||
+ {
|
||||
+ ERR("Failed to get buffer from sample, hr %#x.\n", hr);
|
||||
+ goto done;
|
||||
+ }
|
||||
+
|
||||
+ if (FAILED(hr = IMFMediaBuffer_GetMaxLength(buffer, &buffer_len)))
|
||||
+ {
|
||||
+ ERR("Failed to get buffer size, hr %#x.\n", hr);
|
||||
+ goto done;
|
||||
+ }
|
||||
+
|
||||
+ if (buffer_len < event.u.buffer.size)
|
||||
+ {
|
||||
+ WARN("Client's buffer is smaller (%u bytes) than the output sample (%u bytes)\n",
|
||||
+ buffer_len, event.u.buffer.size);
|
||||
+
|
||||
+ hr = MF_E_BUFFERTOOSMALL;
|
||||
+ goto done;
|
||||
+ }
|
||||
+
|
||||
+ if (FAILED(hr = IMFMediaBuffer_SetCurrentLength(buffer, event.u.buffer.size)))
|
||||
+ {
|
||||
+ ERR("Failed to set size, hr %#x.\n", hr);
|
||||
+ goto done;
|
||||
+ }
|
||||
+
|
||||
+ if (FAILED(hr = IMFMediaBuffer_Lock(buffer, &buffer_data, NULL, NULL)))
|
||||
+ {
|
||||
+ ERR("Failed to lock buffer hr %#x.\n", hr);
|
||||
+ goto done;
|
||||
+ }
|
||||
+
|
||||
+ if (!unix_funcs->wg_parser_stream_copy_buffer(converter->stream, buffer_data, 0, event.u.buffer.size))
|
||||
+ {
|
||||
+ ERR("Failed to copy buffer.\n");
|
||||
+ IMFMediaBuffer_Unlock(buffer);
|
||||
+ hr = E_FAIL;
|
||||
+ goto done;
|
||||
+ }
|
||||
+
|
||||
+ IMFMediaBuffer_Unlock(buffer);
|
||||
+
|
||||
+ unix_funcs->wg_parser_stream_release_buffer(converter->stream);
|
||||
+ converter->buffer_inflight = FALSE;
|
||||
+
|
||||
+ if (converter->buffer_pts != -1)
|
||||
+ IMFSample_SetSampleTime(samples[0].pSample, converter->buffer_pts);
|
||||
+ if (converter->buffer_dur != -1)
|
||||
+ IMFSample_SetSampleDuration(samples[0].pSample, converter->buffer_dur);
|
||||
+
|
||||
+ samples[0].dwStatus = 0;
|
||||
+ samples[0].pEvents = NULL;
|
||||
+
|
||||
+ done:
|
||||
+ if (buffer)
|
||||
+ IMFMediaBuffer_Release(buffer);
|
||||
+ if (FAILED(hr) && allocated_sample)
|
||||
+ {
|
||||
+ IMFSample_Release(allocated_sample);
|
||||
+ samples[0].pSample = NULL;
|
||||
+ }
|
||||
+ LeaveCriticalSection(&converter->cs);
|
||||
+ return hr;
|
||||
}
|
||||
|
||||
static const IMFTransformVtbl color_converter_vtbl =
|
||||
@@ -537,6 +799,13 @@ HRESULT color_converter_create(REFIID riid, void **ret)
|
||||
InitializeCriticalSection(&object->cs);
|
||||
object->cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": color_converter_lock");
|
||||
|
||||
+ if (!(object->parser = unix_funcs->wg_raw_media_converter_create()))
|
||||
+ {
|
||||
+ ERR("Failed to create video converter due to GStreamer error.\n");
|
||||
+ IMFTransform_Release(&object->IMFTransform_iface);
|
||||
+ return E_OUTOFMEMORY;
|
||||
+ }
|
||||
+
|
||||
*ret = &object->IMFTransform_iface;
|
||||
return S_OK;
|
||||
}
|
||||
--
|
||||
2.30.2
|
||||
|
@ -1,45 +0,0 @@
|
||||
From fe0175d8676cbd15ddeac07876e726ef76eef7b5 Mon Sep 17 00:00:00 2001
|
||||
From: Derek Lesho <dlesho@codeweavers.com>
|
||||
Date: Mon, 2 Nov 2020 10:18:27 -0600
|
||||
Subject: [PATCH] winegstreamer: Set MF_PD_MIME_TYPE on source's presentation
|
||||
descriptor.
|
||||
|
||||
Signed-off-by: Derek Lesho <dlesho@codeweavers.com>
|
||||
---
|
||||
dlls/winegstreamer/media_source.c | 13 +++++++++++++
|
||||
1 file changed, 13 insertions(+)
|
||||
|
||||
diff --git a/dlls/winegstreamer/media_source.c b/dlls/winegstreamer/media_source.c
|
||||
index 5f3457e50b0..1bbbb2ffd81 100644
|
||||
--- a/dlls/winegstreamer/media_source.c
|
||||
+++ b/dlls/winegstreamer/media_source.c
|
||||
@@ -1377,6 +1377,7 @@ static HRESULT media_source_constructor(IMFByteStream *bytestream, struct media_
|
||||
GST_STATIC_PAD_TEMPLATE("mf_src", GST_PAD_SRC, GST_PAD_ALWAYS, GST_STATIC_CAPS_ANY);
|
||||
|
||||
IMFStreamDescriptor **descriptors = NULL;
|
||||
+ IMFAttributes *byte_stream_attributes;
|
||||
struct media_source *object;
|
||||
gint64 total_pres_time = 0;
|
||||
DWORD bytestream_caps;
|
||||
@@ -1520,6 +1521,18 @@ static HRESULT media_source_constructor(IMFByteStream *bytestream, struct media_
|
||||
if (object->stream_count)
|
||||
IMFPresentationDescriptor_SetUINT64(object->pres_desc, &MF_PD_DURATION, total_pres_time / 100);
|
||||
|
||||
+ if (SUCCEEDED(IMFByteStream_QueryInterface(object->byte_stream, &IID_IMFAttributes, (void **)&byte_stream_attributes)))
|
||||
+ {
|
||||
+ WCHAR *mimeW = NULL;
|
||||
+ DWORD length;
|
||||
+ if (SUCCEEDED(IMFAttributes_GetAllocatedString(byte_stream_attributes, &MF_BYTESTREAM_CONTENT_TYPE, &mimeW, &length)))
|
||||
+ {
|
||||
+ IMFPresentationDescriptor_SetString(object->pres_desc, &MF_PD_MIME_TYPE, mimeW);
|
||||
+ CoTaskMemFree(mimeW);
|
||||
+ }
|
||||
+ IMFAttributes_Release(byte_stream_attributes);
|
||||
+ }
|
||||
+
|
||||
object->state = SOURCE_STOPPED;
|
||||
|
||||
*out_media_source = object;
|
||||
--
|
||||
2.29.2
|
||||
|
@ -1,19 +1,19 @@
|
||||
From d68df1b4131caa500cea5c4241be3c55b2728d4c Mon Sep 17 00:00:00 2001
|
||||
From ebb43b337b5733e4b3530b4b04fcda0afa517852 Mon Sep 17 00:00:00 2001
|
||||
From: Derek Lesho <dlesho@codeweavers.com>
|
||||
Date: Thu, 3 Dec 2020 16:02:20 -0500
|
||||
Subject: [PATCH] winegstreamer: Implement ::ProcessMessage for color
|
||||
Date: Wed, 17 Mar 2021 16:50:47 -0400
|
||||
Subject: [PATCH 28/39] winegstreamer: Implement ::ProcessMessage for color
|
||||
conversion MFT.
|
||||
|
||||
Signed-off-by: Derek Lesho <dlesho@codeweavers.com>
|
||||
---
|
||||
dlls/winegstreamer/colorconvert.c | 11 +++++++++--
|
||||
1 file changed, 9 insertions(+), 2 deletions(-)
|
||||
dlls/winegstreamer/colorconvert.c | 12 ++++++++++--
|
||||
1 file changed, 10 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/dlls/winegstreamer/colorconvert.c b/dlls/winegstreamer/colorconvert.c
|
||||
index b77f3358c52..c07ef22acc3 100644
|
||||
index a543b9d77af..8d2f7a7d643 100644
|
||||
--- a/dlls/winegstreamer/colorconvert.c
|
||||
+++ b/dlls/winegstreamer/colorconvert.c
|
||||
@@ -477,9 +477,16 @@ static HRESULT WINAPI color_converter_ProcessEvent(IMFTransform *iface, DWORD id
|
||||
@@ -530,9 +530,17 @@ static HRESULT WINAPI color_converter_ProcessEvent(IMFTransform *iface, DWORD id
|
||||
|
||||
static HRESULT WINAPI color_converter_ProcessMessage(IMFTransform *iface, MFT_MESSAGE_TYPE message, ULONG_PTR param)
|
||||
{
|
||||
@ -23,6 +23,7 @@ index b77f3358c52..c07ef22acc3 100644
|
||||
- return E_NOTIMPL;
|
||||
+ switch(message)
|
||||
+ {
|
||||
+ case MFT_MESSAGE_COMMAND_FLUSH:
|
||||
+ case MFT_MESSAGE_NOTIFY_BEGIN_STREAMING:
|
||||
+ return S_OK;
|
||||
+ default:
|
||||
@ -33,5 +34,5 @@ index b77f3358c52..c07ef22acc3 100644
|
||||
|
||||
static HRESULT WINAPI color_converter_ProcessInput(IMFTransform *iface, DWORD id, IMFSample *sample, DWORD flags)
|
||||
--
|
||||
2.29.2
|
||||
2.30.2
|
||||
|
@ -1,141 +0,0 @@
|
||||
From 7bb33ab950fe2fdddcd5e7409827be982044f813 Mon Sep 17 00:00:00 2001
|
||||
From: Derek Lesho <dlesho@codeweavers.com>
|
||||
Date: Tue, 15 Sep 2020 14:25:26 -0500
|
||||
Subject: [PATCH] winegstreamer: Insert parser into pipeline to rectify type
|
||||
differences.
|
||||
|
||||
Signed-off-by: Derek Lesho <dlesho@codeweavers.com>
|
||||
---
|
||||
dlls/winegstreamer/media_source.c | 95 ++++++++++++++++++++++++++++++-
|
||||
1 file changed, 92 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/dlls/winegstreamer/media_source.c b/dlls/winegstreamer/media_source.c
|
||||
index 1bbbb2ffd81..aecf4f27375 100644
|
||||
--- a/dlls/winegstreamer/media_source.c
|
||||
+++ b/dlls/winegstreamer/media_source.c
|
||||
@@ -791,8 +791,17 @@ static const IMFMediaStreamVtbl media_stream_vtbl =
|
||||
media_stream_RequestSample
|
||||
};
|
||||
|
||||
-/* Setup a chain of elements which should hopefully allow transformations to any IMFMediaType
|
||||
- the user throws at us through gstreamer's caps negotiation. */
|
||||
+/* There are two paths this function can take.
|
||||
+ 1) In the first path, we are acting as a real media source, purely demuxing the input data,
|
||||
+ in whichever format it may be in, and passing it along. However, there can be different ways
|
||||
+ to interpret the same streams. Subtypes in MF usually carry an implicit meaning, so we define
|
||||
+ what caps an IMFMediaType corresponds to in mfplat.c, and insert a parser between decodebin
|
||||
+ and the appsink, which usually can resolve these differences. As an example, MFVideoFormat_H264
|
||||
+ implies stream-format=byte-stream, and inserting h264parse can transform stream-format=avc
|
||||
+ into stream-format=byte-stream.
|
||||
+ 2) In the second path, we are dealing with x-raw output from decodebin. In this case, we just
|
||||
+ have to setup a chain of elements which should hopefully allow transformations to any IMFMediaType
|
||||
+ the user throws at us through gstreamer's caps negotiation.*/
|
||||
static HRESULT media_stream_connect_to_sink(struct media_stream *stream)
|
||||
{
|
||||
GstCaps *source_caps = gst_pad_query_caps(stream->their_src, NULL);
|
||||
@@ -832,7 +841,68 @@ static HRESULT media_stream_connect_to_sink(struct media_stream *stream)
|
||||
}
|
||||
else
|
||||
{
|
||||
- stream->my_sink = gst_element_get_static_pad(stream->appsink, "sink");
|
||||
+ GstElement *parser = NULL;
|
||||
+ GstCaps *target_caps;
|
||||
+
|
||||
+ assert(gst_caps_is_fixed(source_caps));
|
||||
+
|
||||
+ if (!(target_caps = make_mf_compatible_caps(source_caps)))
|
||||
+ {
|
||||
+ gst_caps_unref(source_caps);
|
||||
+ return E_FAIL;
|
||||
+ }
|
||||
+
|
||||
+ g_object_set(stream->appsink, "caps", target_caps, NULL);
|
||||
+
|
||||
+ if (!(gst_caps_is_equal(source_caps, target_caps)))
|
||||
+ {
|
||||
+ GList *parser_list_one, *parser_list_two;
|
||||
+ GstElementFactory *parser_factory;
|
||||
+
|
||||
+ parser_list_one = gst_element_factory_list_get_elements(GST_ELEMENT_FACTORY_TYPE_PARSER, 1);
|
||||
+
|
||||
+ parser_list_two = gst_element_factory_list_filter(parser_list_one, source_caps, GST_PAD_SINK, 0);
|
||||
+ gst_plugin_feature_list_free(parser_list_one);
|
||||
+ parser_list_one = parser_list_two;
|
||||
+
|
||||
+ parser_list_two = gst_element_factory_list_filter(parser_list_one, target_caps, GST_PAD_SRC, 0);
|
||||
+ gst_plugin_feature_list_free(parser_list_one);
|
||||
+ parser_list_one = parser_list_two;
|
||||
+ gst_caps_unref(target_caps);
|
||||
+
|
||||
+ if (!(g_list_length(parser_list_one)))
|
||||
+ {
|
||||
+ gst_plugin_feature_list_free(parser_list_one);
|
||||
+ ERR("Failed to find parser for stream\n");
|
||||
+ gst_caps_unref(source_caps);
|
||||
+ return E_FAIL;
|
||||
+ }
|
||||
+
|
||||
+ parser_factory = g_list_first(parser_list_one)->data;
|
||||
+ TRACE("Found parser %s.\n", GST_ELEMENT_NAME(parser_factory));
|
||||
+
|
||||
+ parser = gst_element_factory_create(parser_factory, NULL);
|
||||
+
|
||||
+ gst_plugin_feature_list_free(parser_list_one);
|
||||
+
|
||||
+ if (!parser)
|
||||
+ {
|
||||
+ gst_caps_unref(source_caps);
|
||||
+ return E_FAIL;
|
||||
+ }
|
||||
+
|
||||
+ gst_bin_add(GST_BIN(stream->parent_source->container), parser);
|
||||
+
|
||||
+ assert(gst_element_link(parser, stream->appsink));
|
||||
+
|
||||
+ gst_element_sync_state_with_parent(parser);
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ gst_caps_unref(target_caps);
|
||||
+ }
|
||||
+
|
||||
+ stream->my_sink = gst_element_get_static_pad(parser ? parser : stream->appsink, "sink");
|
||||
}
|
||||
|
||||
if (gst_pad_link(stream->their_src, stream->my_sink) != GST_PAD_LINK_OK)
|
||||
@@ -1326,6 +1396,23 @@ static const IMFSeekInfoVtbl IMFSeekInfo_vtbl =
|
||||
source_seek_info_GetNearestKeyFrames,
|
||||
};
|
||||
|
||||
+/* If this callback is extended to use any significant win32 APIs, a wrapper function
|
||||
+ should be added */
|
||||
+gboolean stream_found(GstElement *bin, GstPad *pad, GstCaps *caps, gpointer user)
|
||||
+{
|
||||
+ GstCaps *target_caps;
|
||||
+
|
||||
+ /* if the stream can be converted into an MF compatible type, we'll go that route
|
||||
+ otherwise, we'll rely on decodebin for the whole process */
|
||||
+
|
||||
+ if ((target_caps = make_mf_compatible_caps(caps)))
|
||||
+ {
|
||||
+ gst_caps_unref(target_caps);
|
||||
+ return FALSE;
|
||||
+ }
|
||||
+ return TRUE;
|
||||
+}
|
||||
+
|
||||
static void stream_added(GstElement *element, GstPad *pad, gpointer user)
|
||||
{
|
||||
struct media_source *source = user;
|
||||
@@ -1445,6 +1532,8 @@ static HRESULT media_source_constructor(IMFByteStream *bytestream, struct media_
|
||||
|
||||
gst_bin_add(GST_BIN(object->container), object->decodebin);
|
||||
|
||||
+ if(!GetEnvironmentVariableA("MF_DECODE_IN_SOURCE", NULL, 0))
|
||||
+ g_signal_connect(object->decodebin, "autoplug-continue", G_CALLBACK(stream_found), object);
|
||||
g_signal_connect(object->decodebin, "pad-added", G_CALLBACK(mf_src_stream_added_wrapper), object);
|
||||
g_signal_connect(object->decodebin, "pad-removed", G_CALLBACK(mf_src_stream_removed_wrapper), object);
|
||||
g_signal_connect(object->decodebin, "no-more-pads", G_CALLBACK(mf_src_no_more_pads_wrapper), object);
|
||||
--
|
||||
2.29.2
|
||||
|
@ -0,0 +1,95 @@
|
||||
From 5a5376981522aba2a5a6f7facb44373584488c7f Mon Sep 17 00:00:00 2001
|
||||
From: Derek Lesho <dlesho@codeweavers.com>
|
||||
Date: Wed, 17 Mar 2021 17:01:11 -0400
|
||||
Subject: [PATCH 29/39] winegstreamer: Implement ::Get(Input/Output)StreamInfo
|
||||
for color conversion transform.
|
||||
|
||||
Signed-off-by: Derek Lesho <dlesho@codeweavers.com>
|
||||
---
|
||||
dlls/winegstreamer/colorconvert.c | 64 +++++++++++++++++++++++++++++--
|
||||
1 file changed, 60 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/dlls/winegstreamer/colorconvert.c b/dlls/winegstreamer/colorconvert.c
|
||||
index 8d2f7a7d643..6f3723b2b1e 100644
|
||||
--- a/dlls/winegstreamer/colorconvert.c
|
||||
+++ b/dlls/winegstreamer/colorconvert.c
|
||||
@@ -141,16 +141,72 @@ 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);
|
||||
+ struct color_converter *converter = impl_color_converter_from_IMFTransform(iface);
|
||||
+ UINT64 framesize;
|
||||
+ GUID subtype;
|
||||
|
||||
- return E_NOTIMPL;
|
||||
+ TRACE("%p %u %p.\n", iface, id, info);
|
||||
+
|
||||
+ if (id != 0)
|
||||
+ return MF_E_INVALIDSTREAMNUMBER;
|
||||
+
|
||||
+ info->dwFlags = MFT_INPUT_STREAM_WHOLE_SAMPLES | MFT_INPUT_STREAM_DOES_NOT_ADDREF | MFT_INPUT_STREAM_FIXED_SAMPLE_SIZE;
|
||||
+ info->cbMaxLookahead = 0;
|
||||
+ info->cbAlignment = 0;
|
||||
+ info->hnsMaxLatency = 0;
|
||||
+ info->cbSize = 0;
|
||||
+
|
||||
+ EnterCriticalSection(&converter->cs);
|
||||
+
|
||||
+ if (converter->input_type)
|
||||
+ {
|
||||
+ if (SUCCEEDED(IMFMediaType_GetGUID(converter->input_type, &MF_MT_SUBTYPE, &subtype)) &&
|
||||
+ SUCCEEDED(IMFMediaType_GetUINT64(converter->input_type, &MF_MT_FRAME_SIZE, &framesize)))
|
||||
+ {
|
||||
+ MFCalculateImageSize(&subtype, framesize >> 32, (UINT32) framesize, &info->cbSize);
|
||||
+ }
|
||||
+
|
||||
+ if (!info->cbSize)
|
||||
+ WARN("Failed to get desired input buffer size, the non-provided sample path will likely break\n");
|
||||
+ }
|
||||
+
|
||||
+ LeaveCriticalSection(&converter->cs);
|
||||
+
|
||||
+ 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);
|
||||
+ struct color_converter *converter = impl_color_converter_from_IMFTransform(iface);
|
||||
+ UINT64 framesize;
|
||||
+ GUID subtype;
|
||||
|
||||
- return E_NOTIMPL;
|
||||
+ TRACE("%p %u %p.\n", iface, id, info);
|
||||
+
|
||||
+ if (id != 0)
|
||||
+ return MF_E_INVALIDSTREAMNUMBER;
|
||||
+
|
||||
+ info->dwFlags = MFT_OUTPUT_STREAM_FIXED_SAMPLE_SIZE | MFT_OUTPUT_STREAM_CAN_PROVIDE_SAMPLES | MFT_OUTPUT_STREAM_WHOLE_SAMPLES | MFT_OUTPUT_STREAM_SINGLE_SAMPLE_PER_BUFFER;
|
||||
+ info->cbAlignment = 0;
|
||||
+ info->cbSize = 0;
|
||||
+
|
||||
+ EnterCriticalSection(&converter->cs);
|
||||
+
|
||||
+ if (converter->output_type)
|
||||
+ {
|
||||
+ if (SUCCEEDED(IMFMediaType_GetGUID(converter->output_type, &MF_MT_SUBTYPE, &subtype)) &&
|
||||
+ SUCCEEDED(IMFMediaType_GetUINT64(converter->output_type, &MF_MT_FRAME_SIZE, &framesize)))
|
||||
+ {
|
||||
+ MFCalculateImageSize(&subtype, framesize >> 32, (UINT32) framesize, &info->cbSize);
|
||||
+ }
|
||||
+
|
||||
+ if (!info->cbSize)
|
||||
+ WARN("Failed to get desired output buffer size, the non-provided sample path will likely break\n");
|
||||
+ }
|
||||
+
|
||||
+ LeaveCriticalSection(&converter->cs);
|
||||
+
|
||||
+ return S_OK;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI color_converter_GetAttributes(IMFTransform *iface, IMFAttributes **attributes)
|
||||
--
|
||||
2.30.2
|
||||
|
@ -1,113 +0,0 @@
|
||||
From d95e8d8349b884800066c9af1ea9a7c7492ca02c Mon Sep 17 00:00:00 2001
|
||||
From: Derek Lesho <dlesho@codeweavers.com>
|
||||
Date: Tue, 24 Mar 2020 16:00:26 -0500
|
||||
Subject: [PATCH] winegstreamer: Translate H.264 caps to attributes.
|
||||
|
||||
Signed-off-by: Derek Lesho <dlesho@codeweavers.com>
|
||||
---
|
||||
dlls/winegstreamer/mfplat.c | 75 +++++++++++++++++++++++++++++++++++++
|
||||
1 file changed, 75 insertions(+)
|
||||
|
||||
diff --git a/dlls/winegstreamer/mfplat.c b/dlls/winegstreamer/mfplat.c
|
||||
index a2873907437..afce3d9831a 100644
|
||||
--- a/dlls/winegstreamer/mfplat.c
|
||||
+++ b/dlls/winegstreamer/mfplat.c
|
||||
@@ -26,6 +26,7 @@
|
||||
#include "gst_private.h"
|
||||
#include "mfapi.h"
|
||||
#include "mfidl.h"
|
||||
+#include "codecapi.h"
|
||||
|
||||
#include "wine/debug.h"
|
||||
#include "wine/heap.h"
|
||||
@@ -629,6 +630,74 @@ IMFMediaType *mf_media_type_from_caps(const GstCaps *caps)
|
||||
}
|
||||
}
|
||||
}
|
||||
+ else if (!(strcmp(mime_type, "video/x-h264")))
|
||||
+ {
|
||||
+ const char *profile, *level;
|
||||
+
|
||||
+ /* validation */
|
||||
+ if (strcmp(gst_structure_get_string(info, "stream-format"), "byte-stream"))
|
||||
+ return NULL;
|
||||
+ if (strcmp(gst_structure_get_string(info, "alignment"), "au"))
|
||||
+ return NULL;
|
||||
+ if (gst_structure_get_value(info, "codec-data"))
|
||||
+ return NULL;
|
||||
+
|
||||
+ /* conversion */
|
||||
+ IMFMediaType_SetGUID(media_type, &MF_MT_SUBTYPE, &MFVideoFormat_H264);
|
||||
+ IMFMediaType_SetUINT32(media_type, &MF_MT_COMPRESSED, TRUE);
|
||||
+
|
||||
+ if ((profile = gst_structure_get_string(info, "profile")))
|
||||
+ {
|
||||
+ if (!(strcmp(profile, "main")))
|
||||
+ IMFMediaType_SetUINT32(media_type, &MF_MT_MPEG2_PROFILE, eAVEncH264VProfile_Main);
|
||||
+ else if (!(strcmp(profile, "high")))
|
||||
+ IMFMediaType_SetUINT32(media_type, &MF_MT_MPEG2_PROFILE, eAVEncH264VProfile_High);
|
||||
+ else if (!(strcmp(profile, "high-4:4:4")))
|
||||
+ IMFMediaType_SetUINT32(media_type, &MF_MT_MPEG2_PROFILE, eAVEncH264VProfile_444);
|
||||
+ else
|
||||
+ FIXME("Unrecognized profile %s\n", profile);
|
||||
+ }
|
||||
+ if ((level = gst_structure_get_string(info, "level")))
|
||||
+ {
|
||||
+ unsigned int i;
|
||||
+
|
||||
+ const static struct
|
||||
+ {
|
||||
+ const char *name;
|
||||
+ enum eAVEncH264VLevel val;
|
||||
+ } levels[] =
|
||||
+ {
|
||||
+ {"1", eAVEncH264VLevel1},
|
||||
+ {"1.1", eAVEncH264VLevel1_1},
|
||||
+ {"1.2", eAVEncH264VLevel1_2},
|
||||
+ {"1.3", eAVEncH264VLevel1_3},
|
||||
+ {"2", eAVEncH264VLevel2},
|
||||
+ {"2.1", eAVEncH264VLevel2_1},
|
||||
+ {"2.2", eAVEncH264VLevel2_2},
|
||||
+ {"3", eAVEncH264VLevel3},
|
||||
+ {"3.1", eAVEncH264VLevel3_1},
|
||||
+ {"3.2", eAVEncH264VLevel3_2},
|
||||
+ {"4", eAVEncH264VLevel4},
|
||||
+ {"4.1", eAVEncH264VLevel4_1},
|
||||
+ {"4.2", eAVEncH264VLevel4_2},
|
||||
+ {"5", eAVEncH264VLevel5},
|
||||
+ {"5.1", eAVEncH264VLevel5_1},
|
||||
+ {"5.2", eAVEncH264VLevel5_2},
|
||||
+ };
|
||||
+ for (i = 0 ; i < ARRAY_SIZE(levels); i++)
|
||||
+ {
|
||||
+ if (!(strcmp(level, levels[i].name)))
|
||||
+ {
|
||||
+ IMFMediaType_SetUINT32(media_type, &MF_MT_MPEG2_LEVEL, levels[i].val);
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+ if (i == ARRAY_SIZE(levels))
|
||||
+ {
|
||||
+ FIXME("Unrecognized level %s", level);
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
else
|
||||
{
|
||||
FIXME("Unrecognized video format %s\n", mime_type);
|
||||
@@ -754,6 +823,12 @@ GstCaps *make_mf_compatible_caps(GstCaps *caps)
|
||||
}
|
||||
}
|
||||
}
|
||||
+ else if (!strcmp(mime_type, "video/x-h264"))
|
||||
+ {
|
||||
+ gst_caps_set_simple(ret, "stream-format", G_TYPE_STRING, "byte-stream", NULL);
|
||||
+ gst_caps_set_simple(ret, "alignment", G_TYPE_STRING, "au", NULL);
|
||||
+ gst_structure_remove_field(structure, "codec_data");
|
||||
+ }
|
||||
|
||||
if ((media_type = mf_media_type_from_caps(ret)))
|
||||
IMFMediaType_Release(media_type);
|
||||
--
|
||||
2.29.2
|
||||
|
@ -0,0 +1,28 @@
|
||||
From e602bc2817910624da0da383933889871e61c0f7 Mon Sep 17 00:00:00 2001
|
||||
From: Derek Lesho <dlesho@codeweavers.com>
|
||||
Date: Thu, 18 Mar 2021 13:53:42 -0400
|
||||
Subject: [PATCH 30/39] mf/topology: Forward failure from ::SetOutputType when
|
||||
resolving topology.
|
||||
|
||||
Signed-off-by: Derek Lesho <dlesho@codeweavers.com>
|
||||
---
|
||||
dlls/mf/topology.c | 3 +--
|
||||
1 file changed, 1 insertion(+), 2 deletions(-)
|
||||
|
||||
diff --git a/dlls/mf/topology.c b/dlls/mf/topology.c
|
||||
index f97c0cc75d3..34459912fb0 100644
|
||||
--- a/dlls/mf/topology.c
|
||||
+++ b/dlls/mf/topology.c
|
||||
@@ -2122,8 +2122,7 @@ static HRESULT connect_to_sink(struct transform_output_type *output_type, struct
|
||||
hr = IMFMediaTypeHandler_SetCurrentMediaType(context->sink_handler, output_type->type);
|
||||
if (SUCCEEDED(hr))
|
||||
hr = IMFTransform_SetOutputType(output_type->transform, 0, output_type->type, 0);
|
||||
-
|
||||
- return S_OK;
|
||||
+ return hr;
|
||||
}
|
||||
|
||||
static HRESULT connect_to_converter(struct transform_output_type *output_type, struct connect_context *context)
|
||||
--
|
||||
2.30.2
|
||||
|
@ -1,82 +0,0 @@
|
||||
From 10dcfecc84651a4c2a270960c585c735ff09ec1c Mon Sep 17 00:00:00 2001
|
||||
From: Derek Lesho <dlesho@codeweavers.com>
|
||||
Date: Tue, 24 Mar 2020 16:01:20 -0500
|
||||
Subject: [PATCH] winegstreamer: Translate WMV caps to attributes.
|
||||
|
||||
Signed-off-by: Derek Lesho <dlesho@codeweavers.com>
|
||||
---
|
||||
dlls/winegstreamer/mfplat.c | 51 +++++++++++++++++++++++++++++++++++++
|
||||
1 file changed, 51 insertions(+)
|
||||
|
||||
diff --git a/dlls/winegstreamer/mfplat.c b/dlls/winegstreamer/mfplat.c
|
||||
index afce3d9831a..6906fd3faeb 100644
|
||||
--- a/dlls/winegstreamer/mfplat.c
|
||||
+++ b/dlls/winegstreamer/mfplat.c
|
||||
@@ -564,6 +564,24 @@ uncompressed_video_formats[] =
|
||||
{&MFVideoFormat_RGB555, GST_VIDEO_FORMAT_BGR15},
|
||||
};
|
||||
|
||||
+static void codec_data_to_user_data(GstStructure *structure, IMFMediaType *type)
|
||||
+{
|
||||
+ const GValue *codec_data;
|
||||
+
|
||||
+ if ((codec_data = gst_structure_get_value(structure, "codec_data")))
|
||||
+ {
|
||||
+ GstBuffer *codec_data_buffer = gst_value_get_buffer(codec_data);
|
||||
+ if (codec_data_buffer)
|
||||
+ {
|
||||
+ gsize codec_data_size = gst_buffer_get_size(codec_data_buffer);
|
||||
+ gpointer codec_data_raw = heap_alloc(codec_data_size);
|
||||
+ gst_buffer_extract(codec_data_buffer, 0, codec_data_raw, codec_data_size);
|
||||
+ IMFMediaType_SetBlob(type, &MF_MT_USER_DATA, codec_data_raw, codec_data_size);
|
||||
+ heap_free(codec_data_raw);
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
/* returns NULL if doesn't match exactly */
|
||||
IMFMediaType *mf_media_type_from_caps(const GstCaps *caps)
|
||||
{
|
||||
@@ -698,6 +716,39 @@ IMFMediaType *mf_media_type_from_caps(const GstCaps *caps)
|
||||
}
|
||||
}
|
||||
}
|
||||
+ else if (!(strcmp(mime_type, "video/x-wmv")))
|
||||
+ {
|
||||
+ gint wmv_version;
|
||||
+ const char *format;
|
||||
+
|
||||
+ if (gst_structure_get_int(info, "wmvversion", &wmv_version))
|
||||
+ {
|
||||
+ switch (wmv_version)
|
||||
+ {
|
||||
+ case 1:
|
||||
+ IMFMediaType_SetGUID(media_type, &MF_MT_SUBTYPE, &MFVideoFormat_WMV1);
|
||||
+ break;
|
||||
+ case 2:
|
||||
+ IMFMediaType_SetGUID(media_type, &MF_MT_SUBTYPE, &MFVideoFormat_WMV2);
|
||||
+ break;
|
||||
+ case 3:
|
||||
+ IMFMediaType_SetGUID(media_type, &MF_MT_SUBTYPE, &MFVideoFormat_WMV3);
|
||||
+ break;
|
||||
+ default:
|
||||
+ FIXME("Unrecognized wmvversion %d\n", wmv_version);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if ((format = gst_structure_get_string(info, "format")))
|
||||
+ {
|
||||
+ if (!(strcmp(format, "WVC1")))
|
||||
+ IMFMediaType_SetGUID(media_type, &MF_MT_SUBTYPE, &MFVideoFormat_WVC1);
|
||||
+ else
|
||||
+ FIXME("Unrecognized format %s\n", format);
|
||||
+ }
|
||||
+
|
||||
+ codec_data_to_user_data(info, media_type);
|
||||
+ }
|
||||
else
|
||||
{
|
||||
FIXME("Unrecognized video format %s\n", mime_type);
|
||||
--
|
||||
2.29.2
|
||||
|
@ -0,0 +1,26 @@
|
||||
From 2268b0ad8fbe8473f936b0fa0e09d9e072443853 Mon Sep 17 00:00:00 2001
|
||||
From: Derek Lesho <dlesho@codeweavers.com>
|
||||
Date: Thu, 18 Mar 2021 14:53:49 -0400
|
||||
Subject: [PATCH 31/39] winegstreamer: Handle flush command in audio
|
||||
converstion transform.
|
||||
|
||||
Signed-off-by: Derek Lesho <dlesho@codeweavers.com>
|
||||
---
|
||||
dlls/winegstreamer/audioconvert.c | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
diff --git a/dlls/winegstreamer/audioconvert.c b/dlls/winegstreamer/audioconvert.c
|
||||
index 43fe8b04e64..1584fefe577 100644
|
||||
--- a/dlls/winegstreamer/audioconvert.c
|
||||
+++ b/dlls/winegstreamer/audioconvert.c
|
||||
@@ -618,6 +618,7 @@ static HRESULT WINAPI audio_converter_ProcessMessage(IMFTransform *iface, MFT_ME
|
||||
|
||||
switch(message)
|
||||
{
|
||||
+ case MFT_MESSAGE_COMMAND_FLUSH:
|
||||
case MFT_MESSAGE_NOTIFY_BEGIN_STREAMING:
|
||||
return S_OK;
|
||||
default:
|
||||
--
|
||||
2.30.2
|
||||
|
@ -1,139 +0,0 @@
|
||||
From 90d881fc889fdaedc7e44c0bee5e54634c0d065c Mon Sep 17 00:00:00 2001
|
||||
From: Derek Lesho <dlesho@codeweavers.com>
|
||||
Date: Tue, 24 Mar 2020 16:02:27 -0500
|
||||
Subject: [PATCH] winegstreamer: Translate AAC caps to attributes.
|
||||
|
||||
Signed-off-by: Derek Lesho <dlesho@codeweavers.com>
|
||||
---
|
||||
dlls/winegstreamer/mfplat.c | 108 ++++++++++++++++++++++++++++++++++++
|
||||
1 file changed, 108 insertions(+)
|
||||
|
||||
diff --git a/dlls/winegstreamer/mfplat.c b/dlls/winegstreamer/mfplat.c
|
||||
index 6906fd3faeb..66048f359e5 100644
|
||||
--- a/dlls/winegstreamer/mfplat.c
|
||||
+++ b/dlls/winegstreamer/mfplat.c
|
||||
@@ -564,6 +564,15 @@ uncompressed_video_formats[] =
|
||||
{&MFVideoFormat_RGB555, GST_VIDEO_FORMAT_BGR15},
|
||||
};
|
||||
|
||||
+struct aac_user_data
|
||||
+{
|
||||
+ WORD payload_type;
|
||||
+ WORD profile_level_indication;
|
||||
+ WORD struct_type;
|
||||
+ WORD reserved;
|
||||
+ /* audio-specific-config is stored here */
|
||||
+};
|
||||
+
|
||||
static void codec_data_to_user_data(GstStructure *structure, IMFMediaType *type)
|
||||
{
|
||||
const GValue *codec_data;
|
||||
@@ -814,6 +823,105 @@ IMFMediaType *mf_media_type_from_caps(const GstCaps *caps)
|
||||
|
||||
IMFMediaType_SetUINT32(media_type, &MF_MT_AUDIO_BITS_PER_SAMPLE, depth);
|
||||
}
|
||||
+ else if (!(strcmp(mime_type, "audio/mpeg")))
|
||||
+ {
|
||||
+ int mpeg_version = -1;
|
||||
+
|
||||
+ IMFMediaType_SetUINT32(media_type, &MF_MT_COMPRESSED, TRUE);
|
||||
+
|
||||
+ if (!(gst_structure_get_int(info, "mpegversion", &mpeg_version)))
|
||||
+ ERR("Failed to get mpegversion\n");
|
||||
+ switch (mpeg_version)
|
||||
+ {
|
||||
+ case 2:
|
||||
+ case 4:
|
||||
+ {
|
||||
+ const char *format, *profile, *level;
|
||||
+ DWORD profile_level_indication = 0;
|
||||
+ const GValue *codec_data;
|
||||
+ DWORD asc_size = 0;
|
||||
+ struct aac_user_data *user_data = NULL;
|
||||
+
|
||||
+ IMFMediaType_SetGUID(media_type, &MF_MT_SUBTYPE, &MFAudioFormat_AAC);
|
||||
+ IMFMediaType_SetUINT32(media_type, &MF_MT_AUDIO_BITS_PER_SAMPLE, 16);
|
||||
+
|
||||
+ codec_data = gst_structure_get_value(info, "codec_data");
|
||||
+ if (codec_data)
|
||||
+ {
|
||||
+ GstBuffer *codec_data_buffer = gst_value_get_buffer(codec_data);
|
||||
+ if (codec_data_buffer)
|
||||
+ {
|
||||
+ if ((asc_size = gst_buffer_get_size(codec_data_buffer)) >= 2)
|
||||
+ {
|
||||
+ user_data = heap_alloc_zero(sizeof(*user_data)+asc_size);
|
||||
+ gst_buffer_extract(codec_data_buffer, 0, (gpointer)(user_data + 1), asc_size);
|
||||
+ }
|
||||
+ else
|
||||
+ ERR("Unexpected buffer size\n");
|
||||
+ }
|
||||
+ else
|
||||
+ ERR("codec_data not a buffer\n");
|
||||
+ }
|
||||
+ else
|
||||
+ ERR("codec_data not found\n");
|
||||
+ if (!user_data)
|
||||
+ user_data = heap_alloc_zero(sizeof(*user_data));
|
||||
+
|
||||
+ if ((format = gst_structure_get_string(info, "stream-format")))
|
||||
+ {
|
||||
+ DWORD payload_type = -1;
|
||||
+ if (!(strcmp(format, "raw")))
|
||||
+ payload_type = 0;
|
||||
+ else if (!(strcmp(format, "adts")))
|
||||
+ payload_type = 1;
|
||||
+ else if (!(strcmp(format, "adif")))
|
||||
+ payload_type = 2;
|
||||
+ else if (!(strcmp(format, "loas")))
|
||||
+ payload_type = 3;
|
||||
+ else
|
||||
+ FIXME("Unrecognized stream-format\n");
|
||||
+ if (payload_type != -1)
|
||||
+ {
|
||||
+ IMFMediaType_SetUINT32(media_type, &MF_MT_AAC_PAYLOAD_TYPE, payload_type);
|
||||
+ user_data->payload_type = payload_type;
|
||||
+ }
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ ERR("Stream format not present\n");
|
||||
+ }
|
||||
+
|
||||
+ profile = gst_structure_get_string(info, "profile");
|
||||
+ level = gst_structure_get_string(info, "level");
|
||||
+ /* Data from http://archive.is/whp6P#45% */
|
||||
+ if (profile && level)
|
||||
+ {
|
||||
+ if (!(strcmp(profile, "lc")) && !(strcmp(level, "2")))
|
||||
+ profile_level_indication = 0x29;
|
||||
+ else if (!(strcmp(profile, "lc")) && !(strcmp(level, "4")))
|
||||
+ profile_level_indication = 0x2A;
|
||||
+ else if (!(strcmp(profile, "lc")) && !(strcmp(level, "5")))
|
||||
+ profile_level_indication = 0x2B;
|
||||
+ else
|
||||
+ FIXME("Unhandled profile/level combo\n");
|
||||
+ }
|
||||
+ else
|
||||
+ ERR("Profile or level not present\n");
|
||||
+
|
||||
+ if (profile_level_indication)
|
||||
+ {
|
||||
+ IMFMediaType_SetUINT32(media_type, &MF_MT_AAC_AUDIO_PROFILE_LEVEL_INDICATION, profile_level_indication);
|
||||
+ user_data->profile_level_indication = profile_level_indication;
|
||||
+ }
|
||||
+
|
||||
+ IMFMediaType_SetBlob(media_type, &MF_MT_USER_DATA, (BYTE *)user_data, sizeof(*user_data) + asc_size);
|
||||
+ heap_free(user_data);
|
||||
+ break;
|
||||
+ }
|
||||
+ default:
|
||||
+ FIXME("Unhandled mpegversion %d\n", mpeg_version);
|
||||
+ }
|
||||
+ }
|
||||
else
|
||||
{
|
||||
FIXME("Unrecognized audio format %s\n", mime_type);
|
||||
--
|
||||
2.29.2
|
||||
|
@ -1,33 +1,26 @@
|
||||
From cda7c0339af6bf5c4d903ef844844ca0d4332d73 Mon Sep 17 00:00:00 2001
|
||||
From baebd866b835a054f00121d577e45c08edcde25c Mon Sep 17 00:00:00 2001
|
||||
From: Derek Lesho <dlesho@codeweavers.com>
|
||||
Date: Tue, 5 May 2020 15:35:16 -0500
|
||||
Subject: [PATCH] Report streams backwards and only select one of each stream
|
||||
type.
|
||||
Date: Fri, 4 Dec 2020 16:17:11 -0500
|
||||
Subject: [PATCH 32/39] winegstreamer: In the default configuration, select one
|
||||
stream of each major type.
|
||||
|
||||
---
|
||||
dlls/winegstreamer/media_source.c | 24 ++++++++++++++++++++++--
|
||||
1 file changed, 22 insertions(+), 2 deletions(-)
|
||||
dlls/winegstreamer/media_source.c | 22 +++++++++++++++++++++-
|
||||
1 file changed, 21 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/dlls/winegstreamer/media_source.c b/dlls/winegstreamer/media_source.c
|
||||
index 2156e07a13c..fd7f1a7f55e 100644
|
||||
index b0c4220cc00..2d1a628cba0 100644
|
||||
--- a/dlls/winegstreamer/media_source.c
|
||||
+++ b/dlls/winegstreamer/media_source.c
|
||||
@@ -1486,6 +1486,7 @@ static HRESULT media_source_constructor(IMFByteStream *bytestream, struct media_
|
||||
GstStaticPadTemplate src_template =
|
||||
GST_STATIC_PAD_TEMPLATE("mf_src", GST_PAD_SRC, GST_PAD_ALWAYS, GST_STATIC_CAPS_ANY);
|
||||
@@ -1273,6 +1273,7 @@ static const IMFMediaSourceVtbl IMFMediaSource_vtbl =
|
||||
|
||||
static HRESULT media_source_constructor(IMFByteStream *bytestream, struct media_source **out_media_source)
|
||||
{
|
||||
+ BOOL video_selected = FALSE, audio_selected = FALSE;
|
||||
IMFStreamDescriptor **descriptors = NULL;
|
||||
IMFAttributes *byte_stream_attributes;
|
||||
struct media_source *object;
|
||||
@@ -1600,15 +1601,34 @@ static HRESULT media_source_constructor(IMFByteStream *bytestream, struct media_
|
||||
descriptors = heap_alloc(object->stream_count * sizeof(IMFStreamDescriptor*));
|
||||
for (i = 0; i < object->stream_count; i++)
|
||||
{
|
||||
- IMFMediaStream_GetStreamDescriptor(&object->streams[i]->IMFMediaStream_iface, &descriptors[i]);
|
||||
+ IMFMediaStream_GetStreamDescriptor(&object->streams[i]->IMFMediaStream_iface, &descriptors[object->stream_count - 1 - i]);
|
||||
}
|
||||
|
||||
UINT64 total_pres_time = 0;
|
||||
@@ -1369,9 +1370,28 @@ static HRESULT media_source_constructor(IMFByteStream *bytestream, struct media_
|
||||
if (FAILED(hr = MFCreatePresentationDescriptor(object->stream_count, descriptors, &object->pres_desc)))
|
||||
goto fail;
|
||||
|
||||
@ -56,7 +49,7 @@ index 2156e07a13c..fd7f1a7f55e 100644
|
||||
+ IMFMediaTypeHandler_Release(handler);
|
||||
IMFStreamDescriptor_Release(descriptors[i]);
|
||||
}
|
||||
heap_free(descriptors);
|
||||
free(descriptors);
|
||||
--
|
||||
2.29.2
|
||||
2.30.2
|
||||
|
@ -1,40 +0,0 @@
|
||||
From c4955ec1798428fe9941cdbb9fed146f3d29dbe2 Mon Sep 17 00:00:00 2001
|
||||
From: Derek Lesho <dlesho@codeweavers.com>
|
||||
Date: Wed, 25 Mar 2020 13:36:19 -0500
|
||||
Subject: [PATCH] winegstreamer: Translate MPEG-4 Section-2 caps to attributes.
|
||||
|
||||
Signed-off-by: Derek Lesho <dlesho@codeweavers.com>
|
||||
---
|
||||
dlls/winegstreamer/mfplat.c | 16 ++++++++++++++++
|
||||
1 file changed, 16 insertions(+)
|
||||
|
||||
diff --git a/dlls/winegstreamer/mfplat.c b/dlls/winegstreamer/mfplat.c
|
||||
index 66048f359e5..090952e7d2b 100644
|
||||
--- a/dlls/winegstreamer/mfplat.c
|
||||
+++ b/dlls/winegstreamer/mfplat.c
|
||||
@@ -758,6 +758,22 @@ IMFMediaType *mf_media_type_from_caps(const GstCaps *caps)
|
||||
|
||||
codec_data_to_user_data(info, media_type);
|
||||
}
|
||||
+ else if (!(strcmp(mime_type, "video/mpeg")))
|
||||
+ {
|
||||
+ gint mpegversion;
|
||||
+ if (gst_structure_get_int(info, "mpegversion", &mpegversion))
|
||||
+ {
|
||||
+ if (mpegversion == 4)
|
||||
+ {
|
||||
+ IMFMediaType_SetGUID(media_type, &MF_MT_SUBTYPE, &MFVideoFormat_M4S2);
|
||||
+ IMFMediaType_SetUINT32(media_type, &MF_MT_COMPRESSED, TRUE);
|
||||
+
|
||||
+ codec_data_to_user_data(info, media_type);
|
||||
+ }
|
||||
+ else
|
||||
+ FIXME("Unrecognized mpeg version %d\n", mpegversion);
|
||||
+ }
|
||||
+ }
|
||||
else
|
||||
{
|
||||
FIXME("Unrecognized video format %s\n", mime_type);
|
||||
--
|
||||
2.29.2
|
||||
|
@ -0,0 +1,131 @@
|
||||
From 2ba70d161799850a073a43c658707fb1682a042f Mon Sep 17 00:00:00 2001
|
||||
From: Derek Lesho <dlesho@codeweavers.com>
|
||||
Date: Thu, 18 Mar 2021 15:25:17 -0400
|
||||
Subject: [PATCH 33/39] winegstreamer: Implement MF_SD_LANGUAGE.
|
||||
|
||||
Signed-off-by: Derek Lesho <dlesho@codeweavers.com>
|
||||
---
|
||||
dlls/winegstreamer/gst_private.h | 1 +
|
||||
dlls/winegstreamer/media_source.c | 20 +++++++++++++++++++-
|
||||
dlls/winegstreamer/wg_parser.c | 27 +++++++++++++++++++++++++++
|
||||
3 files changed, 47 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/dlls/winegstreamer/gst_private.h b/dlls/winegstreamer/gst_private.h
|
||||
index 0827f70112f..f616b8a5d9d 100644
|
||||
--- a/dlls/winegstreamer/gst_private.h
|
||||
+++ b/dlls/winegstreamer/gst_private.h
|
||||
@@ -240,6 +240,7 @@ struct unix_funcs
|
||||
|
||||
/* Returns the duration in 100-nanosecond units. */
|
||||
uint64_t (CDECL *wg_parser_stream_get_duration)(struct wg_parser_stream *stream);
|
||||
+ char * (CDECL *wg_parser_stream_get_language)(struct wg_parser_stream *stream);
|
||||
/* start_pos and stop_pos are in 100-nanosecond units. */
|
||||
bool (CDECL *wg_parser_stream_seek)(struct wg_parser_stream *stream, double rate,
|
||||
uint64_t start_pos, uint64_t stop_pos, DWORD start_flags, DWORD stop_flags);
|
||||
diff --git a/dlls/winegstreamer/media_source.c b/dlls/winegstreamer/media_source.c
|
||||
index 2d1a628cba0..eaf4b9b6815 100644
|
||||
--- a/dlls/winegstreamer/media_source.c
|
||||
+++ b/dlls/winegstreamer/media_source.c
|
||||
@@ -1364,7 +1364,25 @@ static HRESULT media_source_constructor(IMFByteStream *bytestream, struct media_
|
||||
descriptors = malloc(object->stream_count * sizeof(IMFStreamDescriptor *));
|
||||
for (i = 0; i < object->stream_count; i++)
|
||||
{
|
||||
- IMFMediaStream_GetStreamDescriptor(&object->streams[i]->IMFMediaStream_iface, &descriptors[object->stream_count - 1 - i]);
|
||||
+ IMFStreamDescriptor **descriptor = &descriptors[object->stream_count - 1 - i];
|
||||
+ DWORD language_len;
|
||||
+ WCHAR *languageW;
|
||||
+ char *language;
|
||||
+
|
||||
+ IMFMediaStream_GetStreamDescriptor(&object->streams[i]->IMFMediaStream_iface, descriptor);
|
||||
+
|
||||
+ if ((language = unix_funcs->wg_parser_stream_get_language(object->streams[i]->wg_stream)))
|
||||
+ {
|
||||
+ if ((language_len = MultiByteToWideChar(CP_UTF8, 0, language, -1, NULL, 0)))
|
||||
+ {
|
||||
+ languageW = malloc(language_len * sizeof(WCHAR));
|
||||
+ if (MultiByteToWideChar(CP_UTF8, 0, language, -1, languageW, language_len))
|
||||
+ {
|
||||
+ IMFStreamDescriptor_SetString(*descriptor, &MF_SD_LANGUAGE, languageW);
|
||||
+ }
|
||||
+ free(languageW);
|
||||
+ }
|
||||
+ }
|
||||
}
|
||||
|
||||
if (FAILED(hr = MFCreatePresentationDescriptor(object->stream_count, descriptors, &object->pres_desc)))
|
||||
diff --git a/dlls/winegstreamer/wg_parser.c b/dlls/winegstreamer/wg_parser.c
|
||||
index 6f4dd28082b..534db931d8b 100644
|
||||
--- a/dlls/winegstreamer/wg_parser.c
|
||||
+++ b/dlls/winegstreamer/wg_parser.c
|
||||
@@ -93,6 +93,7 @@ struct wg_parser_stream
|
||||
bool flushing, eos, enabled, has_caps;
|
||||
|
||||
uint64_t duration;
|
||||
+ gchar *language_code;
|
||||
};
|
||||
|
||||
static enum wg_audio_format wg_audio_format_from_gst(GstAudioFormat format)
|
||||
@@ -848,6 +849,11 @@ static uint64_t CDECL wg_parser_stream_get_duration(struct wg_parser_stream *str
|
||||
return stream->duration;
|
||||
}
|
||||
|
||||
+static char * CDECL wg_parser_stream_get_language(struct wg_parser_stream *stream)
|
||||
+{
|
||||
+ return stream->language_code;
|
||||
+}
|
||||
+
|
||||
static bool CDECL wg_parser_stream_seek(struct wg_parser_stream *stream, double rate,
|
||||
uint64_t start_pos, uint64_t stop_pos, DWORD start_flags, DWORD stop_flags)
|
||||
{
|
||||
@@ -1946,6 +1952,22 @@ static LONGLONG query_duration(GstPad *pad)
|
||||
return 0;
|
||||
}
|
||||
|
||||
+static gchar *query_language(GstPad *pad)
|
||||
+{
|
||||
+ GstTagList *tag_list;
|
||||
+ GstEvent *tag_event;
|
||||
+ gchar *ret = NULL;
|
||||
+
|
||||
+ if ((tag_event = gst_pad_get_sticky_event(pad, GST_EVENT_TAG, 0)))
|
||||
+ {
|
||||
+ gst_event_parse_tag(tag_event, &tag_list);
|
||||
+ gst_tag_list_get_string(tag_list, "language-code", &ret);
|
||||
+ gst_event_unref(tag_event);
|
||||
+ }
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
static HRESULT wg_parser_connect_inner(struct wg_parser *parser)
|
||||
{
|
||||
GstStaticPadTemplate src_template = GST_STATIC_PAD_TEMPLATE("wine_src",
|
||||
@@ -1995,6 +2017,7 @@ static HRESULT CDECL wg_parser_connect(struct wg_parser *parser, uint64_t file_s
|
||||
{
|
||||
struct wg_parser_stream *stream = parser->streams[i];
|
||||
|
||||
+ stream->language_code = query_language(stream->their_src);
|
||||
while (!stream->has_caps && !parser->error)
|
||||
pthread_cond_wait(&parser->init_cond, &parser->mutex);
|
||||
if (parser->error)
|
||||
@@ -2074,6 +2097,9 @@ static void free_stream(struct wg_parser_stream *stream)
|
||||
pthread_cond_destroy(&stream->event_cond);
|
||||
pthread_cond_destroy(&stream->event_empty_cond);
|
||||
|
||||
+ if (stream->language_code)
|
||||
+ g_free(stream->language_code);
|
||||
+
|
||||
free(stream);
|
||||
}
|
||||
|
||||
@@ -2523,6 +2549,7 @@ static const struct unix_funcs funcs =
|
||||
wg_parser_stream_notify_qos,
|
||||
|
||||
wg_parser_stream_get_duration,
|
||||
+ wg_parser_stream_get_language,
|
||||
wg_parser_stream_seek,
|
||||
wg_parser_stream_drain,
|
||||
};
|
||||
--
|
||||
2.30.2
|
||||
|
@ -1,48 +0,0 @@
|
||||
From 56ac324cb533bde61e25bc86a29440aec7111764 Mon Sep 17 00:00:00 2001
|
||||
From: Derek Lesho <dlesho@codeweavers.com>
|
||||
Date: Tue, 12 May 2020 17:05:41 -0500
|
||||
Subject: [PATCH] winegstreamer: Translate WMA caps to attributes.
|
||||
|
||||
Signed-off-by: Derek Lesho <dlesho@codeweavers.com>
|
||||
---
|
||||
dlls/winegstreamer/mfplat.c | 24 ++++++++++++++++++++++++
|
||||
1 file changed, 24 insertions(+)
|
||||
|
||||
diff --git a/dlls/winegstreamer/mfplat.c b/dlls/winegstreamer/mfplat.c
|
||||
index 090952e7d2b..b2f8f0b83c1 100644
|
||||
--- a/dlls/winegstreamer/mfplat.c
|
||||
+++ b/dlls/winegstreamer/mfplat.c
|
||||
@@ -938,6 +938,30 @@ IMFMediaType *mf_media_type_from_caps(const GstCaps *caps)
|
||||
FIXME("Unhandled mpegversion %d\n", mpeg_version);
|
||||
}
|
||||
}
|
||||
+ else if (!(strcmp(mime_type, "audio/x-wma")))
|
||||
+ {
|
||||
+ gint wma_version, block_align;
|
||||
+
|
||||
+ if (gst_structure_get_int(info, "wmaversion", &wma_version))
|
||||
+ {
|
||||
+ switch (wma_version)
|
||||
+ {
|
||||
+ case 2:
|
||||
+ IMFMediaType_SetGUID(media_type, &MF_MT_SUBTYPE, &MFAudioFormat_WMAudioV8);
|
||||
+ break;
|
||||
+ case 3:
|
||||
+ IMFMediaType_SetGUID(media_type, &MF_MT_SUBTYPE, &MFAudioFormat_WMAudioV9);
|
||||
+ break;
|
||||
+ default:
|
||||
+ FIXME("Unrecognized wmaversion %d\n", wma_version);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (gst_structure_get_int(info, "block_align", &block_align))
|
||||
+ IMFMediaType_SetUINT32(media_type, &MF_MT_AUDIO_BLOCK_ALIGNMENT, block_align);
|
||||
+
|
||||
+ codec_data_to_user_data(info, media_type);
|
||||
+ }
|
||||
else
|
||||
{
|
||||
FIXME("Unrecognized audio format %s\n", mime_type);
|
||||
--
|
||||
2.29.2
|
||||
|
@ -0,0 +1,93 @@
|
||||
From 97f4a9b38ee49706edb3c52b93dd86509665361c Mon Sep 17 00:00:00 2001
|
||||
From: Derek Lesho <dlesho@codeweavers.com>
|
||||
Date: Thu, 18 Mar 2021 16:20:50 -0400
|
||||
Subject: [PATCH 34/39] winegstreamer: Only require videobox element for parser
|
||||
when needed.
|
||||
|
||||
Signed-off-by: Derek Lesho <dlesho@codeweavers.com>
|
||||
---
|
||||
dlls/winegstreamer/wg_parser.c | 42 ++++++++++++++++++++++++++--------
|
||||
1 file changed, 32 insertions(+), 10 deletions(-)
|
||||
|
||||
diff --git a/dlls/winegstreamer/wg_parser.c b/dlls/winegstreamer/wg_parser.c
|
||||
index 534db931d8b..afd69ea6891 100644
|
||||
--- a/dlls/winegstreamer/wg_parser.c
|
||||
+++ b/dlls/winegstreamer/wg_parser.c
|
||||
@@ -753,6 +753,15 @@ static void CDECL wg_parser_stream_enable(struct wg_parser_stream *stream, const
|
||||
|
||||
if (aperture)
|
||||
{
|
||||
+ if (!stream->box && (stream->aperture.left || stream->aperture.top ||
|
||||
+ (stream->aperture.right && stream->aperture.right != stream->current_format.u.video.width) ||
|
||||
+ (stream->aperture.bottom && stream->aperture.bottom != stream->current_format.u.video.height)))
|
||||
+ {
|
||||
+ fprintf(stderr, "winegstreamer: failed to create videobox, are %u-bit GStreamer \"good\" plugins installed?\n",
|
||||
+ 8 * (int)sizeof(void *));
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
if (aperture->left)
|
||||
g_object_set(G_OBJECT(stream->box), "left", -aperture->left, NULL);
|
||||
if (aperture->top)
|
||||
@@ -1309,12 +1318,7 @@ static void pad_added_cb(GstElement *element, GstPad *pad, gpointer user)
|
||||
goto out;
|
||||
}
|
||||
|
||||
- if (!(videobox = gst_element_factory_make("videobox", NULL)))
|
||||
- {
|
||||
- fprintf(stderr, "winegstreamer: failed to create videobox, are %u-bit GStreamer \"base\" plugins installed?\n",
|
||||
- 8 * (int)sizeof(void *));
|
||||
- goto out;
|
||||
- }
|
||||
+ videobox = gst_element_factory_make("videobox", NULL);
|
||||
|
||||
/* videoflip does not support 15 and 16-bit RGB so add a second videoconvert
|
||||
* to do the final conversion. */
|
||||
@@ -1327,6 +1331,14 @@ static void pad_added_cb(GstElement *element, GstPad *pad, gpointer user)
|
||||
|
||||
if (!parser->seekable)
|
||||
{
|
||||
+ if (!videobox && (stream->aperture.left || stream->aperture.top ||
|
||||
+ (stream->aperture.right && stream->aperture.right != stream->current_format.u.video.width) ||
|
||||
+ (stream->aperture.bottom && stream->aperture.bottom != stream->current_format.u.video.height)))
|
||||
+ {
|
||||
+ fprintf(stderr, "winegstreamer: failed to create videobox, are %u-bit GStreamer \"good\" plugins installed?\n",
|
||||
+ 8 * (int)sizeof(void *));
|
||||
+ goto out;
|
||||
+ }
|
||||
if (stream->aperture.left)
|
||||
g_object_set(G_OBJECT(videobox), "left", -stream->aperture.left, NULL);
|
||||
if (stream->aperture.bottom)
|
||||
@@ -1344,15 +1356,25 @@ static void pad_added_cb(GstElement *element, GstPad *pad, gpointer user)
|
||||
gst_element_sync_state_with_parent(vconv);
|
||||
gst_bin_add(GST_BIN(parser->container), flip);
|
||||
gst_element_sync_state_with_parent(flip);
|
||||
- gst_bin_add(GST_BIN(parser->container), videobox);
|
||||
- gst_element_sync_state_with_parent(videobox);
|
||||
+ if (videobox)
|
||||
+ {
|
||||
+ gst_bin_add(GST_BIN(parser->container), videobox);
|
||||
+ gst_element_sync_state_with_parent(videobox);
|
||||
+ }
|
||||
gst_bin_add(GST_BIN(parser->container), vconv2);
|
||||
gst_element_sync_state_with_parent(vconv2);
|
||||
|
||||
gst_element_link(deinterlace, vconv);
|
||||
gst_element_link(vconv, flip);
|
||||
- gst_element_link(flip, videobox);
|
||||
- gst_element_link(videobox, vconv2);
|
||||
+ if (videobox)
|
||||
+ {
|
||||
+ gst_element_link(flip, videobox);
|
||||
+ gst_element_link(videobox, vconv2);
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ gst_element_link(flip, vconv2);
|
||||
+ }
|
||||
|
||||
stream->post_sink = gst_element_get_static_pad(deinterlace, "sink");
|
||||
stream->post_src = gst_element_get_static_pad(vconv2, "src");
|
||||
--
|
||||
2.30.2
|
||||
|
@ -1,128 +0,0 @@
|
||||
From 6ace23bd172cb48c7e326fd3013624a73cdf8c10 Mon Sep 17 00:00:00 2001
|
||||
From: Derek Lesho <dlesho@codeweavers.com>
|
||||
Date: Tue, 24 Mar 2020 16:18:40 -0500
|
||||
Subject: [PATCH] winegstreamer: Translate H.264 attributes to caps.
|
||||
|
||||
Signed-off-by: Derek Lesho <dlesho@codeweavers.com>
|
||||
---
|
||||
dlls/winegstreamer/mfplat.c | 90 +++++++++++++++++++++++++++++--------
|
||||
1 file changed, 71 insertions(+), 19 deletions(-)
|
||||
|
||||
diff --git a/dlls/winegstreamer/mfplat.c b/dlls/winegstreamer/mfplat.c
|
||||
index b2f8f0b83c1..e02f0dfbc5c 100644
|
||||
--- a/dlls/winegstreamer/mfplat.c
|
||||
+++ b/dlls/winegstreamer/mfplat.c
|
||||
@@ -1056,10 +1056,6 @@ GstCaps *caps_from_mf_media_type(IMFMediaType *type)
|
||||
{
|
||||
UINT64 frame_rate = 0, frame_size = 0;
|
||||
DWORD width, height;
|
||||
- GstVideoFormat format = GST_VIDEO_FORMAT_UNKNOWN;
|
||||
- GUID subtype_base;
|
||||
- GstVideoInfo info;
|
||||
- unsigned int i;
|
||||
|
||||
if (FAILED(IMFMediaType_GetUINT64(type, &MF_MT_FRAME_SIZE, &frame_size)))
|
||||
return NULL;
|
||||
@@ -1068,28 +1064,84 @@ GstCaps *caps_from_mf_media_type(IMFMediaType *type)
|
||||
|
||||
output = gst_caps_new_empty_simple("video/x-raw");
|
||||
|
||||
- for (i = 0; i < ARRAY_SIZE(uncompressed_video_formats); i++)
|
||||
+ if (IsEqualGUID(&subtype, &MFVideoFormat_H264))
|
||||
{
|
||||
- if (IsEqualGUID(uncompressed_video_formats[i].subtype, &subtype))
|
||||
+ enum eAVEncH264VProfile h264_profile;
|
||||
+ enum eAVEncH264VLevel h264_level;
|
||||
+ output = gst_caps_new_empty_simple("video/x-h264");
|
||||
+ gst_caps_set_simple(output, "stream-format", G_TYPE_STRING, "byte-stream", NULL);
|
||||
+ gst_caps_set_simple(output, "alignment", G_TYPE_STRING, "au", NULL);
|
||||
+
|
||||
+ if (SUCCEEDED(IMFMediaType_GetUINT32(type, &MF_MT_MPEG2_PROFILE, &h264_profile)))
|
||||
+ {
|
||||
+ const char *profile = NULL;
|
||||
+ switch (h264_profile)
|
||||
+ {
|
||||
+ case eAVEncH264VProfile_Main: profile = "main"; break;
|
||||
+ case eAVEncH264VProfile_High: profile = "high"; break;
|
||||
+ case eAVEncH264VProfile_444: profile = "high-4:4:4"; break;
|
||||
+ default: FIXME("Unknown profile %u\n", h264_profile);
|
||||
+ }
|
||||
+ if (profile)
|
||||
+ gst_caps_set_simple(output, "profile", G_TYPE_STRING, profile, NULL);
|
||||
+ }
|
||||
+ if (SUCCEEDED(IMFMediaType_GetUINT32(type, &MF_MT_MPEG2_LEVEL, &h264_level)))
|
||||
{
|
||||
- format = uncompressed_video_formats[i].format;
|
||||
- break;
|
||||
+ const char *level = NULL;
|
||||
+ switch (h264_level)
|
||||
+ {
|
||||
+ case eAVEncH264VLevel1: level = "1"; break;
|
||||
+ case eAVEncH264VLevel1_1: level = "1.1"; break;
|
||||
+ case eAVEncH264VLevel1_2: level = "1.2"; break;
|
||||
+ case eAVEncH264VLevel1_3: level = "1.3"; break;
|
||||
+ case eAVEncH264VLevel2: level = "2"; break;
|
||||
+ case eAVEncH264VLevel2_1: level = "2.1"; break;
|
||||
+ case eAVEncH264VLevel2_2: level = "2.2"; break;
|
||||
+ case eAVEncH264VLevel3: level = "3"; break;
|
||||
+ case eAVEncH264VLevel3_1: level = "3.1"; break;
|
||||
+ case eAVEncH264VLevel3_2: level = "3.2"; break;
|
||||
+ case eAVEncH264VLevel4: level = "4"; break;
|
||||
+ case eAVEncH264VLevel4_1: level = "4.1"; break;
|
||||
+ case eAVEncH264VLevel4_2: level = "4.2"; break;
|
||||
+ case eAVEncH264VLevel5: level = "5"; break;
|
||||
+ case eAVEncH264VLevel5_1: level = "5.1"; break;
|
||||
+ case eAVEncH264VLevel5_2: level = "5.2"; break;
|
||||
+ default: FIXME("Unknown level %u\n", h264_level);
|
||||
+ }
|
||||
+ if (level)
|
||||
+ gst_caps_set_simple(output, "level", G_TYPE_STRING, level, NULL);
|
||||
}
|
||||
}
|
||||
+ else
|
||||
+ {
|
||||
+ GstVideoFormat format = GST_VIDEO_FORMAT_UNKNOWN;
|
||||
+ GUID subtype_base;
|
||||
+ GstVideoInfo info;
|
||||
+ unsigned int i;
|
||||
|
||||
- subtype_base = subtype;
|
||||
- subtype_base.Data1 = 0;
|
||||
- if (format == GST_VIDEO_FORMAT_UNKNOWN && IsEqualGUID(&MFVideoFormat_Base, &subtype_base))
|
||||
- format = gst_video_format_from_fourcc(subtype.Data1);
|
||||
+ for (i = 0; i < ARRAY_SIZE(uncompressed_video_formats); i++)
|
||||
+ {
|
||||
+ if (IsEqualGUID(uncompressed_video_formats[i].subtype, &subtype))
|
||||
+ {
|
||||
+ format = uncompressed_video_formats[i].format;
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
|
||||
- if (format == GST_VIDEO_FORMAT_UNKNOWN)
|
||||
- {
|
||||
- FIXME("Unrecognized format %s\n", debugstr_guid(&subtype));
|
||||
- return NULL;
|
||||
- }
|
||||
+ subtype_base = subtype;
|
||||
+ subtype_base.Data1 = 0;
|
||||
+ if (format == GST_VIDEO_FORMAT_UNKNOWN && IsEqualGUID(&MFVideoFormat_Base, &subtype_base))
|
||||
+ format = gst_video_format_from_fourcc(subtype.Data1);
|
||||
|
||||
- gst_video_info_set_format(&info, format, width, height);
|
||||
- output = gst_video_info_to_caps(&info);
|
||||
+ if (format == GST_VIDEO_FORMAT_UNKNOWN)
|
||||
+ {
|
||||
+ FIXME("Unrecognized format %s\n", debugstr_guid(&subtype));
|
||||
+ return NULL;
|
||||
+ }
|
||||
+
|
||||
+ gst_video_info_set_format(&info, format, width, height);
|
||||
+ output = gst_video_info_to_caps(&info);
|
||||
+ }
|
||||
|
||||
if (frame_size)
|
||||
{
|
||||
--
|
||||
2.29.2
|
||||
|
@ -0,0 +1,64 @@
|
||||
From 1301b70733c9d5256b5f8352e9bbd6a3578ba590 Mon Sep 17 00:00:00 2001
|
||||
From: Derek Lesho <dlesho@codeweavers.com>
|
||||
Date: Thu, 18 Mar 2021 16:54:44 -0400
|
||||
Subject: [PATCH 35/39] mfplat: Stub out MFCreateDXGIDeviceManager, to avoid
|
||||
the d3d path.
|
||||
|
||||
---
|
||||
dlls/mfplat/main.c | 32 +++++++++++++++++++-------------
|
||||
1 file changed, 19 insertions(+), 13 deletions(-)
|
||||
|
||||
diff --git a/dlls/mfplat/main.c b/dlls/mfplat/main.c
|
||||
index 5406ceb5063..764d825a102 100644
|
||||
--- a/dlls/mfplat/main.c
|
||||
+++ b/dlls/mfplat/main.c
|
||||
@@ -8881,27 +8881,33 @@ static const IMFDXGIDeviceManagerVtbl dxgi_device_manager_vtbl =
|
||||
HRESULT WINAPI MFCreateDXGIDeviceManager(UINT *token, IMFDXGIDeviceManager **manager)
|
||||
{
|
||||
struct dxgi_device_manager *object;
|
||||
+ const char *sgi = getenv("SteamGameId");
|
||||
|
||||
TRACE("%p, %p.\n", token, manager);
|
||||
|
||||
- if (!token || !manager)
|
||||
- return E_POINTER;
|
||||
+ if (sgi && (!strcmp(sgi,"1113560")))
|
||||
+ {
|
||||
+ if (!token || !manager)
|
||||
+ return E_POINTER;
|
||||
|
||||
- if (!(object = calloc(1, sizeof(*object))))
|
||||
- return E_OUTOFMEMORY;
|
||||
+ if (!(object = calloc(1, sizeof(*object))))
|
||||
+ return E_OUTOFMEMORY;
|
||||
|
||||
- object->IMFDXGIDeviceManager_iface.lpVtbl = &dxgi_device_manager_vtbl;
|
||||
- object->refcount = 1;
|
||||
- object->token = GetTickCount();
|
||||
- InitializeCriticalSection(&object->cs);
|
||||
- InitializeConditionVariable(&object->lock);
|
||||
+ object->IMFDXGIDeviceManager_iface.lpVtbl = &dxgi_device_manager_vtbl;
|
||||
+ object->refcount = 1;
|
||||
+ object->token = GetTickCount();
|
||||
+ InitializeCriticalSection(&object->cs);
|
||||
+ InitializeConditionVariable(&object->lock);
|
||||
|
||||
- TRACE("Created device manager: %p, token: %u.\n", object, object->token);
|
||||
+ TRACE("Created device manager: %p, token: %u.\n", object, object->token);
|
||||
|
||||
- *token = object->token;
|
||||
- *manager = &object->IMFDXGIDeviceManager_iface;
|
||||
+ *token = object->token;
|
||||
+ *manager = &object->IMFDXGIDeviceManager_iface;
|
||||
|
||||
- return S_OK;
|
||||
+ return S_OK;
|
||||
+ } else {
|
||||
+ return E_NOTIMPL;
|
||||
+ }
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
--
|
||||
2.30.2
|
||||
|
@ -1,82 +0,0 @@
|
||||
From 5f71506e9482e475bb636a4d3738734afe004443 Mon Sep 17 00:00:00 2001
|
||||
From: Derek Lesho <dlesho@codeweavers.com>
|
||||
Date: Tue, 24 Mar 2020 16:20:17 -0500
|
||||
Subject: [PATCH] winegstreamer: Translate WMV attributes to caps.
|
||||
|
||||
Signed-off-by: Derek Lesho <dlesho@codeweavers.com>
|
||||
---
|
||||
dlls/winegstreamer/mfplat.c | 51 +++++++++++++++++++++++++++++++++++++
|
||||
1 file changed, 51 insertions(+)
|
||||
|
||||
diff --git a/dlls/winegstreamer/mfplat.c b/dlls/winegstreamer/mfplat.c
|
||||
index e02f0dfbc5c..2456d633c6c 100644
|
||||
--- a/dlls/winegstreamer/mfplat.c
|
||||
+++ b/dlls/winegstreamer/mfplat.c
|
||||
@@ -1041,6 +1041,21 @@ GstCaps *make_mf_compatible_caps(GstCaps *caps)
|
||||
return ret;
|
||||
}
|
||||
|
||||
+static void user_data_to_codec_data(IMFMediaType *type, GstCaps *caps)
|
||||
+{
|
||||
+ BYTE *user_data;
|
||||
+ DWORD user_data_size;
|
||||
+
|
||||
+ if (SUCCEEDED(IMFMediaType_GetAllocatedBlob(type, &MF_MT_USER_DATA, &user_data, &user_data_size)))
|
||||
+ {
|
||||
+ GstBuffer *codec_data_buffer = gst_buffer_new_allocate(NULL, user_data_size, NULL);
|
||||
+ gst_buffer_fill(codec_data_buffer, 0, user_data, user_data_size);
|
||||
+ gst_caps_set_simple(caps, "codec_data", GST_TYPE_BUFFER, codec_data_buffer, NULL);
|
||||
+ gst_buffer_unref(codec_data_buffer);
|
||||
+ CoTaskMemFree(user_data);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
GstCaps *caps_from_mf_media_type(IMFMediaType *type)
|
||||
{
|
||||
GUID major_type;
|
||||
@@ -1112,6 +1127,42 @@ GstCaps *caps_from_mf_media_type(IMFMediaType *type)
|
||||
gst_caps_set_simple(output, "level", G_TYPE_STRING, level, NULL);
|
||||
}
|
||||
}
|
||||
+ else if (IsEqualGUID(&subtype, &MFVideoFormat_WMV1))
|
||||
+ {
|
||||
+ output = gst_caps_new_empty_simple("video/x-wmv");
|
||||
+ gst_caps_set_simple(output, "format", G_TYPE_STRING, "WMV1", NULL);
|
||||
+
|
||||
+ gst_caps_set_simple(output, "wmvversion", G_TYPE_INT, 1, NULL);
|
||||
+
|
||||
+ user_data_to_codec_data(type, output);
|
||||
+ }
|
||||
+ else if (IsEqualGUID(&subtype, &MFVideoFormat_WMV2))
|
||||
+ {
|
||||
+ output = gst_caps_new_empty_simple("video/x-wmv");
|
||||
+ gst_caps_set_simple(output, "format", G_TYPE_STRING, "WMV2", NULL);
|
||||
+
|
||||
+ gst_caps_set_simple(output, "wmvversion", G_TYPE_INT, 2, NULL);
|
||||
+
|
||||
+ user_data_to_codec_data(type, output);
|
||||
+ }
|
||||
+ else if (IsEqualGUID(&subtype, &MFVideoFormat_WMV3))
|
||||
+ {
|
||||
+ output = gst_caps_new_empty_simple("video/x-wmv");
|
||||
+ gst_caps_set_simple(output, "format", G_TYPE_STRING, "WMV3", NULL);
|
||||
+
|
||||
+ gst_caps_set_simple(output, "wmvversion", G_TYPE_INT, 3, NULL);
|
||||
+
|
||||
+ user_data_to_codec_data(type, output);
|
||||
+ }
|
||||
+ else if (IsEqualGUID(&subtype, &MFVideoFormat_WVC1))
|
||||
+ {
|
||||
+ output = gst_caps_new_empty_simple("video/x-wmv");
|
||||
+ gst_caps_set_simple(output, "format", G_TYPE_STRING, "WVC1", NULL);
|
||||
+
|
||||
+ gst_caps_set_simple(output, "wmvversion", G_TYPE_INT, 3, NULL);
|
||||
+
|
||||
+ user_data_to_codec_data(type, output);
|
||||
+ }
|
||||
else
|
||||
{
|
||||
GstVideoFormat format = GST_VIDEO_FORMAT_UNKNOWN;
|
||||
--
|
||||
2.29.2
|
||||
|
@ -0,0 +1,30 @@
|
||||
From ac8e72e266b60cf5dcef5ecf256ee3c99d6c9f53 Mon Sep 17 00:00:00 2001
|
||||
From: Derek Lesho <dlesho@codeweavers.com>
|
||||
Date: Mon, 22 Mar 2021 15:50:29 -0400
|
||||
Subject: [PATCH 36/39] winegstreamer: Don't rely on max_size in unseekable
|
||||
parser.
|
||||
|
||||
Signed-off-by: Derek Lesho <dlesho@codeweavers.com>
|
||||
---
|
||||
dlls/winegstreamer/wg_parser.c | 4 ++--
|
||||
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/dlls/winegstreamer/wg_parser.c b/dlls/winegstreamer/wg_parser.c
|
||||
index afd69ea6891..8e98ea08611 100644
|
||||
--- a/dlls/winegstreamer/wg_parser.c
|
||||
+++ b/dlls/winegstreamer/wg_parser.c
|
||||
@@ -1677,9 +1677,9 @@ static void *push_data(void *arg)
|
||||
ULONG size;
|
||||
int ret;
|
||||
|
||||
- if (parser->next_offset >= max_size)
|
||||
+ if (parser->seekable && parser->next_offset >= max_size)
|
||||
break;
|
||||
- size = min(alloc_size, max_size - parser->next_offset);
|
||||
+ size = parser->seekable ? min(alloc_size, max_size - parser->next_offset) : alloc_size;
|
||||
|
||||
ret = pull_data(parser, parser->next_offset, size, &size, &buffer);
|
||||
|
||||
--
|
||||
2.30.2
|
||||
|
@ -1,90 +0,0 @@
|
||||
From 09b135accfd48e079d6a2a3862e647b66b872b15 Mon Sep 17 00:00:00 2001
|
||||
From: Derek Lesho <dlesho@codeweavers.com>
|
||||
Date: Tue, 21 Apr 2020 10:31:02 -0500
|
||||
Subject: [PATCH] winegstreamer: Translate AAC attributes to caps.
|
||||
|
||||
Signed-off-by: Derek Lesho <dlesho@codeweavers.com>
|
||||
---
|
||||
dlls/winegstreamer/mfplat.c | 66 +++++++++++++++++++++++++++++++++++++
|
||||
1 file changed, 66 insertions(+)
|
||||
|
||||
diff --git a/dlls/winegstreamer/mfplat.c b/dlls/winegstreamer/mfplat.c
|
||||
index 2456d633c6c..b1f83f4fa6c 100644
|
||||
--- a/dlls/winegstreamer/mfplat.c
|
||||
+++ b/dlls/winegstreamer/mfplat.c
|
||||
@@ -1255,6 +1255,72 @@ GstCaps *caps_from_mf_media_type(IMFMediaType *type)
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
+ else if (IsEqualGUID(&subtype, &MFAudioFormat_AAC))
|
||||
+ {
|
||||
+ DWORD payload_type, indication;
|
||||
+ struct aac_user_data *user_data;
|
||||
+ UINT32 user_data_size;
|
||||
+ output = gst_caps_new_empty_simple("audio/mpeg");
|
||||
+
|
||||
+ /* Unsure of how to differentiate between mpegversion 2 and 4 */
|
||||
+ gst_caps_set_simple(output, "mpegversion", G_TYPE_INT, 4, NULL);
|
||||
+
|
||||
+ if (SUCCEEDED(IMFMediaType_GetUINT32(type, &MF_MT_AAC_PAYLOAD_TYPE, &payload_type)))
|
||||
+ {
|
||||
+ switch (payload_type)
|
||||
+ {
|
||||
+ case 0:
|
||||
+ gst_caps_set_simple(output, "stream-format", G_TYPE_STRING, "raw", NULL);
|
||||
+ break;
|
||||
+ case 1:
|
||||
+ gst_caps_set_simple(output, "stream-format", G_TYPE_STRING, "adts", NULL);
|
||||
+ break;
|
||||
+ case 2:
|
||||
+ gst_caps_set_simple(output, "stream-format", G_TYPE_STRING, "adif", NULL);
|
||||
+ break;
|
||||
+ case 3:
|
||||
+ gst_caps_set_simple(output, "stream-format", G_TYPE_STRING, "loas", NULL);
|
||||
+ break;
|
||||
+ default:
|
||||
+ gst_caps_set_simple(output, "stream-format", G_TYPE_STRING, "raw", NULL);
|
||||
+ }
|
||||
+ }
|
||||
+ else
|
||||
+ gst_caps_set_simple(output, "stream-format", G_TYPE_STRING, "raw", NULL);
|
||||
+
|
||||
+ if (SUCCEEDED(IMFMediaType_GetUINT32(type, &MF_MT_AAC_AUDIO_PROFILE_LEVEL_INDICATION, &indication)))
|
||||
+ {
|
||||
+ const char *profile, *level;
|
||||
+ switch (indication)
|
||||
+ {
|
||||
+ case 0x29: profile = "lc"; level = "2"; break;
|
||||
+ case 0x2A: profile = "lc"; level = "4"; break;
|
||||
+ case 0x2B: profile = "lc"; level = "5"; break;
|
||||
+ default:
|
||||
+ {
|
||||
+ profile = level = NULL;
|
||||
+ FIXME("Unrecognized profile-level-indication %u\n", indication);
|
||||
+ }
|
||||
+ }
|
||||
+ if (profile)
|
||||
+ gst_caps_set_simple(output, "profile", G_TYPE_STRING, profile, NULL);
|
||||
+ if (level)
|
||||
+ gst_caps_set_simple(output, "level", G_TYPE_STRING, level, NULL);
|
||||
+ }
|
||||
+
|
||||
+ if (SUCCEEDED(IMFMediaType_GetAllocatedBlob(type, &MF_MT_USER_DATA, (BYTE **) &user_data, &user_data_size)))
|
||||
+ {
|
||||
+ if (user_data_size > sizeof(*user_data))
|
||||
+ {
|
||||
+ GstBuffer *audio_specific_config = gst_buffer_new_allocate(NULL, user_data_size - sizeof(*user_data), NULL);
|
||||
+ gst_buffer_fill(audio_specific_config, 0, user_data + 1, user_data_size - sizeof(*user_data));
|
||||
+
|
||||
+ gst_caps_set_simple(output, "codec_data", GST_TYPE_BUFFER, audio_specific_config, NULL);
|
||||
+ gst_buffer_unref(audio_specific_config);
|
||||
+ }
|
||||
+ CoTaskMemFree(user_data);
|
||||
+ }
|
||||
+ }
|
||||
else
|
||||
{
|
||||
FIXME("Unrecognized subtype %s\n", debugstr_guid(&subtype));
|
||||
--
|
||||
2.29.2
|
||||
|
@ -0,0 +1,98 @@
|
||||
From 3666bd0c7cd99b5ae00f8f6fca83f316a9df398c Mon Sep 17 00:00:00 2001
|
||||
From: Derek Lesho <dlesho@codeweavers.com>
|
||||
Date: Mon, 22 Mar 2021 15:50:51 -0400
|
||||
Subject: [PATCH 37/39] winegstreamer: Implement MFT_MESSAGE_COMMAND_FLUSH for
|
||||
media converters.
|
||||
|
||||
Signed-off-by: Derek Lesho <dlesho@codeweavers.com>
|
||||
---
|
||||
dlls/winegstreamer/audioconvert.c | 20 ++++++++++++++++++++
|
||||
dlls/winegstreamer/colorconvert.c | 23 +++++++++++++++++++++++
|
||||
2 files changed, 43 insertions(+)
|
||||
|
||||
diff --git a/dlls/winegstreamer/audioconvert.c b/dlls/winegstreamer/audioconvert.c
|
||||
index 1584fefe577..df471122b9e 100644
|
||||
--- a/dlls/winegstreamer/audioconvert.c
|
||||
+++ b/dlls/winegstreamer/audioconvert.c
|
||||
@@ -614,11 +614,31 @@ static HRESULT WINAPI audio_converter_ProcessEvent(IMFTransform *iface, DWORD id
|
||||
|
||||
static HRESULT WINAPI audio_converter_ProcessMessage(IMFTransform *iface, MFT_MESSAGE_TYPE message, ULONG_PTR param)
|
||||
{
|
||||
+ struct audio_converter *converter = impl_audio_converter_from_IMFTransform(iface);
|
||||
+ struct wg_parser_event event;
|
||||
+
|
||||
TRACE("%p, %u %lu.\n", iface, message, param);
|
||||
|
||||
switch(message)
|
||||
{
|
||||
case MFT_MESSAGE_COMMAND_FLUSH:
|
||||
+ {
|
||||
+ EnterCriticalSection(&converter->cs);
|
||||
+ if (!converter->buffer_inflight)
|
||||
+ {
|
||||
+ LeaveCriticalSection(&converter->cs);
|
||||
+ return S_OK;
|
||||
+ }
|
||||
+
|
||||
+ while (event.type != WG_PARSER_EVENT_BUFFER)
|
||||
+ unix_funcs->wg_parser_stream_get_event(converter->stream, &event);
|
||||
+
|
||||
+ unix_funcs->wg_parser_stream_release_buffer(converter->stream);
|
||||
+ converter->buffer_inflight = FALSE;
|
||||
+
|
||||
+ LeaveCriticalSection(&converter->cs);
|
||||
+ return S_OK;
|
||||
+ }
|
||||
case MFT_MESSAGE_NOTIFY_BEGIN_STREAMING:
|
||||
return S_OK;
|
||||
default:
|
||||
diff --git a/dlls/winegstreamer/colorconvert.c b/dlls/winegstreamer/colorconvert.c
|
||||
index 6f3723b2b1e..947ef9adacb 100644
|
||||
--- a/dlls/winegstreamer/colorconvert.c
|
||||
+++ b/dlls/winegstreamer/colorconvert.c
|
||||
@@ -586,11 +586,31 @@ static HRESULT WINAPI color_converter_ProcessEvent(IMFTransform *iface, DWORD id
|
||||
|
||||
static HRESULT WINAPI color_converter_ProcessMessage(IMFTransform *iface, MFT_MESSAGE_TYPE message, ULONG_PTR param)
|
||||
{
|
||||
+ struct color_converter *converter = impl_color_converter_from_IMFTransform(iface);
|
||||
+ struct wg_parser_event event;
|
||||
+
|
||||
TRACE("%p, %u %lu.\n", iface, message, param);
|
||||
|
||||
switch(message)
|
||||
{
|
||||
case MFT_MESSAGE_COMMAND_FLUSH:
|
||||
+ {
|
||||
+ EnterCriticalSection(&converter->cs);
|
||||
+ if (!converter->buffer_inflight)
|
||||
+ {
|
||||
+ LeaveCriticalSection(&converter->cs);
|
||||
+ return S_OK;
|
||||
+ }
|
||||
+
|
||||
+ while (event.type != WG_PARSER_EVENT_BUFFER)
|
||||
+ unix_funcs->wg_parser_stream_get_event(converter->stream, &event);
|
||||
+
|
||||
+ unix_funcs->wg_parser_stream_release_buffer(converter->stream);
|
||||
+ converter->buffer_inflight = FALSE;
|
||||
+
|
||||
+ LeaveCriticalSection(&converter->cs);
|
||||
+ return S_OK;
|
||||
+ }
|
||||
case MFT_MESSAGE_NOTIFY_BEGIN_STREAMING:
|
||||
return S_OK;
|
||||
default:
|
||||
@@ -641,7 +661,10 @@ static HRESULT WINAPI color_converter_ProcessInput(IMFTransform *iface, DWORD id
|
||||
for (;;)
|
||||
{
|
||||
if (!unix_funcs->wg_parser_get_read_request(converter->parser, &data, &offset, &size))
|
||||
+ {
|
||||
+ TRACE("sink unconnected\n");
|
||||
continue;
|
||||
+ }
|
||||
|
||||
memcpy(data, buffer_data, min(buffer_size, size));
|
||||
|
||||
--
|
||||
2.30.2
|
||||
|
@ -1,32 +0,0 @@
|
||||
From 9638f311e7d31f5e4aa80e173c31396d774afb75 Mon Sep 17 00:00:00 2001
|
||||
From: Derek Lesho <dlesho@codeweavers.com>
|
||||
Date: Mon, 11 May 2020 16:03:09 -0500
|
||||
Subject: [PATCH] winegstreamer: Translate MPEG-4 Section-2 attributes to caps.
|
||||
|
||||
Signed-off-by: Derek Lesho <dlesho@codeweavers.com>
|
||||
---
|
||||
dlls/winegstreamer/mfplat.c | 8 ++++++++
|
||||
1 file changed, 8 insertions(+)
|
||||
|
||||
diff --git a/dlls/winegstreamer/mfplat.c b/dlls/winegstreamer/mfplat.c
|
||||
index b1f83f4fa6c..8906e472766 100644
|
||||
--- a/dlls/winegstreamer/mfplat.c
|
||||
+++ b/dlls/winegstreamer/mfplat.c
|
||||
@@ -1163,6 +1163,14 @@ GstCaps *caps_from_mf_media_type(IMFMediaType *type)
|
||||
|
||||
user_data_to_codec_data(type, output);
|
||||
}
|
||||
+ else if (IsEqualGUID(&subtype, &MFVideoFormat_M4S2))
|
||||
+ {
|
||||
+ output = gst_caps_new_empty_simple("video/mpeg");
|
||||
+ gst_caps_set_simple(output, "mpegversion", G_TYPE_INT, 4, NULL);
|
||||
+ gst_caps_set_simple(output, "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
|
||||
+
|
||||
+ user_data_to_codec_data(type, output);
|
||||
+ }
|
||||
else
|
||||
{
|
||||
GstVideoFormat format = GST_VIDEO_FORMAT_UNKNOWN;
|
||||
--
|
||||
2.29.2
|
||||
|
@ -0,0 +1,120 @@
|
||||
From a3c6815e44291b10a7756c8821e820b71be91fc6 Mon Sep 17 00:00:00 2001
|
||||
From: Giovanni Mascellani <gmascellani@codeweavers.com>
|
||||
Date: Mon, 22 Mar 2021 15:59:49 +0100
|
||||
Subject: [PATCH 38/39] mfreadwrite: Unset seeking flag also on SourceStarted
|
||||
and SourceStopped.
|
||||
|
||||
Signed-off-by: Giovanni Mascellani <gmascellani@codeweavers.com>
|
||||
Signed-off-by: Nikolay Sivov <nsivov@codeweavers.com>
|
||||
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
|
||||
---
|
||||
dlls/mfplat/buffer.c | 18 ++++++++++++++++--
|
||||
dlls/mfreadwrite/tests/mfplat.c | 6 ++++++
|
||||
dlls/winegstreamer/main.c | 1 +
|
||||
3 files changed, 23 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/dlls/mfplat/buffer.c b/dlls/mfplat/buffer.c
|
||||
index c1829043e1b..96eb02b3a61 100644
|
||||
--- a/dlls/mfplat/buffer.c
|
||||
+++ b/dlls/mfplat/buffer.c
|
||||
@@ -68,6 +68,7 @@ struct buffer
|
||||
ID3D11Texture2D *texture;
|
||||
unsigned int sub_resource_idx;
|
||||
ID3D11Texture2D *rb_texture;
|
||||
+ DXGI_FORMAT rb_texture_format;
|
||||
D3D11_MAPPED_SUBRESOURCE map_desc;
|
||||
struct attributes attributes;
|
||||
} dxgi_surface;
|
||||
@@ -890,6 +891,7 @@ static HRESULT dxgi_surface_buffer_create_readback_texture(struct buffer *buffer
|
||||
texture_desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE;
|
||||
texture_desc.MiscFlags = 0;
|
||||
texture_desc.MipLevels = 1;
|
||||
+ buffer->dxgi_surface.rb_texture_format = texture_desc.Format;
|
||||
if (FAILED(hr = ID3D11Device_CreateTexture2D(device, &texture_desc, NULL, &buffer->dxgi_surface.rb_texture)))
|
||||
WARN("Failed to create readback texture, hr %#x.\n", hr);
|
||||
|
||||
@@ -947,6 +949,7 @@ static HRESULT WINAPI dxgi_surface_buffer_Lock(IMFMediaBuffer *iface, BYTE **dat
|
||||
{
|
||||
struct buffer *buffer = impl_from_IMFMediaBuffer(iface);
|
||||
HRESULT hr = S_OK;
|
||||
+ DWORD lines;
|
||||
|
||||
TRACE("%p, %p, %p, %p.\n", iface, data, max_length, current_length);
|
||||
|
||||
@@ -967,8 +970,13 @@ static HRESULT WINAPI dxgi_surface_buffer_Lock(IMFMediaBuffer *iface, BYTE **dat
|
||||
hr = dxgi_surface_buffer_map(buffer);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
+ if (buffer->dxgi_surface.rb_texture_format == DXGI_FORMAT_NV12)
|
||||
+ lines = buffer->_2d.height * 3 / 2;
|
||||
+ else
|
||||
+ lines = buffer->_2d.height;
|
||||
+
|
||||
copy_image(buffer, buffer->_2d.linear_buffer, buffer->_2d.width, buffer->dxgi_surface.map_desc.pData,
|
||||
- buffer->dxgi_surface.map_desc.RowPitch, buffer->_2d.width, buffer->_2d.height);
|
||||
+ buffer->dxgi_surface.map_desc.RowPitch, buffer->_2d.width, lines);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -992,6 +1000,7 @@ static HRESULT WINAPI dxgi_surface_buffer_Unlock(IMFMediaBuffer *iface)
|
||||
{
|
||||
struct buffer *buffer = impl_from_IMFMediaBuffer(iface);
|
||||
HRESULT hr = S_OK;
|
||||
+ DWORD lines;
|
||||
|
||||
TRACE("%p.\n", iface);
|
||||
|
||||
@@ -1001,8 +1010,13 @@ static HRESULT WINAPI dxgi_surface_buffer_Unlock(IMFMediaBuffer *iface)
|
||||
hr = HRESULT_FROM_WIN32(ERROR_WAS_UNLOCKED);
|
||||
else if (!--buffer->_2d.locks)
|
||||
{
|
||||
+ if (buffer->dxgi_surface.rb_texture_format == DXGI_FORMAT_NV12)
|
||||
+ lines = buffer->_2d.height * 3 / 2;
|
||||
+ else
|
||||
+ lines = buffer->_2d.height;
|
||||
+
|
||||
copy_image(buffer, buffer->dxgi_surface.map_desc.pData, buffer->dxgi_surface.map_desc.RowPitch,
|
||||
- buffer->_2d.linear_buffer, buffer->_2d.width, buffer->_2d.width, buffer->_2d.height);
|
||||
+ buffer->_2d.linear_buffer, buffer->_2d.width, buffer->_2d.width, lines);
|
||||
dxgi_surface_buffer_unmap(buffer);
|
||||
|
||||
free(buffer->_2d.linear_buffer);
|
||||
diff --git a/dlls/mfreadwrite/tests/mfplat.c b/dlls/mfreadwrite/tests/mfplat.c
|
||||
index e3ff7f6e7aa..ba821df2190 100644
|
||||
--- a/dlls/mfreadwrite/tests/mfplat.c
|
||||
+++ b/dlls/mfreadwrite/tests/mfplat.c
|
||||
@@ -508,6 +508,7 @@ static IMFMediaSource *create_test_source(int stream_count)
|
||||
{
|
||||
struct test_source *source;
|
||||
int i;
|
||||
+ PROPVARIANT pos;
|
||||
|
||||
source = heap_alloc_zero(sizeof(*source));
|
||||
source->IMFMediaSource_iface.lpVtbl = &test_source_vtbl;
|
||||
@@ -924,6 +925,11 @@ static void test_source_reader_from_media_source(void)
|
||||
hr = IMFSourceReader_SetCurrentPosition(reader, &GUID_NULL, &pos);
|
||||
ok(hr == S_OK, "Failed to seek to beginning of stream, hr %#x.\n", hr);
|
||||
|
||||
+ pos.vt = VT_I8;
|
||||
+ pos.hVal.QuadPart = 0;
|
||||
+ hr = IMFSourceReader_SetCurrentPosition(reader, &GUID_NULL, &pos);
|
||||
+ ok(hr == S_OK, "Failed to seek to beginning of stream, hr %#x.\n", hr);
|
||||
+
|
||||
hr = IMFSourceReader_ReadSample(reader, MF_SOURCE_READER_ANY_STREAM, 0, &actual_index, &stream_flags,
|
||||
×tamp, &sample);
|
||||
ok(hr == S_OK, "Failed to get a sample, hr %#x.\n", hr);
|
||||
diff --git a/dlls/winegstreamer/main.c b/dlls/winegstreamer/main.c
|
||||
index 16fd6147ddf..f6206fa5e2b 100644
|
||||
--- a/dlls/winegstreamer/main.c
|
||||
+++ b/dlls/winegstreamer/main.c
|
||||
@@ -39,6 +39,7 @@ BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, void *reserved)
|
||||
{
|
||||
DisableThreadLibraryCalls(instance);
|
||||
__wine_init_unix_lib(instance, reason, NULL, &unix_funcs);
|
||||
+ init_gstreamer();
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
--
|
||||
2.30.2
|
||||
|
@ -1,39 +0,0 @@
|
||||
From e16c1d7b27467663a90eb23863d8110627ec3ad1 Mon Sep 17 00:00:00 2001
|
||||
From: Derek Lesho <dlesho@codeweavers.com>
|
||||
Date: Tue, 12 May 2020 17:05:59 -0500
|
||||
Subject: [PATCH] winegstreamer: Translate WMA attributes to caps.
|
||||
|
||||
Signed-off-by: Derek Lesho <dlesho@codeweavers.com>
|
||||
---
|
||||
dlls/winegstreamer/mfplat.c | 15 +++++++++++++++
|
||||
1 file changed, 15 insertions(+)
|
||||
|
||||
diff --git a/dlls/winegstreamer/mfplat.c b/dlls/winegstreamer/mfplat.c
|
||||
index 8906e472766..bf3486d2be8 100644
|
||||
--- a/dlls/winegstreamer/mfplat.c
|
||||
+++ b/dlls/winegstreamer/mfplat.c
|
||||
@@ -1329,6 +1329,21 @@ GstCaps *caps_from_mf_media_type(IMFMediaType *type)
|
||||
CoTaskMemFree(user_data);
|
||||
}
|
||||
}
|
||||
+ else if (IsEqualGUID(&subtype, &MFAudioFormat_WMAudioV9) ||
|
||||
+ IsEqualGUID(&subtype, &MFAudioFormat_WMAudioV8))
|
||||
+ {
|
||||
+ DWORD block_align;
|
||||
+
|
||||
+ output = gst_caps_new_empty_simple("audio/x-wma");
|
||||
+
|
||||
+ gst_caps_set_simple(output, "wmaversion", G_TYPE_INT,
|
||||
+ IsEqualGUID(&subtype, &MFAudioFormat_WMAudioV9) ? 3 : 2, NULL);
|
||||
+
|
||||
+ if (SUCCEEDED(IMFMediaType_GetUINT32(type, &MF_MT_AUDIO_BLOCK_ALIGNMENT, &block_align)))
|
||||
+ gst_caps_set_simple(output, "block_align", G_TYPE_INT, block_align, NULL);
|
||||
+
|
||||
+ user_data_to_codec_data(type, output);
|
||||
+ }
|
||||
else
|
||||
{
|
||||
FIXME("Unrecognized subtype %s\n", debugstr_guid(&subtype));
|
||||
--
|
||||
2.29.2
|
||||
|
@ -1,167 +0,0 @@
|
||||
From dd690ffa7c0a3b2a067f0f2fc1ec7f99cfc9d343 Mon Sep 17 00:00:00 2001
|
||||
From: Derek Lesho <dlesho@codeweavers.com>
|
||||
Date: Wed, 29 Jan 2020 15:37:39 -0600
|
||||
Subject: [PATCH] tools: Add support for multiple parent directories.
|
||||
|
||||
Signed-off-by: Derek Lesho <dlesho@codeweavers.com>
|
||||
---
|
||||
tools/make_makefiles | 45 +++++++++++++++++++++++++++-----------------
|
||||
tools/makedep.c | 26 +++++++++++++++++--------
|
||||
2 files changed, 46 insertions(+), 25 deletions(-)
|
||||
|
||||
diff --git a/tools/make_makefiles b/tools/make_makefiles
|
||||
index 2d3c14cb2ec..cb4a808244d 100755
|
||||
--- a/tools/make_makefiles
|
||||
+++ b/tools/make_makefiles
|
||||
@@ -229,14 +229,14 @@ sub parse_makefile($)
|
||||
{
|
||||
die "Configure substitution is not allowed in $file" unless $file eq "Makefile";
|
||||
}
|
||||
- if (/^\s*(MODULE|IMPORTLIB|TESTDLL|PARENTSRC|APPMODE|EXTRADLLFLAGS)\s*=\s*(.*)/)
|
||||
+ if (/^\s*(MODULE|IMPORTLIB|TESTDLL|APPMODE|EXTRADLLFLAGS)\s*=\s*(.*)/)
|
||||
{
|
||||
my $var = $1;
|
||||
$make{$var} = $2;
|
||||
next;
|
||||
}
|
||||
my $source_vars_regexp = join "|", @source_vars;
|
||||
- if (/^\s*($source_vars_regexp|PROGRAMS|EXTRA_TARGETS|EXTRA_OBJS|INSTALL_LIB|INSTALL_DEV)\s*=\s*(.*)/)
|
||||
+ if (/^\s*($source_vars_regexp|PROGRAMS|EXTRA_TARGETS|EXTRA_OBJS|INSTALL_LIB|INSTALL_DEV|PARENTSRC)\s*=\s*(.*)/)
|
||||
{
|
||||
my $var = $1;
|
||||
my @list = split(/\s+/, $2);
|
||||
@@ -291,19 +291,27 @@ sub get_makedep_flags($)
|
||||
return %flags;
|
||||
}
|
||||
|
||||
-sub get_parent_makefile($)
|
||||
+sub get_parent_makefiles($)
|
||||
{
|
||||
my $file = shift;
|
||||
my %make = %{$makefiles{$file}};
|
||||
- my $reldir = $make{"PARENTSRC"} || "";
|
||||
- return "" unless $reldir;
|
||||
- (my $path = $file) =~ s/\/Makefile$/\//;
|
||||
- while ($reldir =~ /^\.\.\//)
|
||||
+ my $pointer = $make{"PARENTSRC"} || ();
|
||||
+ return () unless $pointer;
|
||||
+ my @reldirs = @{$pointer};
|
||||
+ my @makefiles = ();
|
||||
+ foreach my $reldir (@reldirs)
|
||||
{
|
||||
- $reldir =~ s/^\.\.\///;
|
||||
- $path =~ s/[^\/]+\/$//;
|
||||
+ my $length = @reldirs;
|
||||
+ (my $path = $file) =~ s/\/Makefile$/\//;
|
||||
+ while ($reldir =~ /^\.\.\//)
|
||||
+ {
|
||||
+ $reldir =~ s/^\.\.\///;
|
||||
+ $path =~ s/[^\/]+\/$//;
|
||||
+ }
|
||||
+ push @makefiles, "$path$reldir/Makefile";
|
||||
}
|
||||
- return "$path$reldir/Makefile";
|
||||
+
|
||||
+ return @makefiles
|
||||
}
|
||||
|
||||
# preserve shared source files that are listed in the existing makefile
|
||||
@@ -404,13 +412,16 @@ sub assign_sources_to_makefiles(@)
|
||||
foreach my $file (@makefiles)
|
||||
{
|
||||
my $make = $makefiles{$file};
|
||||
- my $parent = get_parent_makefile( $file );
|
||||
- next unless $parent;
|
||||
- preserve_shared_source_files( $makefiles{$file}, $makefiles{$parent}, "C_SRCS" );
|
||||
- preserve_shared_source_files( $makefiles{$file}, $makefiles{$parent}, "RC_SRCS" );
|
||||
- preserve_shared_source_files( $makefiles{$file}, $makefiles{$parent}, "IDL_SRCS" );
|
||||
- preserve_shared_source_files( $makefiles{$file}, $makefiles{$parent}, "LEX_SRCS" );
|
||||
- preserve_shared_source_files( $makefiles{$file}, $makefiles{$parent}, "BISON_SRCS" );
|
||||
+ my @parents = get_parent_makefiles( $file );
|
||||
+ next unless @parents;
|
||||
+ foreach my $parent (@parents)
|
||||
+ {
|
||||
+ preserve_shared_source_files( $makefiles{$file}, $makefiles{$parent}, "C_SRCS" );
|
||||
+ preserve_shared_source_files( $makefiles{$file}, $makefiles{$parent}, "RC_SRCS" );
|
||||
+ preserve_shared_source_files( $makefiles{$file}, $makefiles{$parent}, "IDL_SRCS" );
|
||||
+ preserve_shared_source_files( $makefiles{$file}, $makefiles{$parent}, "LEX_SRCS" );
|
||||
+ preserve_shared_source_files( $makefiles{$file}, $makefiles{$parent}, "BISON_SRCS" );
|
||||
+ }
|
||||
}
|
||||
}
|
||||
|
||||
diff --git a/tools/makedep.c b/tools/makedep.c
|
||||
index d892b7e9541..688487ffd82 100644
|
||||
--- a/tools/makedep.c
|
||||
+++ b/tools/makedep.c
|
||||
@@ -190,11 +190,11 @@ struct makefile
|
||||
struct strarray install_dev;
|
||||
struct strarray extra_targets;
|
||||
struct strarray extra_imports;
|
||||
+ struct strarray parent_dirs;
|
||||
struct list sources;
|
||||
struct list includes;
|
||||
const char *src_dir;
|
||||
const char *obj_dir;
|
||||
- const char *parent_dir;
|
||||
const char *module;
|
||||
const char *testdll;
|
||||
const char *sharedlib;
|
||||
@@ -1388,14 +1388,21 @@ static struct file *open_local_file( const struct makefile *make, const char *pa
|
||||
{
|
||||
char *src_path = src_dir_path( make, path );
|
||||
struct file *ret = load_file( src_path );
|
||||
+ unsigned int i;
|
||||
|
||||
- /* if not found, try parent dir */
|
||||
- if (!ret && make->parent_dir)
|
||||
+ /* if not found, try parent dirs */
|
||||
+ for (i = 0; !ret && i < make->parent_dirs.count; i++)
|
||||
{
|
||||
+ char *new_path;
|
||||
+
|
||||
free( src_path );
|
||||
- path = strmake( "%s/%s", make->parent_dir, path );
|
||||
- src_path = src_dir_path( make, path );
|
||||
+ new_path = strmake( "%s/%s", make->parent_dirs.str[i], path );
|
||||
+ src_path = src_dir_path( make, new_path );
|
||||
ret = load_file( src_path );
|
||||
+ if (ret)
|
||||
+ path = new_path;
|
||||
+ else
|
||||
+ free(new_path);
|
||||
}
|
||||
|
||||
if (ret) *filename = src_path;
|
||||
@@ -4158,13 +4165,13 @@ static void load_sources( struct makefile *make )
|
||||
strarray_set_value( &make->vars, "top_srcdir", root_src_dir_path( "" ));
|
||||
strarray_set_value( &make->vars, "srcdir", src_dir_path( make, "" ));
|
||||
|
||||
- make->parent_dir = get_expanded_make_variable( make, "PARENTSRC" );
|
||||
make->module = get_expanded_make_variable( make, "MODULE" );
|
||||
make->testdll = get_expanded_make_variable( make, "TESTDLL" );
|
||||
make->sharedlib = get_expanded_make_variable( make, "SHAREDLIB" );
|
||||
make->staticlib = get_expanded_make_variable( make, "STATICLIB" );
|
||||
make->importlib = get_expanded_make_variable( make, "IMPORTLIB" );
|
||||
|
||||
+ make->parent_dirs = get_expanded_make_var_array( make, "PARENTSRC" );
|
||||
make->programs = get_expanded_make_var_array( make, "PROGRAMS" );
|
||||
make->scripts = get_expanded_make_var_array( make, "SCRIPTS" );
|
||||
make->imports = get_expanded_make_var_array( make, "IMPORTS" );
|
||||
@@ -4209,8 +4216,11 @@ static void load_sources( struct makefile *make )
|
||||
strarray_add( &make->include_args, strmake( "-I%s", obj_dir_path( make, "" )));
|
||||
if (make->src_dir)
|
||||
strarray_add( &make->include_args, strmake( "-I%s", make->src_dir ));
|
||||
- if (make->parent_dir)
|
||||
- strarray_add( &make->include_args, strmake( "-I%s", src_dir_path( make, make->parent_dir )));
|
||||
+ if (make->parent_dirs.count)
|
||||
+ {
|
||||
+ for (i = 0; i < make->parent_dirs.count; i++)
|
||||
+ strarray_add( &make->include_args, strmake( "-I%s", src_dir_path( make, make->parent_dirs.str[i] )));
|
||||
+ }
|
||||
strarray_add( &make->include_args, "-Iinclude" );
|
||||
if (root_src_dir) strarray_add( &make->include_args, strmake( "-I%s", root_src_dir_path( "include" )));
|
||||
|
||||
--
|
||||
2.29.2
|
||||
|
@ -0,0 +1,44 @@
|
||||
From 9113e5421fd865f783f2bb3101336491fc92404d Mon Sep 17 00:00:00 2001
|
||||
From: Alistair Leslie-Hughes <leslie_alistair@hotmail.com>
|
||||
Date: Sun, 20 Jun 2021 14:46:57 +1000
|
||||
Subject: [PATCH] winegstreamer: Default Frame size if one isn't available
|
||||
|
||||
Stop crash when loading steam
|
||||
---
|
||||
dlls/winegstreamer/mfplat.c | 15 ++++++++-------
|
||||
1 file changed, 8 insertions(+), 7 deletions(-)
|
||||
|
||||
diff --git a/dlls/winegstreamer/mfplat.c b/dlls/winegstreamer/mfplat.c
|
||||
index 251ab021073..19fd2596a47 100644
|
||||
--- a/dlls/winegstreamer/mfplat.c
|
||||
+++ b/dlls/winegstreamer/mfplat.c
|
||||
@@ -837,18 +837,19 @@ static void mf_media_type_to_wg_format_video(IMFMediaType *type, struct wg_forma
|
||||
FIXME("Subtype is not set.\n");
|
||||
return;
|
||||
}
|
||||
- if (FAILED(IMFMediaType_GetUINT64(type, &MF_MT_FRAME_SIZE, &frame_size)))
|
||||
- {
|
||||
- FIXME("Frame size is not set.\n");
|
||||
- return;
|
||||
- }
|
||||
|
||||
format->major_type = WG_MAJOR_TYPE_VIDEO;
|
||||
- format->u.video.width = (UINT32)(frame_size >> 32);
|
||||
- format->u.video.height = (UINT32)frame_size;
|
||||
+ format->u.video.width = 0;
|
||||
+ format->u.video.height = 0;
|
||||
format->u.video.fps_n = 1;
|
||||
format->u.video.fps_d = 1;
|
||||
|
||||
+ if (SUCCEEDED(IMFMediaType_GetUINT64(type, &MF_MT_FRAME_SIZE, &frame_size)) && (UINT32)frame_size)
|
||||
+ {
|
||||
+ format->u.video.width = (UINT32)(frame_size >> 32);
|
||||
+ format->u.video.height = (UINT32)frame_size;
|
||||
+ }
|
||||
+
|
||||
if (SUCCEEDED(IMFMediaType_GetUINT64(type, &MF_MT_FRAME_RATE, &frame_rate)) && (UINT32)frame_rate)
|
||||
{
|
||||
format->u.video.fps_n = (UINT32)(frame_rate >> 32);
|
||||
--
|
||||
2.30.2
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -1,28 +0,0 @@
|
||||
From 7fa665fa4360cf8656c30683c84280c1751850c0 Mon Sep 17 00:00:00 2001
|
||||
From: Derek Lesho <dlesho@codeweavers.com>
|
||||
Date: Mon, 23 Mar 2020 11:55:41 -0500
|
||||
Subject: [PATCH] mfreadwrite: Select all streams when creating a source
|
||||
reader.
|
||||
|
||||
---
|
||||
dlls/mfreadwrite/reader.c | 4 ++++
|
||||
1 file changed, 4 insertions(+)
|
||||
|
||||
diff --git a/dlls/mfreadwrite/reader.c b/dlls/mfreadwrite/reader.c
|
||||
index 85aec9aaedc..77ce301d8be 100644
|
||||
--- a/dlls/mfreadwrite/reader.c
|
||||
+++ b/dlls/mfreadwrite/reader.c
|
||||
@@ -2138,6 +2138,10 @@ static HRESULT create_source_reader_from_source(IMFMediaSource *source, IMFAttri
|
||||
break;
|
||||
|
||||
object->streams[i].index = i;
|
||||
+
|
||||
+ hr = IMFPresentationDescriptor_SelectStream(object->descriptor, i);
|
||||
+ if (FAILED(hr))
|
||||
+ break;
|
||||
}
|
||||
|
||||
if (FAILED(hr))
|
||||
--
|
||||
2.29.2
|
||||
|
@ -1,155 +0,0 @@
|
||||
From 2cc1a2009879fec87340b1818111f3cea6fe2442 Mon Sep 17 00:00:00 2001
|
||||
From: Derek Lesho <dlesho@codeweavers.com>
|
||||
Date: Mon, 2 Nov 2020 09:58:09 -0600
|
||||
Subject: [PATCH] Miscellaneous
|
||||
|
||||
---
|
||||
dlls/mfreadwrite/reader.c | 12 +++++++++++-
|
||||
dlls/winegstreamer/gst_cbs.c | 20 +++++++++-----------
|
||||
dlls/winegstreamer/gst_cbs.h | 1 -
|
||||
dlls/winegstreamer/media_source.c | 24 +++++++++++++++++++++++-
|
||||
4 files changed, 43 insertions(+), 14 deletions(-)
|
||||
|
||||
diff --git a/dlls/mfreadwrite/reader.c b/dlls/mfreadwrite/reader.c
|
||||
index 77ce301d8be..9fdef9a8c9c 100644
|
||||
--- a/dlls/mfreadwrite/reader.c
|
||||
+++ b/dlls/mfreadwrite/reader.c
|
||||
@@ -1584,6 +1584,7 @@ static HRESULT source_reader_create_decoder_for_stream(struct source_reader *rea
|
||||
{
|
||||
MFT_REGISTER_TYPE_INFO in_type, out_type;
|
||||
CLSID *clsids, mft_clsid, category;
|
||||
+ BOOL decoder_found = FALSE;
|
||||
unsigned int i = 0, count;
|
||||
IMFMediaType *input_type;
|
||||
HRESULT hr;
|
||||
@@ -1630,12 +1631,21 @@ static HRESULT source_reader_create_decoder_for_stream(struct source_reader *rea
|
||||
}
|
||||
|
||||
}
|
||||
+ else if (!decoder_found)
|
||||
+ {
|
||||
+ /* see if there are other decoders for this stream */
|
||||
+ if (SUCCEEDED(MFTEnum(category, 0, &in_type, NULL, NULL, &clsids, &count)) && count)
|
||||
+ {
|
||||
+ decoder_found = TRUE;
|
||||
+ CoTaskMemFree(clsids);
|
||||
+ }
|
||||
+ }
|
||||
}
|
||||
|
||||
IMFMediaType_Release(input_type);
|
||||
}
|
||||
|
||||
- return MF_E_TOPO_CODEC_NOT_FOUND;
|
||||
+ return decoder_found ? MF_E_INVALIDREQUEST : MF_E_TOPO_CODEC_NOT_FOUND;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI src_reader_SetCurrentMediaType(IMFSourceReader *iface, DWORD index, DWORD *reserved,
|
||||
diff --git a/dlls/winegstreamer/gst_cbs.c b/dlls/winegstreamer/gst_cbs.c
|
||||
index 261a5b9f4ce..81692fdf919 100644
|
||||
--- a/dlls/winegstreamer/gst_cbs.c
|
||||
+++ b/dlls/winegstreamer/gst_cbs.c
|
||||
@@ -18,6 +18,9 @@
|
||||
|
||||
#include "config.h"
|
||||
|
||||
+#include <stdio.h>
|
||||
+#include <assert.h>
|
||||
+
|
||||
#include <gst/gst.h>
|
||||
|
||||
#include "objbase.h"
|
||||
@@ -53,6 +56,12 @@ static void CALLBACK perform_cb(TP_CALLBACK_INSTANCE *instance, void *user)
|
||||
perform_cb_media_source(cbdata);
|
||||
else if (cbdata->type < MF_DECODE_MAX)
|
||||
perform_cb_mf_decode(cbdata);
|
||||
+ else
|
||||
+ {
|
||||
+ fprintf(stderr, "No handler registered for callback\n");
|
||||
+ assert(0);
|
||||
+ }
|
||||
+
|
||||
|
||||
pthread_mutex_lock(&cbdata->lock);
|
||||
cbdata->finished = 1;
|
||||
@@ -447,17 +456,6 @@ GstBusSyncReply watch_decoder_bus_wrapper(GstBus *bus, GstMessage *message, gpoi
|
||||
return cbdata.u.watch_bus_data.ret;
|
||||
}
|
||||
|
||||
-void decoder_pad_added_wrapper(GstElement *element, GstPad *pad, gpointer user)
|
||||
-{
|
||||
- struct cb_data cbdata = { DECODER_PAD_ADDED };
|
||||
-
|
||||
- cbdata.u.pad_added_data.element = element;
|
||||
- cbdata.u.pad_added_data.pad = pad;
|
||||
- cbdata.u.pad_added_data.user = user;
|
||||
-
|
||||
- call_cb(&cbdata);
|
||||
-}
|
||||
-
|
||||
GstFlowReturn decoder_new_sample_wrapper(GstElement *appsink, gpointer user)
|
||||
{
|
||||
struct cb_data cbdata = {DECODER_NEW_SAMPLE};
|
||||
diff --git a/dlls/winegstreamer/gst_cbs.h b/dlls/winegstreamer/gst_cbs.h
|
||||
index 6659aedefa5..825b46d13bb 100644
|
||||
--- a/dlls/winegstreamer/gst_cbs.h
|
||||
+++ b/dlls/winegstreamer/gst_cbs.h
|
||||
@@ -194,6 +194,5 @@ gboolean activate_push_mode_wrapper(GstPad *pad, GstObject *parent, GstPadMode m
|
||||
gboolean query_input_src_wrapper(GstPad *pad, GstObject *parent, GstQuery *query) DECLSPEC_HIDDEN;
|
||||
GstBusSyncReply watch_decoder_bus_wrapper(GstBus *bus, GstMessage *message, gpointer user) DECLSPEC_HIDDEN;
|
||||
GstFlowReturn decoder_new_sample_wrapper(GstElement *appsink, gpointer user) DECLSPEC_HIDDEN;
|
||||
-void decoder_pad_added_wrapper(GstElement *element, GstPad *Pad, gpointer user) DECLSPEC_HIDDEN;
|
||||
|
||||
#endif
|
||||
diff --git a/dlls/winegstreamer/media_source.c b/dlls/winegstreamer/media_source.c
|
||||
index 5f46f7d575a..2156e07a13c 100644
|
||||
--- a/dlls/winegstreamer/media_source.c
|
||||
+++ b/dlls/winegstreamer/media_source.c
|
||||
@@ -554,6 +554,11 @@ static gboolean bytestream_query(GstPad *pad, GstObject *parent, GstQuery *query
|
||||
gst_query_add_scheduling_mode(query, GST_PAD_MODE_PULL);
|
||||
return TRUE;
|
||||
}
|
||||
+ case GST_QUERY_LATENCY:
|
||||
+ {
|
||||
+ gst_query_set_latency(query, FALSE, 0, 0);
|
||||
+ return TRUE;
|
||||
+ }
|
||||
default:
|
||||
{
|
||||
WARN("Unhandled query type %s\n", GST_QUERY_TYPE_NAME(query));
|
||||
@@ -616,6 +621,23 @@ GstBusSyncReply bus_watch(GstBus *bus, GstMessage *message, gpointer user)
|
||||
g_error_free(err);
|
||||
g_free(dbg_info);
|
||||
break;
|
||||
+ case GST_MESSAGE_TAG:
|
||||
+ {
|
||||
+ GstTagList *tag_list;
|
||||
+ gchar *printable;
|
||||
+ gst_message_parse_tag(message, &tag_list);
|
||||
+ if (tag_list)
|
||||
+ {
|
||||
+ printable = gst_tag_list_to_string(tag_list);
|
||||
+ if (printable)
|
||||
+ {
|
||||
+ TRACE("tag test: %s\n", debugstr_a(printable));
|
||||
+ g_free(printable);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ break;
|
||||
+ }
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -1154,7 +1176,7 @@ static HRESULT WINAPI media_source_GetCharacteristics(IMFMediaSource *iface, DWO
|
||||
if (source->state == SOURCE_SHUTDOWN)
|
||||
return MF_E_SHUTDOWN;
|
||||
|
||||
- *characteristics = MFMEDIASOURCE_CAN_SEEK;
|
||||
+ *characteristics = MFMEDIASOURCE_CAN_SEEK | MFMEDIASOURCE_CAN_PAUSE;
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
--
|
||||
2.29.2
|
||||
|
@ -1,153 +0,0 @@
|
||||
From c918862beea585aa413d3a629e5818a762d1568f Mon Sep 17 00:00:00 2001
|
||||
From: Derek Lesho <dlesho@codeweavers.com>
|
||||
Date: Wed, 25 Mar 2020 19:07:11 -0500
|
||||
Subject: [PATCH] WMV
|
||||
|
||||
---
|
||||
dlls/winegstreamer/gst_private.h | 1 +
|
||||
dlls/winegstreamer/mf_decode.c | 10 +++++
|
||||
dlls/winegstreamer/mfplat.c | 40 ++++++++++++++++++++
|
||||
dlls/winegstreamer/winegstreamer_classes.idl | 6 +++
|
||||
include/mfidl.idl | 2 +
|
||||
5 files changed, 59 insertions(+)
|
||||
|
||||
diff --git a/dlls/winegstreamer/gst_private.h b/dlls/winegstreamer/gst_private.h
|
||||
index 019cce5fad5..02343fa676e 100644
|
||||
--- a/dlls/winegstreamer/gst_private.h
|
||||
+++ b/dlls/winegstreamer/gst_private.h
|
||||
@@ -90,6 +90,7 @@ enum decoder_type
|
||||
{
|
||||
DECODER_TYPE_H264,
|
||||
DECODER_TYPE_AAC,
|
||||
+ DECODER_TYPE_WMV,
|
||||
};
|
||||
HRESULT generic_decoder_construct(REFIID riid, void **obj, enum decoder_type) DECLSPEC_HIDDEN;
|
||||
HRESULT winegstreamer_stream_handler_create(REFIID riid, void **obj) DECLSPEC_HIDDEN;
|
||||
diff --git a/dlls/winegstreamer/mf_decode.c b/dlls/winegstreamer/mf_decode.c
|
||||
index 7055ffa54fc..3625382c573 100644
|
||||
--- a/dlls/winegstreamer/mf_decode.c
|
||||
+++ b/dlls/winegstreamer/mf_decode.c
|
||||
@@ -29,6 +29,9 @@ const GUID *h264_output_types[] = {&MFVideoFormat_NV12, &MFVideoFormat_I420, &MF
|
||||
const GUID *aac_input_types[] = {&MFAudioFormat_AAC};
|
||||
const GUID *aac_output_types[] = {&MFAudioFormat_Float};
|
||||
|
||||
+const GUID *wmv_input_types[] = {&MFVideoFormat_WMV3, &MFVideoFormat_WVC1};
|
||||
+const GUID *wmv_output_types[] = {&MFVideoFormat_NV12, &MFVideoFormat_YV12, &MFVideoFormat_YUY2, &MFVideoFormat_UYVY, &MFVideoFormat_YVYU, &MFVideoFormat_NV11, &MFVideoFormat_RGB32, &MFVideoFormat_RGB24, &MFVideoFormat_RGB555, &MFVideoFormat_RGB8};
|
||||
+
|
||||
static struct decoder_desc
|
||||
{
|
||||
const GUID *major_type;
|
||||
@@ -51,6 +54,13 @@ static struct decoder_desc
|
||||
ARRAY_SIZE(aac_input_types),
|
||||
aac_output_types,
|
||||
ARRAY_SIZE(aac_output_types),
|
||||
+ },
|
||||
+ { /* DECODER_TYPE_WMV */
|
||||
+ &MFMediaType_Video,
|
||||
+ wmv_input_types,
|
||||
+ ARRAY_SIZE(wmv_input_types),
|
||||
+ wmv_output_types,
|
||||
+ ARRAY_SIZE(wmv_output_types),
|
||||
}
|
||||
};
|
||||
|
||||
diff --git a/dlls/winegstreamer/mfplat.c b/dlls/winegstreamer/mfplat.c
|
||||
index b604f6df066..2fb730ff4c0 100644
|
||||
--- a/dlls/winegstreamer/mfplat.c
|
||||
+++ b/dlls/winegstreamer/mfplat.c
|
||||
@@ -420,6 +420,10 @@ static HRESULT aac_decoder_create(REFIID riid, void **ret)
|
||||
return generic_decoder_construct(riid, ret, DECODER_TYPE_AAC);
|
||||
}
|
||||
|
||||
+static HRESULT wmv_decoder_create(REFIID riid, void **ret)
|
||||
+{
|
||||
+ return generic_decoder_construct(riid, ret, DECODER_TYPE_WMV);
|
||||
+}
|
||||
static const struct class_object
|
||||
{
|
||||
const GUID *clsid;
|
||||
@@ -433,6 +437,7 @@ class_objects[] =
|
||||
{ &CLSID_WINEColorConverter, &color_converter_create },
|
||||
{ &CLSID_CMSH264DecoderMFT, &h264_decoder_create },
|
||||
{ &CLSID_CMSAACDecMFT, &aac_decoder_create },
|
||||
+ { &CLSID_CWMVDecMediaObject, &wmv_decoder_create },
|
||||
};
|
||||
|
||||
HRESULT mfplat_get_class_object(REFCLSID rclsid, REFIID riid, void **obj)
|
||||
@@ -514,6 +519,29 @@ const GUID *aac_decoder_output_types[] =
|
||||
&MFAudioFormat_PCM,
|
||||
};
|
||||
|
||||
+static WCHAR wmvdecoderW[] = {'W','M','V','i','d','e','o',' ','D','e','c','o','d','e','r',' ','M','F','T',0};
|
||||
+
|
||||
+const GUID *wmv_decoder_input_types[] =
|
||||
+{
|
||||
+ &MFVideoFormat_WMV3,
|
||||
+ &MFVideoFormat_WVC1,
|
||||
+};
|
||||
+
|
||||
+const GUID *wmv_decoder_output_types[] =
|
||||
+{
|
||||
+ &MFVideoFormat_NV12,
|
||||
+ &MFVideoFormat_YV12,
|
||||
+ &MFVideoFormat_YUY2,
|
||||
+ &MFVideoFormat_UYVY,
|
||||
+ &MFVideoFormat_YVYU,
|
||||
+ &MFVideoFormat_NV11,
|
||||
+ &MFVideoFormat_RGB32,
|
||||
+ &MFVideoFormat_RGB24,
|
||||
+ &MFVideoFormat_RGB565,
|
||||
+ &MFVideoFormat_RGB555,
|
||||
+ &MFVideoFormat_RGB8,
|
||||
+};
|
||||
+
|
||||
static const struct mft
|
||||
{
|
||||
const GUID *clsid;
|
||||
@@ -577,6 +605,18 @@ mfts[] =
|
||||
aac_decoder_output_types,
|
||||
NULL
|
||||
},
|
||||
+ {
|
||||
+ &CLSID_CWMVDecMediaObject,
|
||||
+ &MFT_CATEGORY_VIDEO_DECODER,
|
||||
+ wmvdecoderW,
|
||||
+ MFT_ENUM_FLAG_SYNCMFT,
|
||||
+ &MFMediaType_Video,
|
||||
+ ARRAY_SIZE(wmv_decoder_input_types),
|
||||
+ wmv_decoder_input_types,
|
||||
+ ARRAY_SIZE(wmv_decoder_output_types),
|
||||
+ wmv_decoder_output_types,
|
||||
+ NULL
|
||||
+ },
|
||||
};
|
||||
|
||||
HRESULT mfplat_DllRegisterServer(void)
|
||||
diff --git a/dlls/winegstreamer/winegstreamer_classes.idl b/dlls/winegstreamer/winegstreamer_classes.idl
|
||||
index fe8649c690c..3b29bbfc36d 100644
|
||||
--- a/dlls/winegstreamer/winegstreamer_classes.idl
|
||||
+++ b/dlls/winegstreamer/winegstreamer_classes.idl
|
||||
@@ -85,3 +85,9 @@ coclass CMSH264DecoderMFT { }
|
||||
uuid(32d186a7-218f-4c75-8876-dd77273a8999)
|
||||
]
|
||||
coclass CMSAACDecMFT { }
|
||||
+
|
||||
+[
|
||||
+ threading(both),
|
||||
+ uuid(82d353df-90bd-4382-8bc2-3f6192b76e34)
|
||||
+]
|
||||
+coclass CLSID_CWMVDecMediaObject {}
|
||||
diff --git a/include/mfidl.idl b/include/mfidl.idl
|
||||
index 4023c3a62d2..7cb027b156a 100644
|
||||
--- a/include/mfidl.idl
|
||||
+++ b/include/mfidl.idl
|
||||
@@ -1308,3 +1308,5 @@ cpp_quote("EXTERN_GUID(MF_ACTIVATE_CUSTOM_VIDEO_PRESENTER_FLAGS, 0xba491366, 0xb
|
||||
cpp_quote("EXTERN_GUID(CLSID_VideoProcessorMFT, 0x88753b26, 0x5b24, 0x49bd, 0xb2, 0xe7, 0xc, 0x44, 0x5c, 0x78, 0xc9, 0x82);")
|
||||
cpp_quote("EXTERN_GUID(CLSID_CMSH264DecoderMFT, 0x62ce7e72, 0x4c71, 0x4d20, 0xb1, 0x5d, 0x45, 0x28, 0x31, 0xa8, 0x7d, 0x9d);")
|
||||
cpp_quote("EXTERN_GUID(CLSID_CMSAACDecMFT, 0x32d186a7, 0x218f, 0x4c75, 0x88, 0x76, 0xdd, 0x77, 0x27, 0x3a, 0x89, 0x99);")
|
||||
+cpp_quote("EXTERN_GUID(CLSID_ASFByteStreamHandler, 0x41457294, 0x644c, 0x4298, 0xa2, 0x8a, 0xbd, 0x69, 0xf2, 0xc0, 0xcf, 0x3b);")
|
||||
+cpp_quote("EXTERN_GUID(CLSID_CWMVDecMediaObject, 0x82d353df, 0x90bd, 0x4382, 0x8b, 0xc2, 0x3f, 0x61, 0x92, 0xb7, 0x6e, 0x34);")
|
||||
\ No newline at end of file
|
||||
--
|
||||
2.29.2
|
||||
|
@ -1,25 +0,0 @@
|
||||
From 8b1429c51559a4cb5685cfcf11302f0b8a6e9f14 Mon Sep 17 00:00:00 2001
|
||||
From: Derek Lesho <dlesho@codeweavers.com>
|
||||
Date: Fri, 3 Apr 2020 11:12:33 -0500
|
||||
Subject: [PATCH] Expose PCM output type on AAC decoder.
|
||||
|
||||
---
|
||||
dlls/winegstreamer/mf_decode.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/dlls/winegstreamer/mf_decode.c b/dlls/winegstreamer/mf_decode.c
|
||||
index 3625382c573..c188d08c57f 100644
|
||||
--- a/dlls/winegstreamer/mf_decode.c
|
||||
+++ b/dlls/winegstreamer/mf_decode.c
|
||||
@@ -27,7 +27,7 @@ const GUID *h264_input_types[] = {&MFVideoFormat_H264};
|
||||
const GUID *h264_output_types[] = {&MFVideoFormat_NV12, &MFVideoFormat_I420, &MFVideoFormat_IYUV, &MFVideoFormat_YUY2, &MFVideoFormat_YV12};
|
||||
|
||||
const GUID *aac_input_types[] = {&MFAudioFormat_AAC};
|
||||
-const GUID *aac_output_types[] = {&MFAudioFormat_Float};
|
||||
+const GUID *aac_output_types[] = {&MFAudioFormat_Float, &MFAudioFormat_PCM};
|
||||
|
||||
const GUID *wmv_input_types[] = {&MFVideoFormat_WMV3, &MFVideoFormat_WVC1};
|
||||
const GUID *wmv_output_types[] = {&MFVideoFormat_NV12, &MFVideoFormat_YV12, &MFVideoFormat_YUY2, &MFVideoFormat_UYVY, &MFVideoFormat_YVYU, &MFVideoFormat_NV11, &MFVideoFormat_RGB32, &MFVideoFormat_RGB24, &MFVideoFormat_RGB555, &MFVideoFormat_RGB8};
|
||||
--
|
||||
2.29.2
|
||||
|
@ -1,153 +0,0 @@
|
||||
From 32e2cc5815a0f2836ba22f42e2eb7930289a18db Mon Sep 17 00:00:00 2001
|
||||
From: Derek Lesho <dlesho@codeweavers.com>
|
||||
Date: Mon, 11 May 2020 16:05:50 -0500
|
||||
Subject: [PATCH] winegstreamer: Introduce MPEG-4 Section-2 video decoder.
|
||||
|
||||
Signed-off-by: Derek Lesho <dlesho@codeweavers.com>
|
||||
---
|
||||
dlls/winegstreamer/gst_private.h | 1 +
|
||||
dlls/winegstreamer/mf_decode.c | 10 ++++++
|
||||
dlls/winegstreamer/mfplat.c | 35 ++++++++++++++++++++
|
||||
dlls/winegstreamer/winegstreamer_classes.idl | 6 ++++
|
||||
include/mfidl.idl | 1 +
|
||||
5 files changed, 53 insertions(+)
|
||||
|
||||
diff --git a/dlls/winegstreamer/gst_private.h b/dlls/winegstreamer/gst_private.h
|
||||
index 02343fa676e..1c6530d2f38 100644
|
||||
--- a/dlls/winegstreamer/gst_private.h
|
||||
+++ b/dlls/winegstreamer/gst_private.h
|
||||
@@ -91,6 +91,7 @@ enum decoder_type
|
||||
DECODER_TYPE_H264,
|
||||
DECODER_TYPE_AAC,
|
||||
DECODER_TYPE_WMV,
|
||||
+ DECODER_TYPE_M4S2,
|
||||
};
|
||||
HRESULT generic_decoder_construct(REFIID riid, void **obj, enum decoder_type) DECLSPEC_HIDDEN;
|
||||
HRESULT winegstreamer_stream_handler_create(REFIID riid, void **obj) DECLSPEC_HIDDEN;
|
||||
diff --git a/dlls/winegstreamer/mf_decode.c b/dlls/winegstreamer/mf_decode.c
|
||||
index c188d08c57f..b5220bc3332 100644
|
||||
--- a/dlls/winegstreamer/mf_decode.c
|
||||
+++ b/dlls/winegstreamer/mf_decode.c
|
||||
@@ -32,6 +32,9 @@ const GUID *aac_output_types[] = {&MFAudioFormat_Float, &MFAudioFormat_PCM};
|
||||
const GUID *wmv_input_types[] = {&MFVideoFormat_WMV3, &MFVideoFormat_WVC1};
|
||||
const GUID *wmv_output_types[] = {&MFVideoFormat_NV12, &MFVideoFormat_YV12, &MFVideoFormat_YUY2, &MFVideoFormat_UYVY, &MFVideoFormat_YVYU, &MFVideoFormat_NV11, &MFVideoFormat_RGB32, &MFVideoFormat_RGB24, &MFVideoFormat_RGB555, &MFVideoFormat_RGB8};
|
||||
|
||||
+const GUID *m4s2_input_types[] = {&MFVideoFormat_MPEG2};
|
||||
+const GUID *m4s2_output_types[] = {&MFVideoFormat_I420, &MFVideoFormat_IYUV, &MFVideoFormat_NV12, &MFVideoFormat_YUY2, &MFVideoFormat_YV12};
|
||||
+
|
||||
static struct decoder_desc
|
||||
{
|
||||
const GUID *major_type;
|
||||
@@ -61,6 +64,13 @@ static struct decoder_desc
|
||||
ARRAY_SIZE(wmv_input_types),
|
||||
wmv_output_types,
|
||||
ARRAY_SIZE(wmv_output_types),
|
||||
+ },
|
||||
+ { /* DECODER_TYPE_M4S2 */
|
||||
+ &MFMediaType_Video,
|
||||
+ m4s2_input_types,
|
||||
+ ARRAY_SIZE(m4s2_input_types),
|
||||
+ m4s2_output_types,
|
||||
+ ARRAY_SIZE(m4s2_output_types),
|
||||
}
|
||||
};
|
||||
|
||||
diff --git a/dlls/winegstreamer/mfplat.c b/dlls/winegstreamer/mfplat.c
|
||||
index 2fb730ff4c0..e5227340fd2 100644
|
||||
--- a/dlls/winegstreamer/mfplat.c
|
||||
+++ b/dlls/winegstreamer/mfplat.c
|
||||
@@ -424,6 +424,12 @@ static HRESULT wmv_decoder_create(REFIID riid, void **ret)
|
||||
{
|
||||
return generic_decoder_construct(riid, ret, DECODER_TYPE_WMV);
|
||||
}
|
||||
+
|
||||
+static HRESULT m4s2_decoder_create(REFIID riid, void **ret)
|
||||
+{
|
||||
+ return generic_decoder_construct(riid, ret, DECODER_TYPE_M4S2);
|
||||
+}
|
||||
+
|
||||
static const struct class_object
|
||||
{
|
||||
const GUID *clsid;
|
||||
@@ -438,6 +444,7 @@ class_objects[] =
|
||||
{ &CLSID_CMSH264DecoderMFT, &h264_decoder_create },
|
||||
{ &CLSID_CMSAACDecMFT, &aac_decoder_create },
|
||||
{ &CLSID_CWMVDecMediaObject, &wmv_decoder_create },
|
||||
+ { &CLSID_CMpeg4sDecMFT, m4s2_decoder_create },
|
||||
};
|
||||
|
||||
HRESULT mfplat_get_class_object(REFCLSID rclsid, REFIID riid, void **obj)
|
||||
@@ -542,6 +549,22 @@ const GUID *wmv_decoder_output_types[] =
|
||||
&MFVideoFormat_RGB8,
|
||||
};
|
||||
|
||||
+static WCHAR m4s2decoderW[] = {'M','p','e','g','4','s',' ','D','e','c','o','d','e','r',' ','M','F','T',0};
|
||||
+
|
||||
+const GUID *m4s2_decoder_input_types[] =
|
||||
+{
|
||||
+ &MFVideoFormat_M4S2,
|
||||
+};
|
||||
+
|
||||
+const GUID *m4s2_decoder_output_types[] =
|
||||
+{
|
||||
+ &MFVideoFormat_I420,
|
||||
+ &MFVideoFormat_IYUV,
|
||||
+ &MFVideoFormat_NV12,
|
||||
+ &MFVideoFormat_YUY2,
|
||||
+ &MFVideoFormat_YV12,
|
||||
+};
|
||||
+
|
||||
static const struct mft
|
||||
{
|
||||
const GUID *clsid;
|
||||
@@ -617,6 +640,18 @@ mfts[] =
|
||||
wmv_decoder_output_types,
|
||||
NULL
|
||||
},
|
||||
+ {
|
||||
+ &CLSID_CMpeg4sDecMFT,
|
||||
+ &MFT_CATEGORY_VIDEO_DECODER,
|
||||
+ m4s2decoderW,
|
||||
+ MFT_ENUM_FLAG_SYNCMFT,
|
||||
+ &MFMediaType_Video,
|
||||
+ ARRAY_SIZE(m4s2_decoder_input_types),
|
||||
+ m4s2_decoder_input_types,
|
||||
+ ARRAY_SIZE(m4s2_decoder_output_types),
|
||||
+ m4s2_decoder_output_types,
|
||||
+ NULL
|
||||
+ },
|
||||
};
|
||||
|
||||
HRESULT mfplat_DllRegisterServer(void)
|
||||
diff --git a/dlls/winegstreamer/winegstreamer_classes.idl b/dlls/winegstreamer/winegstreamer_classes.idl
|
||||
index 3b29bbfc36d..2382a884069 100644
|
||||
--- a/dlls/winegstreamer/winegstreamer_classes.idl
|
||||
+++ b/dlls/winegstreamer/winegstreamer_classes.idl
|
||||
@@ -86,6 +86,12 @@ coclass CMSH264DecoderMFT { }
|
||||
]
|
||||
coclass CMSAACDecMFT { }
|
||||
|
||||
+[
|
||||
+ threading(both),
|
||||
+ uuid(5686a0d9-fe39-409f-9dff-3fdbc849f9f5)
|
||||
+]
|
||||
+coclass CMpeg4sDecMFT { }
|
||||
+
|
||||
[
|
||||
threading(both),
|
||||
uuid(82d353df-90bd-4382-8bc2-3f6192b76e34)
|
||||
diff --git a/include/mfidl.idl b/include/mfidl.idl
|
||||
index 7cb027b156a..926f593b3bc 100644
|
||||
--- a/include/mfidl.idl
|
||||
+++ b/include/mfidl.idl
|
||||
@@ -1308,5 +1308,6 @@ cpp_quote("EXTERN_GUID(MF_ACTIVATE_CUSTOM_VIDEO_PRESENTER_FLAGS, 0xba491366, 0xb
|
||||
cpp_quote("EXTERN_GUID(CLSID_VideoProcessorMFT, 0x88753b26, 0x5b24, 0x49bd, 0xb2, 0xe7, 0xc, 0x44, 0x5c, 0x78, 0xc9, 0x82);")
|
||||
cpp_quote("EXTERN_GUID(CLSID_CMSH264DecoderMFT, 0x62ce7e72, 0x4c71, 0x4d20, 0xb1, 0x5d, 0x45, 0x28, 0x31, 0xa8, 0x7d, 0x9d);")
|
||||
cpp_quote("EXTERN_GUID(CLSID_CMSAACDecMFT, 0x32d186a7, 0x218f, 0x4c75, 0x88, 0x76, 0xdd, 0x77, 0x27, 0x3a, 0x89, 0x99);")
|
||||
+cpp_quote("EXTERN_GUID(CLSID_CMpeg4sDecMFT, 0x5686a0d9, 0xfe39, 0x409f, 0x9d, 0xff, 0x3f, 0xdb, 0xc8, 0x49, 0xf9, 0xf5);")
|
||||
cpp_quote("EXTERN_GUID(CLSID_ASFByteStreamHandler, 0x41457294, 0x644c, 0x4298, 0xa2, 0x8a, 0xbd, 0x69, 0xf2, 0xc0, 0xcf, 0x3b);")
|
||||
cpp_quote("EXTERN_GUID(CLSID_CWMVDecMediaObject, 0x82d353df, 0x90bd, 0x4382, 0x8b, 0xc2, 0x3f, 0x61, 0x92, 0xb7, 0x6e, 0x34);")
|
||||
\ No newline at end of file
|
||||
--
|
||||
2.29.2
|
||||
|
@ -1,148 +0,0 @@
|
||||
From 1d5e925925e63fe244964b26cf6128ede0776a06 Mon Sep 17 00:00:00 2001
|
||||
From: Derek Lesho <dlesho@codeweavers.com>
|
||||
Date: Tue, 12 May 2020 16:50:41 -0500
|
||||
Subject: [PATCH] winegstreamer: Introduce WMA audio decoder.
|
||||
|
||||
Signed-off-by: Derek Lesho <dlesho@codeweavers.com>
|
||||
---
|
||||
dlls/winegstreamer/gst_private.h | 1 +
|
||||
dlls/winegstreamer/mf_decode.c | 10 ++++++
|
||||
dlls/winegstreamer/mfplat.c | 32 ++++++++++++++++++++
|
||||
dlls/winegstreamer/winegstreamer_classes.idl | 6 ++++
|
||||
include/mfidl.idl | 3 +-
|
||||
5 files changed, 51 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/dlls/winegstreamer/gst_private.h b/dlls/winegstreamer/gst_private.h
|
||||
index 1c6530d2f38..81fc9b5ce14 100644
|
||||
--- a/dlls/winegstreamer/gst_private.h
|
||||
+++ b/dlls/winegstreamer/gst_private.h
|
||||
@@ -91,6 +91,7 @@ enum decoder_type
|
||||
DECODER_TYPE_H264,
|
||||
DECODER_TYPE_AAC,
|
||||
DECODER_TYPE_WMV,
|
||||
+ DECODER_TYPE_WMA,
|
||||
DECODER_TYPE_M4S2,
|
||||
};
|
||||
HRESULT generic_decoder_construct(REFIID riid, void **obj, enum decoder_type) DECLSPEC_HIDDEN;
|
||||
diff --git a/dlls/winegstreamer/mf_decode.c b/dlls/winegstreamer/mf_decode.c
|
||||
index b5220bc3332..9b10cfd9e4a 100644
|
||||
--- a/dlls/winegstreamer/mf_decode.c
|
||||
+++ b/dlls/winegstreamer/mf_decode.c
|
||||
@@ -32,6 +32,9 @@ const GUID *aac_output_types[] = {&MFAudioFormat_Float, &MFAudioFormat_PCM};
|
||||
const GUID *wmv_input_types[] = {&MFVideoFormat_WMV3, &MFVideoFormat_WVC1};
|
||||
const GUID *wmv_output_types[] = {&MFVideoFormat_NV12, &MFVideoFormat_YV12, &MFVideoFormat_YUY2, &MFVideoFormat_UYVY, &MFVideoFormat_YVYU, &MFVideoFormat_NV11, &MFVideoFormat_RGB32, &MFVideoFormat_RGB24, &MFVideoFormat_RGB555, &MFVideoFormat_RGB8};
|
||||
|
||||
+const GUID *wma_input_types[] = {&MFAudioFormat_WMAudioV8, &MFAudioFormat_WMAudioV9};
|
||||
+const GUID *wma_output_types[] = {&MFAudioFormat_Float, &MFAudioFormat_PCM};
|
||||
+
|
||||
const GUID *m4s2_input_types[] = {&MFVideoFormat_MPEG2};
|
||||
const GUID *m4s2_output_types[] = {&MFVideoFormat_I420, &MFVideoFormat_IYUV, &MFVideoFormat_NV12, &MFVideoFormat_YUY2, &MFVideoFormat_YV12};
|
||||
|
||||
@@ -65,6 +68,13 @@ static struct decoder_desc
|
||||
wmv_output_types,
|
||||
ARRAY_SIZE(wmv_output_types),
|
||||
},
|
||||
+ { /* DECODER_TYPE_WMA */
|
||||
+ &MFMediaType_Audio,
|
||||
+ wma_input_types,
|
||||
+ ARRAY_SIZE(wma_input_types),
|
||||
+ wma_output_types,
|
||||
+ ARRAY_SIZE(wma_output_types),
|
||||
+ },
|
||||
{ /* DECODER_TYPE_M4S2 */
|
||||
&MFMediaType_Video,
|
||||
m4s2_input_types,
|
||||
diff --git a/dlls/winegstreamer/mfplat.c b/dlls/winegstreamer/mfplat.c
|
||||
index e5227340fd2..8f770f94bf8 100644
|
||||
--- a/dlls/winegstreamer/mfplat.c
|
||||
+++ b/dlls/winegstreamer/mfplat.c
|
||||
@@ -425,6 +425,11 @@ static HRESULT wmv_decoder_create(REFIID riid, void **ret)
|
||||
return generic_decoder_construct(riid, ret, DECODER_TYPE_WMV);
|
||||
}
|
||||
|
||||
+static HRESULT wma_decoder_create(REFIID riid, void **ret)
|
||||
+{
|
||||
+ return generic_decoder_construct(riid, ret, DECODER_TYPE_WMA);
|
||||
+}
|
||||
+
|
||||
static HRESULT m4s2_decoder_create(REFIID riid, void **ret)
|
||||
{
|
||||
return generic_decoder_construct(riid, ret, DECODER_TYPE_M4S2);
|
||||
@@ -444,6 +449,7 @@ class_objects[] =
|
||||
{ &CLSID_CMSH264DecoderMFT, &h264_decoder_create },
|
||||
{ &CLSID_CMSAACDecMFT, &aac_decoder_create },
|
||||
{ &CLSID_CWMVDecMediaObject, &wmv_decoder_create },
|
||||
+ { &CLSID_CWMADecMediaObject, &wma_decoder_create },
|
||||
{ &CLSID_CMpeg4sDecMFT, m4s2_decoder_create },
|
||||
};
|
||||
|
||||
@@ -549,6 +555,20 @@ const GUID *wmv_decoder_output_types[] =
|
||||
&MFVideoFormat_RGB8,
|
||||
};
|
||||
|
||||
+static WCHAR wmadecoderW[] = {'W','M','A','u','d','i','o',' ','D','e','c','o','d','e','r',' ','M','F','T',0};
|
||||
+
|
||||
+const GUID *wma_decoder_input_types[] =
|
||||
+{
|
||||
+ &MFAudioFormat_WMAudioV8,
|
||||
+ &MFAudioFormat_WMAudioV9,
|
||||
+};
|
||||
+
|
||||
+const GUID *wma_decoder_output_types[] =
|
||||
+{
|
||||
+ &MFAudioFormat_Float,
|
||||
+ &MFAudioFormat_PCM,
|
||||
+};
|
||||
+
|
||||
static WCHAR m4s2decoderW[] = {'M','p','e','g','4','s',' ','D','e','c','o','d','e','r',' ','M','F','T',0};
|
||||
|
||||
const GUID *m4s2_decoder_input_types[] =
|
||||
@@ -640,6 +660,18 @@ mfts[] =
|
||||
wmv_decoder_output_types,
|
||||
NULL
|
||||
},
|
||||
+ {
|
||||
+ &CLSID_CWMADecMediaObject,
|
||||
+ &MFT_CATEGORY_AUDIO_DECODER,
|
||||
+ wmadecoderW,
|
||||
+ MFT_ENUM_FLAG_SYNCMFT,
|
||||
+ &MFMediaType_Audio,
|
||||
+ ARRAY_SIZE(wma_decoder_input_types),
|
||||
+ wma_decoder_input_types,
|
||||
+ ARRAY_SIZE(wma_decoder_output_types),
|
||||
+ wma_decoder_output_types,
|
||||
+ NULL
|
||||
+ },
|
||||
{
|
||||
&CLSID_CMpeg4sDecMFT,
|
||||
&MFT_CATEGORY_VIDEO_DECODER,
|
||||
diff --git a/dlls/winegstreamer/winegstreamer_classes.idl b/dlls/winegstreamer/winegstreamer_classes.idl
|
||||
index 2382a884069..3aa85dfdab3 100644
|
||||
--- a/dlls/winegstreamer/winegstreamer_classes.idl
|
||||
+++ b/dlls/winegstreamer/winegstreamer_classes.idl
|
||||
@@ -97,3 +97,9 @@ coclass CMpeg4sDecMFT { }
|
||||
uuid(82d353df-90bd-4382-8bc2-3f6192b76e34)
|
||||
]
|
||||
coclass CLSID_CWMVDecMediaObject {}
|
||||
+
|
||||
+[
|
||||
+ threading(both),
|
||||
+ uuid(2eeb4adf-4578-4d10-bca7-bb955f56320a)
|
||||
+]
|
||||
+coclass CLSID_CWMADecMediaObject {}
|
||||
diff --git a/include/mfidl.idl b/include/mfidl.idl
|
||||
index 926f593b3bc..ca469846458 100644
|
||||
--- a/include/mfidl.idl
|
||||
+++ b/include/mfidl.idl
|
||||
@@ -1310,4 +1310,5 @@ cpp_quote("EXTERN_GUID(CLSID_CMSH264DecoderMFT, 0x62ce7e72, 0x4c71, 0x4d20, 0xb1
|
||||
cpp_quote("EXTERN_GUID(CLSID_CMSAACDecMFT, 0x32d186a7, 0x218f, 0x4c75, 0x88, 0x76, 0xdd, 0x77, 0x27, 0x3a, 0x89, 0x99);")
|
||||
cpp_quote("EXTERN_GUID(CLSID_CMpeg4sDecMFT, 0x5686a0d9, 0xfe39, 0x409f, 0x9d, 0xff, 0x3f, 0xdb, 0xc8, 0x49, 0xf9, 0xf5);")
|
||||
cpp_quote("EXTERN_GUID(CLSID_ASFByteStreamHandler, 0x41457294, 0x644c, 0x4298, 0xa2, 0x8a, 0xbd, 0x69, 0xf2, 0xc0, 0xcf, 0x3b);")
|
||||
-cpp_quote("EXTERN_GUID(CLSID_CWMVDecMediaObject, 0x82d353df, 0x90bd, 0x4382, 0x8b, 0xc2, 0x3f, 0x61, 0x92, 0xb7, 0x6e, 0x34);")
|
||||
\ No newline at end of file
|
||||
+cpp_quote("EXTERN_GUID(CLSID_CWMVDecMediaObject, 0x82d353df, 0x90bd, 0x4382, 0x8b, 0xc2, 0x3f, 0x61, 0x92, 0xb7, 0x6e, 0x34);")
|
||||
+cpp_quote("EXTERN_GUID(CLSID_CWMADecMediaObject, 0x2eeb4adf, 0x4578, 0x4d10, 0xbc, 0xa7, 0xbb, 0x95, 0x5f, 0x56, 0x32, 0x0a);")
|
||||
\ No newline at end of file
|
||||
--
|
||||
2.29.2
|
||||
|
@ -1,65 +0,0 @@
|
||||
From f85db2dd85e074dcb3373d711a937c00c3a5bc73 Mon Sep 17 00:00:00 2001
|
||||
From: Derek Lesho <dlesho@codeweavers.com>
|
||||
Date: Tue, 11 Aug 2020 13:41:15 -0500
|
||||
Subject: [PATCH] winegstreamer: Implement MF_SD_LANGUAGE.
|
||||
|
||||
Signed-off-by: Derek Lesho <dlesho@codeweavers.com>
|
||||
---
|
||||
dlls/winegstreamer/media_source.c | 32 ++++++++++++++++++++++++++++---
|
||||
1 file changed, 29 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/dlls/winegstreamer/media_source.c b/dlls/winegstreamer/media_source.c
|
||||
index fd7f1a7f55e..2c6b82c43b4 100644
|
||||
--- a/dlls/winegstreamer/media_source.c
|
||||
+++ b/dlls/winegstreamer/media_source.c
|
||||
@@ -1636,11 +1636,12 @@ static HRESULT media_source_constructor(IMFByteStream *bytestream, struct media_
|
||||
|
||||
for (i = 0; i < object->stream_count; i++)
|
||||
{
|
||||
+ struct media_stream *stream = object->streams[i];
|
||||
gint64 stream_pres_time;
|
||||
- if (gst_pad_query_duration(object->streams[i]->their_src, GST_FORMAT_TIME, &stream_pres_time))
|
||||
- {
|
||||
- TRACE("Stream %u has duration %llu\n", i, (unsigned long long int) stream_pres_time);
|
||||
+ GstEvent *tag_event;
|
||||
|
||||
+ if (gst_pad_query_duration(stream->their_src, GST_FORMAT_TIME, &stream_pres_time))
|
||||
+ {
|
||||
if (stream_pres_time > total_pres_time)
|
||||
total_pres_time = stream_pres_time;
|
||||
}
|
||||
@@ -1648,6 +1649,31 @@ static HRESULT media_source_constructor(IMFByteStream *bytestream, struct media_
|
||||
{
|
||||
WARN("Unable to get presentation time of stream %u\n", i);
|
||||
}
|
||||
+
|
||||
+ tag_event = gst_pad_get_sticky_event(stream->their_src, GST_EVENT_TAG, 0);
|
||||
+ if (tag_event)
|
||||
+ {
|
||||
+ GstTagList *tag_list;
|
||||
+ gchar *language_code = NULL;
|
||||
+
|
||||
+ gst_event_parse_tag(tag_event, &tag_list);
|
||||
+
|
||||
+ gst_tag_list_get_string(tag_list, "language-code", &language_code);
|
||||
+ if (language_code)
|
||||
+ {
|
||||
+ DWORD char_count = MultiByteToWideChar(CP_UTF8, 0, language_code, -1, NULL, 0);
|
||||
+ if (char_count)
|
||||
+ {
|
||||
+ WCHAR *language_codeW = heap_alloc(char_count * sizeof(WCHAR));
|
||||
+ MultiByteToWideChar(CP_UTF8, 0, language_code, -1, language_codeW, char_count);
|
||||
+ IMFStreamDescriptor_SetString(stream->descriptor, &MF_SD_LANGUAGE, language_codeW);
|
||||
+ heap_free(language_codeW);
|
||||
+ }
|
||||
+ g_free(language_code);
|
||||
+ }
|
||||
+
|
||||
+ gst_event_unref(tag_event);
|
||||
+ }
|
||||
}
|
||||
|
||||
if (object->stream_count)
|
||||
--
|
||||
2.29.2
|
||||
|
@ -1,135 +0,0 @@
|
||||
From 94a318fdf7083bcb8142a7b869ce9de1f9e1b0a3 Mon Sep 17 00:00:00 2001
|
||||
From: Thomas Crider <gloriouseggroll@gmail.com>
|
||||
Date: Fri, 18 Dec 2020 14:01:29 -0500
|
||||
Subject: [PATCH] winegstreamer: Force audio/mpeg to decode in source
|
||||
|
||||
Currently AAC audio does not transform correctly when done manually, however forcing mfplat
|
||||
to perform the decode in source via MF_DECODE_IN_SOURCE as it does with raw audio works properly.
|
||||
|
||||
Fixes various game audio freezes/hangs including Borderlands 3, Seven: Enhanced Edition
|
||||
---
|
||||
dlls/winegstreamer/mfplat.c | 101 +-----------------------------------
|
||||
1 file changed, 1 insertion(+), 100 deletions(-)
|
||||
|
||||
diff --git a/dlls/winegstreamer/mfplat.c b/dlls/winegstreamer/mfplat.c
|
||||
index e77c1d49e9a..ce0766beb12 100644
|
||||
--- a/dlls/winegstreamer/mfplat.c
|
||||
+++ b/dlls/winegstreamer/mfplat.c
|
||||
@@ -967,7 +967,7 @@ IMFMediaType *mf_media_type_from_caps(const GstCaps *caps)
|
||||
if (gst_structure_get_int(info, "bitrate", &bitrate))
|
||||
IMFMediaType_SetUINT32(media_type, &MF_MT_AVG_BITRATE, bitrate);
|
||||
|
||||
- if (!strcmp(mime_type, "audio/x-raw"))
|
||||
+ if (!strcmp(mime_type, "audio/x-raw") || !(strcmp(mime_type, "audio/mpeg")))
|
||||
{
|
||||
GstAudioInfo audio_info;
|
||||
DWORD depth;
|
||||
@@ -1008,105 +1008,6 @@ IMFMediaType *mf_media_type_from_caps(const GstCaps *caps)
|
||||
|
||||
IMFMediaType_SetUINT32(media_type, &MF_MT_AUDIO_BITS_PER_SAMPLE, depth);
|
||||
}
|
||||
- else if (!(strcmp(mime_type, "audio/mpeg")))
|
||||
- {
|
||||
- int mpeg_version = -1;
|
||||
-
|
||||
- IMFMediaType_SetUINT32(media_type, &MF_MT_COMPRESSED, TRUE);
|
||||
-
|
||||
- if (!(gst_structure_get_int(info, "mpegversion", &mpeg_version)))
|
||||
- ERR("Failed to get mpegversion\n");
|
||||
- switch (mpeg_version)
|
||||
- {
|
||||
- case 2:
|
||||
- case 4:
|
||||
- {
|
||||
- const char *format, *profile, *level;
|
||||
- DWORD profile_level_indication = 0;
|
||||
- const GValue *codec_data;
|
||||
- DWORD asc_size = 0;
|
||||
- struct aac_user_data *user_data = NULL;
|
||||
-
|
||||
- IMFMediaType_SetGUID(media_type, &MF_MT_SUBTYPE, &MFAudioFormat_AAC);
|
||||
- IMFMediaType_SetUINT32(media_type, &MF_MT_AUDIO_BITS_PER_SAMPLE, 16);
|
||||
-
|
||||
- codec_data = gst_structure_get_value(info, "codec_data");
|
||||
- if (codec_data)
|
||||
- {
|
||||
- GstBuffer *codec_data_buffer = gst_value_get_buffer(codec_data);
|
||||
- if (codec_data_buffer)
|
||||
- {
|
||||
- if ((asc_size = gst_buffer_get_size(codec_data_buffer)) >= 2)
|
||||
- {
|
||||
- user_data = heap_alloc_zero(sizeof(*user_data)+asc_size);
|
||||
- gst_buffer_extract(codec_data_buffer, 0, (gpointer)(user_data + 1), asc_size);
|
||||
- }
|
||||
- else
|
||||
- ERR("Unexpected buffer size\n");
|
||||
- }
|
||||
- else
|
||||
- ERR("codec_data not a buffer\n");
|
||||
- }
|
||||
- else
|
||||
- ERR("codec_data not found\n");
|
||||
- if (!user_data)
|
||||
- user_data = heap_alloc_zero(sizeof(*user_data));
|
||||
-
|
||||
- if ((format = gst_structure_get_string(info, "stream-format")))
|
||||
- {
|
||||
- DWORD payload_type = -1;
|
||||
- if (!(strcmp(format, "raw")))
|
||||
- payload_type = 0;
|
||||
- else if (!(strcmp(format, "adts")))
|
||||
- payload_type = 1;
|
||||
- else if (!(strcmp(format, "adif")))
|
||||
- payload_type = 2;
|
||||
- else if (!(strcmp(format, "loas")))
|
||||
- payload_type = 3;
|
||||
- else
|
||||
- FIXME("Unrecognized stream-format\n");
|
||||
- if (payload_type != -1)
|
||||
- {
|
||||
- IMFMediaType_SetUINT32(media_type, &MF_MT_AAC_PAYLOAD_TYPE, payload_type);
|
||||
- user_data->payload_type = payload_type;
|
||||
- }
|
||||
- }
|
||||
- else
|
||||
- {
|
||||
- ERR("Stream format not present\n");
|
||||
- }
|
||||
-
|
||||
- profile = gst_structure_get_string(info, "profile");
|
||||
- level = gst_structure_get_string(info, "level");
|
||||
- /* Data from http://archive.is/whp6P#45% */
|
||||
- if (profile && level)
|
||||
- {
|
||||
- if (!(strcmp(profile, "lc")) && !(strcmp(level, "2")))
|
||||
- profile_level_indication = 0x29;
|
||||
- else if (!(strcmp(profile, "lc")) && !(strcmp(level, "4")))
|
||||
- profile_level_indication = 0x2A;
|
||||
- else if (!(strcmp(profile, "lc")) && !(strcmp(level, "5")))
|
||||
- profile_level_indication = 0x2B;
|
||||
- else
|
||||
- FIXME("Unhandled profile/level combo\n");
|
||||
- }
|
||||
- else
|
||||
- ERR("Profile or level not present\n");
|
||||
-
|
||||
- if (profile_level_indication)
|
||||
- {
|
||||
- IMFMediaType_SetUINT32(media_type, &MF_MT_AAC_AUDIO_PROFILE_LEVEL_INDICATION, profile_level_indication);
|
||||
- user_data->profile_level_indication = profile_level_indication;
|
||||
- }
|
||||
-
|
||||
- IMFMediaType_SetBlob(media_type, &MF_MT_USER_DATA, (BYTE *)user_data, sizeof(*user_data) + asc_size);
|
||||
- heap_free(user_data);
|
||||
- break;
|
||||
- }
|
||||
- default:
|
||||
- FIXME("Unhandled mpegversion %d\n", mpeg_version);
|
||||
- }
|
||||
- }
|
||||
else if (!(strcmp(mime_type, "audio/x-wma")))
|
||||
{
|
||||
gint wma_version, block_align;
|
||||
--
|
||||
2.29.2
|
||||
|
@ -1,35 +0,0 @@
|
||||
From e8cf102151b0fdcd5ccf54ad207e1256e3725b3c Mon Sep 17 00:00:00 2001
|
||||
From: Alistair Leslie-Hughes <leslie_alistair@hotmail.com>
|
||||
Date: Sun, 30 Aug 2020 12:37:59 +1000
|
||||
Subject: [PATCH] winegstreamer: Support eAVEncH264VProfile_ConstrainedBase
|
||||
media type
|
||||
|
||||
Game: American Fugitive
|
||||
---
|
||||
dlls/winegstreamer/mfplat.c | 3 +++
|
||||
1 file changed, 3 insertions(+)
|
||||
|
||||
diff --git a/dlls/winegstreamer/mfplat.c b/dlls/winegstreamer/mfplat.c
|
||||
index 21d44c498b8..7e482b77863 100644
|
||||
--- a/dlls/winegstreamer/mfplat.c
|
||||
+++ b/dlls/winegstreamer/mfplat.c
|
||||
@@ -835,6 +835,8 @@ static IMFMediaType* transform_to_media_type(GstCaps *caps)
|
||||
IMFMediaType_SetUINT32(media_type, &MF_MT_MPEG2_PROFILE, eAVEncH264VProfile_High);
|
||||
else if (!(strcmp(profile, "high-4:4:4")))
|
||||
IMFMediaType_SetUINT32(media_type, &MF_MT_MPEG2_PROFILE, eAVEncH264VProfile_444);
|
||||
+ else if (!(strcmp(profile, "constrained-baseline")))
|
||||
+ IMFMediaType_SetUINT32(media_type, &MF_MT_MPEG2_PROFILE, eAVEncH264VProfile_ConstrainedBase);
|
||||
else
|
||||
FIXME("Unrecognized profile %s\n", profile);
|
||||
}
|
||||
@@ -1274,6 +1276,7 @@ GstCaps *caps_from_mf_media_type(IMFMediaType *type)
|
||||
case eAVEncH264VProfile_Main: profile = "main"; break;
|
||||
case eAVEncH264VProfile_High: profile = "high"; break;
|
||||
case eAVEncH264VProfile_444: profile = "high-4:4:4"; break;
|
||||
+ case eAVEncH264VProfile_ConstrainedBase: profile = "constrained-baseline"; break;
|
||||
default: FIXME("Unknown profile %u\n", h264_profile);
|
||||
}
|
||||
if (profile)
|
||||
--
|
||||
2.28.0
|
||||
|
@ -1,3 +1 @@
|
||||
Fixes: [49692] Multiple applications need a Media Foundation media source implementation
|
||||
# Will need to be rewritten after winegstreamer is converted.
|
||||
Disabled: true
|
||||
|
@ -138,6 +138,7 @@ patch_enable_all ()
|
||||
enable_krnl386_exe16_Invalid_Console_Handles="$1"
|
||||
enable_libs_Unicode_Collation="$1"
|
||||
enable_loader_KeyboardLayouts="$1"
|
||||
enable_mfplat_streaming_support="$1"
|
||||
enable_mmsystem_dll16_MIDIHDR_Refcount="$1"
|
||||
enable_mountmgr_DosDevices="$1"
|
||||
enable_mscoree_CorValidateImage="$1"
|
||||
@ -459,6 +460,9 @@ patch_enable ()
|
||||
loader-KeyboardLayouts)
|
||||
enable_loader_KeyboardLayouts="$2"
|
||||
;;
|
||||
mfplat-streaming-support)
|
||||
enable_mfplat_streaming_support="$2"
|
||||
;;
|
||||
mmsystem.dll16-MIDIHDR_Refcount)
|
||||
enable_mmsystem_dll16_MIDIHDR_Refcount="$2"
|
||||
;;
|
||||
@ -2446,6 +2450,60 @@ if test "$enable_loader_KeyboardLayouts" -eq 1; then
|
||||
patch_apply loader-KeyboardLayouts/0002-user32-Improve-GetKeyboardLayoutList.patch
|
||||
fi
|
||||
|
||||
# Patchset mfplat-streaming-support
|
||||
# |
|
||||
# | This patchset fixes the following Wine bugs:
|
||||
# | * [#49692] Multiple applications need a Media Foundation media source implementation
|
||||
# |
|
||||
# | Modified files:
|
||||
# | * dlls/mf/topology.c, dlls/mfplat/buffer.c, dlls/mfplat/main.c, dlls/mfreadwrite/tests/mfplat.c,
|
||||
# | dlls/winegstreamer/Makefile.in, dlls/winegstreamer/audioconvert.c, dlls/winegstreamer/colorconvert.c,
|
||||
# | dlls/winegstreamer/decode_transform.c, dlls/winegstreamer/gst_private.h, dlls/winegstreamer/main.c,
|
||||
# | dlls/winegstreamer/media_source.c, dlls/winegstreamer/mfplat.c, dlls/winegstreamer/quartz_parser.c,
|
||||
# | dlls/winegstreamer/wg_parser.c, dlls/winegstreamer/winegstreamer_classes.idl, include/mfidl.idl, include/wmcodecdsp.idl
|
||||
# |
|
||||
if test "$enable_mfplat_streaming_support" -eq 1; then
|
||||
patch_apply mfplat-streaming-support/0001-winegstreamer-Activate-source-pad-in-push-mode-if-it.patch
|
||||
patch_apply mfplat-streaming-support/0002-winegstreamer-Push-stream-start-and-segment-events-i.patch
|
||||
patch_apply mfplat-streaming-support/0003-winegstreamer-Introduce-H.264-decoder-transform.patch
|
||||
patch_apply mfplat-streaming-support/0004-winegstreamer-Implement-GetInputAvailableType-for-de.patch
|
||||
patch_apply mfplat-streaming-support/0005-winegstreamer-Implement-GetOutputAvailableType-for-d.patch
|
||||
patch_apply mfplat-streaming-support/0006-winegstreamer-Implement-SetInputType-for-decode-tran.patch
|
||||
patch_apply mfplat-streaming-support/0007-winegstreamer-Implement-SetOutputType-for-decode-tra.patch
|
||||
patch_apply mfplat-streaming-support/0008-winegstreamer-Implement-Get-Input-Output-StreamInfo-.patch
|
||||
patch_apply mfplat-streaming-support/0009-winegstreamer-Add-push-mode-path-for-wg_parser.patch
|
||||
patch_apply mfplat-streaming-support/0010-winegstreamer-Implement-Process-Input-Output-for-dec.patch
|
||||
patch_apply mfplat-streaming-support/0011-winestreamer-Implement-ProcessMessage-for-decoder-tr.patch
|
||||
patch_apply mfplat-streaming-support/0012-winegstreamer-Semi-stub-GetAttributes-for-decoder-tr.patch
|
||||
patch_apply mfplat-streaming-support/0013-winegstreamer-Register-the-H.264-decoder-transform.patch
|
||||
patch_apply mfplat-streaming-support/0014-winegstreamer-Introduce-AAC-decoder-transform.patch
|
||||
patch_apply mfplat-streaming-support/0015-winegstreamer-Register-the-AAC-decoder-transform.patch
|
||||
patch_apply mfplat-streaming-support/0016-winegstreamer-Rename-GStreamer-objects-to-be-more-ge.patch
|
||||
patch_apply mfplat-streaming-support/0017-winegstreamer-Report-streams-backwards-in-media-sour.patch
|
||||
patch_apply mfplat-streaming-support/0018-winegstreamer-Implement-Process-Input-Output-for-aud.patch
|
||||
patch_apply mfplat-streaming-support/0019-winegstreamer-Implement-Get-Input-Output-StreamInfo-.patch
|
||||
patch_apply mfplat-streaming-support/0020-winegstreamer-Semi-stub-Get-Attributes-functions-for.patch
|
||||
patch_apply mfplat-streaming-support/0021-winegstreamer-Introduce-color-conversion-transform.patch
|
||||
patch_apply mfplat-streaming-support/0022-winegstreamer-Register-the-color-conversion-transfor.patch
|
||||
patch_apply mfplat-streaming-support/0023-winegstreamer-Implement-GetInputAvailableType-for-co.patch
|
||||
patch_apply mfplat-streaming-support/0024-winegstreamer-Implement-SetInputType-for-color-conve.patch
|
||||
patch_apply mfplat-streaming-support/0025-winegstreamer-Implement-GetOutputAvailableType-for-c.patch
|
||||
patch_apply mfplat-streaming-support/0026-winegstreamer-Implement-SetOutputType-for-color-conv.patch
|
||||
patch_apply mfplat-streaming-support/0027-winegstreamer-Implement-Process-Input-Output-for-col.patch
|
||||
patch_apply mfplat-streaming-support/0028-winegstreamer-Implement-ProcessMessage-for-color-con.patch
|
||||
patch_apply mfplat-streaming-support/0029-winegstreamer-Implement-Get-Input-Output-StreamInfo-.patch
|
||||
patch_apply mfplat-streaming-support/0030-mf-topology-Forward-failure-from-SetOutputType-when-.patch
|
||||
patch_apply mfplat-streaming-support/0031-winegstreamer-Handle-flush-command-in-audio-converst.patch
|
||||
patch_apply mfplat-streaming-support/0032-winegstreamer-In-the-default-configuration-select-on.patch
|
||||
patch_apply mfplat-streaming-support/0033-winegstreamer-Implement-MF_SD_LANGUAGE.patch
|
||||
patch_apply mfplat-streaming-support/0034-winegstreamer-Only-require-videobox-element-for-pars.patch
|
||||
patch_apply mfplat-streaming-support/0035-mfplat-Stub-out-MFCreateDXGIDeviceManager-to-avoid-t.patch
|
||||
patch_apply mfplat-streaming-support/0036-winegstreamer-Don-t-rely-on-max_size-in-unseekable-p.patch
|
||||
patch_apply mfplat-streaming-support/0037-winegstreamer-Implement-MFT_MESSAGE_COMMAND_FLUSH-fo.patch
|
||||
patch_apply mfplat-streaming-support/0038-mfreadwrite-Unset-seeking-flag-also-on-SourceStarted.patch
|
||||
patch_apply mfplat-streaming-support/0039-winegstreamer-Default-Frame-size-if-one-isn-t-availa.patch
|
||||
fi
|
||||
|
||||
# Patchset mmsystem.dll16-MIDIHDR_Refcount
|
||||
# |
|
||||
# | This patchset fixes the following Wine bugs:
|
||||
|
Loading…
Reference in New Issue
Block a user