mfplat-streaming-support: Remove transform patches already implemented or superseded upstream.

This commit is contained in:
Zebediah Figura 2022-09-03 15:54:56 -05:00
parent 34b3ffed35
commit 73351fd593
58 changed files with 0 additions and 10664 deletions

View File

@ -1,223 +0,0 @@
From fb5e9adb5eb72fa5d8369ec2e014985450432329 Mon Sep 17 00:00:00 2001
From: Thomas Crider <gloriouseggroll@gmail.com>
Date: Sat, 19 Feb 2022 16:58:07 -0700
Subject: [PATCH 04/88] Revert "winegstreamer: Create static pads on
wg_transform struct."
This reverts commit 71bf5b24d7efabfcacfa707198efc4be0da3e446.
---
dlls/winegstreamer/gst_private.h | 3 +-
dlls/winegstreamer/main.c | 9 ++----
dlls/winegstreamer/unixlib.h | 2 --
dlls/winegstreamer/wg_format.c | 40 ++----------------------
dlls/winegstreamer/wg_transform.c | 51 +------------------------------
dlls/winegstreamer/wma_decoder.c | 2 +-
6 files changed, 7 insertions(+), 100 deletions(-)
diff --git a/dlls/winegstreamer/gst_private.h b/dlls/winegstreamer/gst_private.h
index a63daaf04b9..8bc9f838d29 100644
--- a/dlls/winegstreamer/gst_private.h
+++ b/dlls/winegstreamer/gst_private.h
@@ -96,8 +96,7 @@ uint64_t wg_parser_stream_get_duration(struct wg_parser_stream *stream);
void 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);
-struct wg_transform *wg_transform_create(const struct wg_format *input_format,
- const struct wg_format *output_format);
+struct wg_transform *wg_transform_create(void);
void wg_transform_destroy(struct wg_transform *transform);
unsigned int wg_format_get_max_size(const struct wg_format *format);
diff --git a/dlls/winegstreamer/main.c b/dlls/winegstreamer/main.c
index 95b22abebb7..af5a691371d 100644
--- a/dlls/winegstreamer/main.c
+++ b/dlls/winegstreamer/main.c
@@ -254,14 +254,9 @@ void wg_parser_stream_seek(struct wg_parser_stream *stream, double rate,
__wine_unix_call(unix_handle, unix_wg_parser_stream_seek, &params);
}
-struct wg_transform *wg_transform_create(const struct wg_format *input_format,
- const struct wg_format *output_format)
+struct wg_transform *wg_transform_create(void)
{
- struct wg_transform_create_params params =
- {
- .input_format = input_format,
- .output_format = output_format,
- };
+ struct wg_transform_create_params params = {0};
if (__wine_unix_call(unix_handle, unix_wg_transform_create, &params))
return NULL;
diff --git a/dlls/winegstreamer/unixlib.h b/dlls/winegstreamer/unixlib.h
index 4adbb694766..8e3f5e84bfb 100644
--- a/dlls/winegstreamer/unixlib.h
+++ b/dlls/winegstreamer/unixlib.h
@@ -232,8 +232,6 @@ struct wg_parser_stream_seek_params
struct wg_transform_create_params
{
struct wg_transform *transform;
- const struct wg_format *input_format;
- const struct wg_format *output_format;
};
enum unix_funcs
diff --git a/dlls/winegstreamer/wg_format.c b/dlls/winegstreamer/wg_format.c
index 40b9acfefff..8f771bb8abd 100644
--- a/dlls/winegstreamer/wg_format.c
+++ b/dlls/winegstreamer/wg_format.c
@@ -394,43 +394,6 @@ static GstCaps *wg_format_to_caps_video(const struct wg_format *format)
return caps;
}
-static GstCaps *wg_format_to_caps_wma(const struct wg_format *format)
-{
- GstBuffer *buffer;
- GstCaps *caps;
-
- if (!(caps = gst_caps_new_empty_simple("audio/x-wma")))
- return NULL;
- if (format->u.wma.version)
- gst_caps_set_simple(caps, "wmaversion", G_TYPE_INT, format->u.wma.version, NULL);
-
- if (format->u.wma.bitrate)
- gst_caps_set_simple(caps, "bitrate", G_TYPE_INT, format->u.wma.bitrate, NULL);
- if (format->u.wma.rate)
- gst_caps_set_simple(caps, "rate", G_TYPE_INT, format->u.wma.rate, NULL);
- if (format->u.wma.depth)
- gst_caps_set_simple(caps, "depth", G_TYPE_INT, format->u.wma.depth, NULL);
- if (format->u.wma.channels)
- gst_caps_set_simple(caps, "channels", G_TYPE_INT, format->u.wma.channels, NULL);
- if (format->u.wma.block_align)
- gst_caps_set_simple(caps, "block_align", G_TYPE_INT, format->u.wma.block_align, NULL);
-
- if (format->u.wma.codec_data_len)
- {
- if (!(buffer = gst_buffer_new_and_alloc(format->u.wma.codec_data_len)))
- {
- gst_caps_unref(caps);
- return NULL;
- }
-
- gst_buffer_fill(buffer, 0, format->u.wma.codec_data, format->u.wma.codec_data_len);
- gst_caps_set_simple(caps, "codec_data", GST_TYPE_BUFFER, buffer, NULL);
- gst_buffer_unref(buffer);
- }
-
- return caps;
-}
-
GstCaps *wg_format_to_caps(const struct wg_format *format)
{
switch (format->major_type)
@@ -438,7 +401,8 @@ GstCaps *wg_format_to_caps(const struct wg_format *format)
case WG_MAJOR_TYPE_UNKNOWN:
return NULL;
case WG_MAJOR_TYPE_WMA:
- return wg_format_to_caps_wma(format);
+ GST_FIXME("WMA format not implemented!\n");
+ return NULL;
case WG_MAJOR_TYPE_AUDIO:
return wg_format_to_caps_audio(format);
case WG_MAJOR_TYPE_VIDEO:
diff --git a/dlls/winegstreamer/wg_transform.c b/dlls/winegstreamer/wg_transform.c
index e4545774428..2f225e5bc55 100644
--- a/dlls/winegstreamer/wg_transform.c
+++ b/dlls/winegstreamer/wg_transform.c
@@ -44,29 +44,13 @@ GST_DEBUG_CATEGORY_EXTERN(wine);
struct wg_transform
{
- GstPad *my_src, *my_sink;
+ int dummy;
};
-static GstFlowReturn transform_sink_chain_cb(GstPad *pad, GstObject *parent, GstBuffer *buffer)
-{
- struct wg_transform *transform = gst_pad_get_element_private(pad);
-
- GST_INFO("transform %p, buffer %p.", transform, buffer);
-
- gst_buffer_unref(buffer);
-
- return GST_FLOW_OK;
-}
-
NTSTATUS wg_transform_destroy(void *args)
{
struct wg_transform *transform = args;
- if (transform->my_sink)
- g_object_unref(transform->my_sink);
- if (transform->my_src)
- g_object_unref(transform->my_src);
-
free(transform);
return STATUS_SUCCESS;
}
@@ -74,10 +58,6 @@ NTSTATUS wg_transform_destroy(void *args)
NTSTATUS wg_transform_create(void *args)
{
struct wg_transform_create_params *params = args;
- struct wg_format output_format = *params->output_format;
- struct wg_format input_format = *params->input_format;
- GstCaps *src_caps = NULL, *sink_caps = NULL;
- GstPadTemplate *template = NULL;
struct wg_transform *transform;
NTSTATUS status;
@@ -89,38 +69,9 @@ NTSTATUS wg_transform_create(void *args)
if (!(transform = calloc(1, sizeof(*transform))))
goto done;
- if (!(src_caps = wg_format_to_caps(&input_format)))
- goto done;
- if (!(sink_caps = wg_format_to_caps(&output_format)))
- goto done;
-
- if (!(template = gst_pad_template_new("src", GST_PAD_SRC, GST_PAD_ALWAYS, src_caps)))
- goto done;
- if (!(transform->my_src = gst_pad_new_from_template(template, "src")))
- goto done;
- g_object_unref(template);
- template = NULL;
-
- if (!(template = gst_pad_template_new("sink", GST_PAD_SINK, GST_PAD_ALWAYS, sink_caps)))
- goto done;
- if (!(transform->my_sink = gst_pad_new_from_template(template, "sink")))
- goto done;
- g_object_unref(template);
- template = NULL;
-
- gst_pad_set_element_private(transform->my_sink, transform);
- gst_pad_set_chain_function(transform->my_sink, transform_sink_chain_cb);
-
status = STATUS_SUCCESS;
done:
- if (template)
- g_object_unref(template);
- if (sink_caps)
- gst_caps_unref(sink_caps);
- if (src_caps)
- gst_caps_unref(src_caps);
-
if (status)
{
GST_ERROR("Failed to create winegstreamer transform.");
diff --git a/dlls/winegstreamer/wma_decoder.c b/dlls/winegstreamer/wma_decoder.c
index 6c198706944..b14261706a7 100644
--- a/dlls/winegstreamer/wma_decoder.c
+++ b/dlls/winegstreamer/wma_decoder.c
@@ -78,7 +78,7 @@ static HRESULT try_create_wg_transform(struct wma_decoder *decoder)
if (output_format.major_type == WG_MAJOR_TYPE_UNKNOWN)
return MF_E_INVALIDMEDIATYPE;
- if (!(decoder->wg_transform = wg_transform_create(&input_format, &output_format)))
+ if (!(decoder->wg_transform = wg_transform_create()))
return E_FAIL;
return S_OK;
--
2.34.1

View File

@ -1,293 +0,0 @@
From 51f5ec2a0fd00995b4ff155a89e46c7dff8e338b Mon Sep 17 00:00:00 2001
From: Thomas Crider <gloriouseggroll@gmail.com>
Date: Sat, 19 Feb 2022 16:58:23 -0700
Subject: [PATCH 05/88] Revert "winegstreamer: Introduce new wg_transform
struct."
This reverts commit 51a262d368afca3ec1edf50a850dbd5339194280.
---
dlls/winegstreamer/Makefile.in | 1 -
dlls/winegstreamer/gst_private.h | 3 --
dlls/winegstreamer/main.c | 14 -----
dlls/winegstreamer/unix_private.h | 5 --
dlls/winegstreamer/unixlib.h | 8 ---
dlls/winegstreamer/wg_parser.c | 13 +----
dlls/winegstreamer/wg_transform.c | 88 -------------------------------
dlls/winegstreamer/wma_decoder.c | 11 ----
8 files changed, 2 insertions(+), 141 deletions(-)
delete mode 100644 dlls/winegstreamer/wg_transform.c
diff --git a/dlls/winegstreamer/Makefile.in b/dlls/winegstreamer/Makefile.in
index 0bcdb3eec65..d9805e3d797 100644
--- a/dlls/winegstreamer/Makefile.in
+++ b/dlls/winegstreamer/Makefile.in
@@ -14,7 +14,6 @@ C_SRCS = \
quartz_parser.c \
wg_format.c \
wg_parser.c \
- wg_transform.c \
wm_asyncreader.c \
wm_reader.c \
wm_syncreader.c \
diff --git a/dlls/winegstreamer/gst_private.h b/dlls/winegstreamer/gst_private.h
index 8bc9f838d29..3584f465218 100644
--- a/dlls/winegstreamer/gst_private.h
+++ b/dlls/winegstreamer/gst_private.h
@@ -96,9 +96,6 @@ uint64_t wg_parser_stream_get_duration(struct wg_parser_stream *stream);
void 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);
-struct wg_transform *wg_transform_create(void);
-void wg_transform_destroy(struct wg_transform *transform);
-
unsigned int wg_format_get_max_size(const struct wg_format *format);
HRESULT avi_splitter_create(IUnknown *outer, IUnknown **out);
diff --git a/dlls/winegstreamer/main.c b/dlls/winegstreamer/main.c
index af5a691371d..51a71d3b4a5 100644
--- a/dlls/winegstreamer/main.c
+++ b/dlls/winegstreamer/main.c
@@ -254,20 +254,6 @@ void wg_parser_stream_seek(struct wg_parser_stream *stream, double rate,
__wine_unix_call(unix_handle, unix_wg_parser_stream_seek, &params);
}
-struct wg_transform *wg_transform_create(void)
-{
- struct wg_transform_create_params params = {0};
-
- if (__wine_unix_call(unix_handle, unix_wg_transform_create, &params))
- return NULL;
- return params.transform;
-}
-
-void wg_transform_destroy(struct wg_transform *transform)
-{
- __wine_unix_call(unix_handle, unix_wg_transform_destroy, transform);
-}
-
BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, void *reserved)
{
if (reason == DLL_PROCESS_ATTACH)
diff --git a/dlls/winegstreamer/unix_private.h b/dlls/winegstreamer/unix_private.h
index f9c4da2f6ea..b483638403d 100644
--- a/dlls/winegstreamer/unix_private.h
+++ b/dlls/winegstreamer/unix_private.h
@@ -25,13 +25,8 @@
#include <gst/gst.h>
-extern bool init_gstreamer(void) DECLSPEC_HIDDEN;
-
extern void wg_format_from_caps(struct wg_format *format, const GstCaps *caps) DECLSPEC_HIDDEN;
extern bool wg_format_compare(const struct wg_format *a, const struct wg_format *b) DECLSPEC_HIDDEN;
extern GstCaps *wg_format_to_caps(const struct wg_format *format) DECLSPEC_HIDDEN;
-extern NTSTATUS wg_transform_create(void *args) DECLSPEC_HIDDEN;
-extern NTSTATUS wg_transform_destroy(void *args) DECLSPEC_HIDDEN;
-
#endif /* __WINE_WINEGSTREAMER_UNIX_PRIVATE_H */
diff --git a/dlls/winegstreamer/unixlib.h b/dlls/winegstreamer/unixlib.h
index 8e3f5e84bfb..45ec606fc6a 100644
--- a/dlls/winegstreamer/unixlib.h
+++ b/dlls/winegstreamer/unixlib.h
@@ -229,11 +229,6 @@ struct wg_parser_stream_seek_params
DWORD start_flags, stop_flags;
};
-struct wg_transform_create_params
-{
- struct wg_transform *transform;
-};
-
enum unix_funcs
{
unix_wg_parser_create,
@@ -262,9 +257,6 @@ enum unix_funcs
unix_wg_parser_stream_get_duration,
unix_wg_parser_stream_seek,
-
- unix_wg_transform_create,
- unix_wg_transform_destroy,
};
#endif /* __WINE_WINEGSTREAMER_UNIXLIB_H */
diff --git a/dlls/winegstreamer/wg_parser.c b/dlls/winegstreamer/wg_parser.c
index 40c394c3caf..66f60d27477 100644
--- a/dlls/winegstreamer/wg_parser.c
+++ b/dlls/winegstreamer/wg_parser.c
@@ -1586,13 +1586,6 @@ static void init_gstreamer_once(void)
gst_version_string(), GST_VERSION_MAJOR, GST_VERSION_MINOR, GST_VERSION_MICRO);
}
-bool init_gstreamer(void)
-{
- static pthread_once_t init_once = PTHREAD_ONCE_INIT;
-
- return !pthread_once(&init_once, init_gstreamer_once);
-}
-
static NTSTATUS wg_parser_create(void *args)
{
static const init_gst_cb init_funcs[] =
@@ -1603,10 +1596,11 @@ static NTSTATUS wg_parser_create(void *args)
[WG_PARSER_WAVPARSE] = wave_parser_init_gst,
};
+ static pthread_once_t once = PTHREAD_ONCE_INIT;
struct wg_parser_create_params *params = args;
struct wg_parser *parser;
- if (!init_gstreamer())
+ if (pthread_once(&once, init_gstreamer_once))
return E_FAIL;
if (!(parser = calloc(1, sizeof(*parser))))
@@ -1673,7 +1667,4 @@ const unixlib_entry_t __wine_unix_call_funcs[] =
X(wg_parser_stream_get_duration),
X(wg_parser_stream_seek),
-
- X(wg_transform_create),
- X(wg_transform_destroy),
};
diff --git a/dlls/winegstreamer/wg_transform.c b/dlls/winegstreamer/wg_transform.c
deleted file mode 100644
index 2f225e5bc55..00000000000
--- a/dlls/winegstreamer/wg_transform.c
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * GStreamer transform backend
- *
- * Copyright 2022 Rémi Bernon for CodeWeavers
- *
- * 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
- */
-
-#if 0
-#pragma makedep unix
-#endif
-
-#include "config.h"
-
-#include <assert.h>
-#include <stdarg.h>
-#include <stdio.h>
-
-#include <gst/gst.h>
-#include <gst/video/video.h>
-#include <gst/audio/audio.h>
-
-#include "ntstatus.h"
-#define WIN32_NO_STATUS
-#include "winternl.h"
-#include "dshow.h"
-
-#include "unix_private.h"
-
-GST_DEBUG_CATEGORY_EXTERN(wine);
-#define GST_CAT_DEFAULT wine
-
-struct wg_transform
-{
- int dummy;
-};
-
-NTSTATUS wg_transform_destroy(void *args)
-{
- struct wg_transform *transform = args;
-
- free(transform);
- return STATUS_SUCCESS;
-}
-
-NTSTATUS wg_transform_create(void *args)
-{
- struct wg_transform_create_params *params = args;
- struct wg_transform *transform;
- NTSTATUS status;
-
- if (!init_gstreamer())
- return STATUS_UNSUCCESSFUL;
-
- status = STATUS_NO_MEMORY;
-
- if (!(transform = calloc(1, sizeof(*transform))))
- goto done;
-
- status = STATUS_SUCCESS;
-
-done:
- if (status)
- {
- GST_ERROR("Failed to create winegstreamer transform.");
- if (transform)
- wg_transform_destroy(transform);
- }
- else
- {
- GST_INFO("Created winegstreamer transform %p.", transform);
- params->transform = transform;
- }
-
- return status;
-}
diff --git a/dlls/winegstreamer/wma_decoder.c b/dlls/winegstreamer/wma_decoder.c
index b14261706a7..31f735a5b1d 100644
--- a/dlls/winegstreamer/wma_decoder.c
+++ b/dlls/winegstreamer/wma_decoder.c
@@ -53,8 +53,6 @@ struct wma_decoder
LONG refcount;
IMFMediaType *input_type;
IMFMediaType *output_type;
-
- struct wg_transform *wg_transform;
};
static inline struct wma_decoder *impl_from_IUnknown(IUnknown *iface)
@@ -66,10 +64,6 @@ static HRESULT try_create_wg_transform(struct wma_decoder *decoder)
{
struct wg_format input_format, output_format;
- if (decoder->wg_transform)
- wg_transform_destroy(decoder->wg_transform);
- decoder->wg_transform = NULL;
-
mf_media_type_to_wg_format(decoder->input_type, &input_format);
if (input_format.major_type == WG_MAJOR_TYPE_UNKNOWN)
return MF_E_INVALIDMEDIATYPE;
@@ -78,9 +72,6 @@ static HRESULT try_create_wg_transform(struct wma_decoder *decoder)
if (output_format.major_type == WG_MAJOR_TYPE_UNKNOWN)
return MF_E_INVALIDMEDIATYPE;
- if (!(decoder->wg_transform = wg_transform_create()))
- return E_FAIL;
-
return S_OK;
}
@@ -128,8 +119,6 @@ static ULONG WINAPI unknown_Release(IUnknown *iface)
if (!refcount)
{
- if (decoder->wg_transform)
- wg_transform_destroy(decoder->wg_transform);
if (decoder->input_type)
IMFMediaType_Release(decoder->input_type);
if (decoder->output_type)
--
2.34.1

View File

@ -1,344 +0,0 @@
From 01b1caa979ab811edb7b859bc8f84ee68053a991 Mon Sep 17 00:00:00 2001
From: Thomas Crider <gloriouseggroll@gmail.com>
Date: Sat, 19 Feb 2022 16:58:47 -0700
Subject: [PATCH 06/88] Revert "winegstreamer: Introduce new WG_MAJOR_TYPE_WMA
major type."
This reverts commit 76e2883c4ace29279dce8ea58787871046227b1a.
---
dlls/winegstreamer/mfplat.c | 109 ++++++-----------------------
dlls/winegstreamer/quartz_parser.c | 8 ---
dlls/winegstreamer/unixlib.h | 12 ----
dlls/winegstreamer/wg_format.c | 7 --
dlls/winegstreamer/wm_reader.c | 8 ---
dlls/winegstreamer/wma_decoder.c | 18 -----
6 files changed, 21 insertions(+), 141 deletions(-)
diff --git a/dlls/winegstreamer/mfplat.c b/dlls/winegstreamer/mfplat.c
index 9b3fc429d32..a111bbe196d 100644
--- a/dlls/winegstreamer/mfplat.c
+++ b/dlls/winegstreamer/mfplat.c
@@ -635,10 +635,6 @@ IMFMediaType *mf_media_type_from_wg_format(const struct wg_format *format)
case WG_MAJOR_TYPE_UNKNOWN:
return NULL;
- case WG_MAJOR_TYPE_WMA:
- FIXME("WMA format not implemented!\n");
- return NULL;
-
case WG_MAJOR_TYPE_AUDIO:
return mf_media_type_from_wg_format_audio(format);
@@ -650,11 +646,17 @@ IMFMediaType *mf_media_type_from_wg_format(const struct wg_format *format)
return NULL;
}
-static void mf_media_type_to_wg_format_audio(IMFMediaType *type, const GUID *subtype, struct wg_format *format)
+static void mf_media_type_to_wg_format_audio(IMFMediaType *type, struct wg_format *format)
{
UINT32 rate, channels, channel_mask, depth;
unsigned int i;
+ GUID subtype;
+ if (FAILED(IMFMediaType_GetGUID(type, &MF_MT_SUBTYPE, &subtype)))
+ {
+ FIXME("Subtype is not set.\n");
+ return;
+ }
if (FAILED(IMFMediaType_GetUINT32(type, &MF_MT_AUDIO_SAMPLES_PER_SECOND, &rate)))
{
FIXME("Sample rate is not set.\n");
@@ -690,20 +692,26 @@ static void mf_media_type_to_wg_format_audio(IMFMediaType *type, const GUID *sub
for (i = 0; i < ARRAY_SIZE(audio_formats); ++i)
{
- if (IsEqualGUID(subtype, audio_formats[i].subtype) && depth == audio_formats[i].depth)
+ if (IsEqualGUID(&subtype, audio_formats[i].subtype) && depth == audio_formats[i].depth)
{
format->u.audio.format = audio_formats[i].format;
return;
}
}
- FIXME("Unrecognized audio subtype %s, depth %u.\n", debugstr_guid(subtype), depth);
+ FIXME("Unrecognized audio subtype %s, depth %u.\n", debugstr_guid(&subtype), depth);
}
-static void mf_media_type_to_wg_format_video(IMFMediaType *type, const GUID *subtype, struct wg_format *format)
+static void mf_media_type_to_wg_format_video(IMFMediaType *type, struct wg_format *format)
{
UINT64 frame_rate, frame_size;
unsigned int i;
+ GUID subtype;
+ if (FAILED(IMFMediaType_GetGUID(type, &MF_MT_SUBTYPE, &subtype)))
+ {
+ 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");
@@ -724,80 +732,18 @@ static void mf_media_type_to_wg_format_video(IMFMediaType *type, const GUID *sub
for (i = 0; i < ARRAY_SIZE(video_formats); ++i)
{
- if (IsEqualGUID(subtype, video_formats[i].subtype))
+ if (IsEqualGUID(&subtype, video_formats[i].subtype))
{
format->u.video.format = video_formats[i].format;
return;
}
}
- FIXME("Unrecognized video subtype %s.\n", debugstr_guid(subtype));
-}
-
-static void mf_media_type_to_wg_format_wma(IMFMediaType *type, const GUID *subtype, struct wg_format *format)
-{
- UINT32 rate, depth, channels, block_align, bytes_per_second, codec_data_len;
- BYTE codec_data[64];
- UINT32 version;
-
- if (FAILED(IMFMediaType_GetUINT32(type, &MF_MT_AUDIO_SAMPLES_PER_SECOND, &rate)))
- {
- FIXME("Sample rate is not set.\n");
- return;
- }
- if (FAILED(IMFMediaType_GetUINT32(type, &MF_MT_AUDIO_NUM_CHANNELS, &channels)))
- {
- FIXME("Channel count is not set.\n");
- return;
- }
- if (FAILED(IMFMediaType_GetUINT32(type, &MF_MT_AUDIO_BLOCK_ALIGNMENT, &block_align)))
- {
- FIXME("Block alignment is not set.\n");
- return;
- }
- if (FAILED(IMFMediaType_GetUINT32(type, &MF_MT_AUDIO_BITS_PER_SAMPLE, &depth)))
- {
- FIXME("Depth is not set.\n");
- return;
- }
- if (FAILED(IMFMediaType_GetBlob(type, &MF_MT_USER_DATA, codec_data, sizeof(codec_data), &codec_data_len)))
- {
- FIXME("Codec data is not set.\n");
- return;
- }
- if (FAILED(IMFMediaType_GetUINT32(type, &MF_MT_AUDIO_AVG_BYTES_PER_SECOND, &bytes_per_second)))
- {
- FIXME("Bitrate is not set.\n");
- bytes_per_second = 0;
- }
-
- if (IsEqualGUID(subtype, &MEDIASUBTYPE_MSAUDIO1))
- version = 1;
- else if (IsEqualGUID(subtype, &MFAudioFormat_WMAudioV8))
- version = 2;
- else if (IsEqualGUID(subtype, &MFAudioFormat_WMAudioV9))
- version = 3;
- else if (IsEqualGUID(subtype, &MFAudioFormat_WMAudio_Lossless))
- version = 4;
- else
- {
- assert(0);
- return;
- }
-
- format->major_type = WG_MAJOR_TYPE_WMA;
- format->u.wma.version = version;
- format->u.wma.bitrate = bytes_per_second * 8;
- format->u.wma.rate = rate;
- format->u.wma.depth = depth;
- format->u.wma.channels = channels;
- format->u.wma.block_align = block_align;
- format->u.wma.codec_data_len = codec_data_len;
- memcpy(format->u.wma.codec_data, codec_data, codec_data_len);
+ FIXME("Unrecognized video subtype %s.\n", debugstr_guid(&subtype));
}
void mf_media_type_to_wg_format(IMFMediaType *type, struct wg_format *format)
{
- GUID major_type, subtype;
+ GUID major_type;
memset(format, 0, sizeof(*format));
@@ -806,24 +752,11 @@ void mf_media_type_to_wg_format(IMFMediaType *type, struct wg_format *format)
FIXME("Major type is not set.\n");
return;
}
- if (FAILED(IMFMediaType_GetGUID(type, &MF_MT_SUBTYPE, &subtype)))
- {
- FIXME("Subtype is not set.\n");
- return;
- }
if (IsEqualGUID(&major_type, &MFMediaType_Audio))
- {
- if (IsEqualGUID(&subtype, &MEDIASUBTYPE_MSAUDIO1) ||
- IsEqualGUID(&subtype, &MFAudioFormat_WMAudioV8) ||
- IsEqualGUID(&subtype, &MFAudioFormat_WMAudioV9) ||
- IsEqualGUID(&subtype, &MFAudioFormat_WMAudio_Lossless))
- mf_media_type_to_wg_format_wma(type, &subtype, format);
- else
- mf_media_type_to_wg_format_audio(type, &subtype, format);
- }
+ mf_media_type_to_wg_format_audio(type, format);
else if (IsEqualGUID(&major_type, &MFMediaType_Video))
- mf_media_type_to_wg_format_video(type, &subtype, format);
+ mf_media_type_to_wg_format_video(type, format);
else
FIXME("Unrecognized major type %s.\n", debugstr_guid(&major_type));
}
diff --git a/dlls/winegstreamer/quartz_parser.c b/dlls/winegstreamer/quartz_parser.c
index e06c55ccfe0..45313ebda27 100644
--- a/dlls/winegstreamer/quartz_parser.c
+++ b/dlls/winegstreamer/quartz_parser.c
@@ -319,10 +319,6 @@ unsigned int wg_format_get_max_size(const struct wg_format *format)
break;
}
- case WG_MAJOR_TYPE_WMA:
- FIXME("WMA format not implemented!\n");
- return 0;
-
case WG_MAJOR_TYPE_UNKNOWN:
FIXME("Cannot guess maximum sample size for unknown format.\n");
return 0;
@@ -417,10 +413,6 @@ bool amt_from_wg_format(AM_MEDIA_TYPE *mt, const struct wg_format *format, bool
case WG_MAJOR_TYPE_UNKNOWN:
return false;
- case WG_MAJOR_TYPE_WMA:
- FIXME("WMA format not implemented!\n");
- return false;
-
case WG_MAJOR_TYPE_AUDIO:
return amt_from_wg_format_audio(mt, format);
diff --git a/dlls/winegstreamer/unixlib.h b/dlls/winegstreamer/unixlib.h
index 45ec606fc6a..82bb534b938 100644
--- a/dlls/winegstreamer/unixlib.h
+++ b/dlls/winegstreamer/unixlib.h
@@ -37,7 +37,6 @@ struct wg_format
WG_MAJOR_TYPE_UNKNOWN,
WG_MAJOR_TYPE_VIDEO,
WG_MAJOR_TYPE_AUDIO,
- WG_MAJOR_TYPE_WMA,
} major_type;
union
@@ -89,17 +88,6 @@ struct wg_format
uint32_t channel_mask; /* In WinMM format. */
uint32_t rate;
} audio;
- struct
- {
- uint32_t version;
- uint32_t bitrate;
- uint32_t rate;
- uint32_t depth;
- uint32_t channels;
- uint32_t block_align;
- uint32_t codec_data_len;
- unsigned char codec_data[64];
- } wma;
} u;
};
diff --git a/dlls/winegstreamer/wg_format.c b/dlls/winegstreamer/wg_format.c
index 8f771bb8abd..8952acc1c2e 100644
--- a/dlls/winegstreamer/wg_format.c
+++ b/dlls/winegstreamer/wg_format.c
@@ -400,9 +400,6 @@ GstCaps *wg_format_to_caps(const struct wg_format *format)
{
case WG_MAJOR_TYPE_UNKNOWN:
return NULL;
- case WG_MAJOR_TYPE_WMA:
- GST_FIXME("WMA format not implemented!\n");
- return NULL;
case WG_MAJOR_TYPE_AUDIO:
return wg_format_to_caps_audio(format);
case WG_MAJOR_TYPE_VIDEO:
@@ -422,10 +419,6 @@ bool wg_format_compare(const struct wg_format *a, const struct wg_format *b)
case WG_MAJOR_TYPE_UNKNOWN:
return false;
- case WG_MAJOR_TYPE_WMA:
- GST_FIXME("WMA format not implemented!\n");
- return false;
-
case WG_MAJOR_TYPE_AUDIO:
return a->u.audio.format == b->u.audio.format
&& a->u.audio.channels == b->u.audio.channels
diff --git a/dlls/winegstreamer/wm_reader.c b/dlls/winegstreamer/wm_reader.c
index 01518c6b9a8..d40afb66afd 100644
--- a/dlls/winegstreamer/wm_reader.c
+++ b/dlls/winegstreamer/wm_reader.c
@@ -1687,9 +1687,6 @@ HRESULT wm_reader_get_output_format_count(struct wm_reader *reader, DWORD output
*count = ARRAY_SIZE(video_formats);
break;
- case WG_MAJOR_TYPE_WMA:
- FIXME("WMA format not implemented!\n");
- /* fallthrough */
case WG_MAJOR_TYPE_AUDIO:
case WG_MAJOR_TYPE_UNKNOWN:
*count = 1;
@@ -1736,9 +1733,6 @@ HRESULT wm_reader_get_output_format(struct wm_reader *reader, DWORD output,
format.u.audio.format = WG_AUDIO_FORMAT_S16LE;
break;
- case WG_MAJOR_TYPE_WMA:
- FIXME("WMA format not implemented!\n");
- break;
case WG_MAJOR_TYPE_UNKNOWN:
break;
}
@@ -1814,8 +1808,6 @@ static const char *get_major_type_string(enum wg_major_type type)
return "video";
case WG_MAJOR_TYPE_UNKNOWN:
return "unknown";
- case WG_MAJOR_TYPE_WMA:
- return "wma";
}
assert(0);
return NULL;
diff --git a/dlls/winegstreamer/wma_decoder.c b/dlls/winegstreamer/wma_decoder.c
index 31f735a5b1d..78316059052 100644
--- a/dlls/winegstreamer/wma_decoder.c
+++ b/dlls/winegstreamer/wma_decoder.c
@@ -60,21 +60,6 @@ static inline struct wma_decoder *impl_from_IUnknown(IUnknown *iface)
return CONTAINING_RECORD(iface, struct wma_decoder, IUnknown_inner);
}
-static HRESULT try_create_wg_transform(struct wma_decoder *decoder)
-{
- struct wg_format input_format, output_format;
-
- mf_media_type_to_wg_format(decoder->input_type, &input_format);
- if (input_format.major_type == WG_MAJOR_TYPE_UNKNOWN)
- return MF_E_INVALIDMEDIATYPE;
-
- mf_media_type_to_wg_format(decoder->output_type, &output_format);
- if (output_format.major_type == WG_MAJOR_TYPE_UNKNOWN)
- return MF_E_INVALIDMEDIATYPE;
-
- return S_OK;
-}
-
static HRESULT WINAPI unknown_QueryInterface(IUnknown *iface, REFIID iid, void **out)
{
struct wma_decoder *decoder = impl_from_IUnknown(iface);
@@ -453,9 +438,6 @@ static HRESULT WINAPI transform_SetOutputType(IMFTransform *iface, DWORD id, IMF
if (FAILED(hr = IMFMediaType_CopyAllItems(type, (IMFAttributes *)decoder->output_type)))
goto failed;
- if (FAILED(hr = try_create_wg_transform(decoder)))
- goto failed;
-
return S_OK;
failed:
--
2.34.1

View File

@ -1,933 +0,0 @@
From 9f3feb4b3f4d3225e0733254fb673b675b975525 Mon Sep 17 00:00:00 2001
From: Thomas Crider <gloriouseggroll@gmail.com>
Date: Sat, 19 Feb 2022 16:59:35 -0700
Subject: [PATCH 07/88] Revert "winegstreamer: Move format helpers to a
dedicated source."
This reverts commit a288b94831bcd9ef65c23475d8499e53fea69c18.
---
dlls/winegstreamer/Makefile.in | 1 -
dlls/winegstreamer/unix_private.h | 32 ---
dlls/winegstreamer/wg_format.c | 436 ------------------------------
dlls/winegstreamer/wg_parser.c | 397 ++++++++++++++++++++++++++-
4 files changed, 395 insertions(+), 471 deletions(-)
delete mode 100644 dlls/winegstreamer/unix_private.h
delete mode 100644 dlls/winegstreamer/wg_format.c
diff --git a/dlls/winegstreamer/Makefile.in b/dlls/winegstreamer/Makefile.in
index d9805e3d797..c53e914e246 100644
--- a/dlls/winegstreamer/Makefile.in
+++ b/dlls/winegstreamer/Makefile.in
@@ -12,7 +12,6 @@ C_SRCS = \
media_source.c \
mfplat.c \
quartz_parser.c \
- wg_format.c \
wg_parser.c \
wm_asyncreader.c \
wm_reader.c \
diff --git a/dlls/winegstreamer/unix_private.h b/dlls/winegstreamer/unix_private.h
deleted file mode 100644
index b483638403d..00000000000
--- a/dlls/winegstreamer/unix_private.h
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * winegstreamer Unix library interface
- *
- * Copyright 2020-2021 Zebediah Figura for CodeWeavers
- *
- * 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
- */
-
-#ifndef __WINE_WINEGSTREAMER_UNIX_PRIVATE_H
-#define __WINE_WINEGSTREAMER_UNIX_PRIVATE_H
-
-#include "unixlib.h"
-
-#include <gst/gst.h>
-
-extern void wg_format_from_caps(struct wg_format *format, const GstCaps *caps) DECLSPEC_HIDDEN;
-extern bool wg_format_compare(const struct wg_format *a, const struct wg_format *b) DECLSPEC_HIDDEN;
-extern GstCaps *wg_format_to_caps(const struct wg_format *format) DECLSPEC_HIDDEN;
-
-#endif /* __WINE_WINEGSTREAMER_UNIX_PRIVATE_H */
diff --git a/dlls/winegstreamer/wg_format.c b/dlls/winegstreamer/wg_format.c
deleted file mode 100644
index 8952acc1c2e..00000000000
--- a/dlls/winegstreamer/wg_format.c
+++ /dev/null
@@ -1,436 +0,0 @@
-/*
- * GStreamer format helpers
- *
- * Copyright 2010 Maarten Lankhorst for CodeWeavers
- * Copyright 2010 Aric Stewart for CodeWeavers
- * Copyright 2019-2020 Zebediah Figura
- *
- * 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
- */
-
-#if 0
-#pragma makedep unix
-#endif
-
-#include "config.h"
-
-#include <assert.h>
-#include <stdarg.h>
-#include <stdio.h>
-
-#include <gst/gst.h>
-#include <gst/video/video.h>
-#include <gst/audio/audio.h>
-
-#include "winternl.h"
-#include "dshow.h"
-
-#include "unix_private.h"
-
-GST_DEBUG_CATEGORY_EXTERN(wine);
-#define GST_CAT_DEFAULT wine
-
-static enum wg_audio_format wg_audio_format_from_gst(GstAudioFormat format)
-{
- switch (format)
- {
- case GST_AUDIO_FORMAT_U8:
- return WG_AUDIO_FORMAT_U8;
- case GST_AUDIO_FORMAT_S16LE:
- return WG_AUDIO_FORMAT_S16LE;
- case GST_AUDIO_FORMAT_S24LE:
- return WG_AUDIO_FORMAT_S24LE;
- case GST_AUDIO_FORMAT_S32LE:
- return WG_AUDIO_FORMAT_S32LE;
- case GST_AUDIO_FORMAT_F32LE:
- return WG_AUDIO_FORMAT_F32LE;
- case GST_AUDIO_FORMAT_F64LE:
- return WG_AUDIO_FORMAT_F64LE;
- default:
- return WG_AUDIO_FORMAT_UNKNOWN;
- }
-}
-
-static uint32_t wg_channel_position_from_gst(GstAudioChannelPosition position)
-{
- static const uint32_t position_map[] =
- {
- SPEAKER_FRONT_LEFT,
- SPEAKER_FRONT_RIGHT,
- SPEAKER_FRONT_CENTER,
- SPEAKER_LOW_FREQUENCY,
- SPEAKER_BACK_LEFT,
- SPEAKER_BACK_RIGHT,
- SPEAKER_FRONT_LEFT_OF_CENTER,
- SPEAKER_FRONT_RIGHT_OF_CENTER,
- SPEAKER_BACK_CENTER,
- 0,
- SPEAKER_SIDE_LEFT,
- SPEAKER_SIDE_RIGHT,
- SPEAKER_TOP_FRONT_LEFT,
- SPEAKER_TOP_FRONT_RIGHT,
- SPEAKER_TOP_FRONT_CENTER,
- SPEAKER_TOP_CENTER,
- SPEAKER_TOP_BACK_LEFT,
- SPEAKER_TOP_BACK_RIGHT,
- 0,
- 0,
- SPEAKER_TOP_BACK_CENTER,
- };
-
- if (position == GST_AUDIO_CHANNEL_POSITION_MONO)
- return SPEAKER_FRONT_CENTER;
-
- if (position >= 0 && position < ARRAY_SIZE(position_map))
- return position_map[position];
- return 0;
-}
-
-static uint32_t wg_channel_mask_from_gst(const GstAudioInfo *info)
-{
- uint32_t mask = 0, position;
- unsigned int i;
-
- for (i = 0; i < GST_AUDIO_INFO_CHANNELS(info); ++i)
- {
- if (!(position = wg_channel_position_from_gst(GST_AUDIO_INFO_POSITION(info, i))))
- {
- GST_WARNING("Unsupported channel %#x.", GST_AUDIO_INFO_POSITION(info, i));
- return 0;
- }
- /* Make sure it's also in WinMM order. WinMM mandates that channels be
- * ordered, as it were, from least to most significant SPEAKER_* bit.
- * Hence we fail if the current channel was already specified, or if any
- * higher bit was already specified. */
- if (mask & ~(position - 1))
- {
- GST_WARNING("Unsupported channel order.");
- return 0;
- }
- mask |= position;
- }
- return mask;
-}
-
-static void wg_format_from_audio_info(struct wg_format *format, const GstAudioInfo *info)
-{
- format->major_type = WG_MAJOR_TYPE_AUDIO;
- format->u.audio.format = wg_audio_format_from_gst(GST_AUDIO_INFO_FORMAT(info));
- format->u.audio.channels = GST_AUDIO_INFO_CHANNELS(info);
- format->u.audio.channel_mask = wg_channel_mask_from_gst(info);
- format->u.audio.rate = GST_AUDIO_INFO_RATE(info);
-}
-
-static enum wg_video_format wg_video_format_from_gst(GstVideoFormat format)
-{
- switch (format)
- {
- case GST_VIDEO_FORMAT_BGRA:
- return WG_VIDEO_FORMAT_BGRA;
- case GST_VIDEO_FORMAT_BGRx:
- return WG_VIDEO_FORMAT_BGRx;
- case GST_VIDEO_FORMAT_BGR:
- return WG_VIDEO_FORMAT_BGR;
- case GST_VIDEO_FORMAT_RGB15:
- return WG_VIDEO_FORMAT_RGB15;
- case GST_VIDEO_FORMAT_RGB16:
- return WG_VIDEO_FORMAT_RGB16;
- case GST_VIDEO_FORMAT_AYUV:
- return WG_VIDEO_FORMAT_AYUV;
- case GST_VIDEO_FORMAT_I420:
- return WG_VIDEO_FORMAT_I420;
- case GST_VIDEO_FORMAT_NV12:
- return WG_VIDEO_FORMAT_NV12;
- case GST_VIDEO_FORMAT_UYVY:
- return WG_VIDEO_FORMAT_UYVY;
- case GST_VIDEO_FORMAT_YUY2:
- return WG_VIDEO_FORMAT_YUY2;
- case GST_VIDEO_FORMAT_YV12:
- return WG_VIDEO_FORMAT_YV12;
- case GST_VIDEO_FORMAT_YVYU:
- return WG_VIDEO_FORMAT_YVYU;
- default:
- return WG_VIDEO_FORMAT_UNKNOWN;
- }
-}
-
-static void wg_format_from_video_info(struct wg_format *format, const GstVideoInfo *info)
-{
- format->major_type = WG_MAJOR_TYPE_VIDEO;
- format->u.video.format = wg_video_format_from_gst(GST_VIDEO_INFO_FORMAT(info));
- format->u.video.width = GST_VIDEO_INFO_WIDTH(info);
- format->u.video.height = GST_VIDEO_INFO_HEIGHT(info);
- format->u.video.fps_n = GST_VIDEO_INFO_FPS_N(info);
- format->u.video.fps_d = GST_VIDEO_INFO_FPS_D(info);
-}
-
-static void wg_format_from_caps_audio_mpeg(struct wg_format *format, const GstCaps *caps)
-{
- const GstStructure *structure = gst_caps_get_structure(caps, 0);
- gint layer, channels, rate;
-
- if (!gst_structure_get_int(structure, "layer", &layer))
- {
- GST_WARNING("Missing \"layer\" value.");
- return;
- }
- if (!gst_structure_get_int(structure, "channels", &channels))
- {
- GST_WARNING("Missing \"channels\" value.");
- return;
- }
- if (!gst_structure_get_int(structure, "rate", &rate))
- {
- GST_WARNING("Missing \"rate\" value.");
- return;
- }
-
- format->major_type = WG_MAJOR_TYPE_AUDIO;
-
- if (layer == 1)
- format->u.audio.format = WG_AUDIO_FORMAT_MPEG1_LAYER1;
- else if (layer == 2)
- format->u.audio.format = WG_AUDIO_FORMAT_MPEG1_LAYER2;
- else if (layer == 3)
- format->u.audio.format = WG_AUDIO_FORMAT_MPEG1_LAYER3;
-
- format->u.audio.channels = channels;
- format->u.audio.rate = rate;
-}
-
-static void wg_format_from_caps_video_cinepak(struct wg_format *format, const GstCaps *caps)
-{
- const GstStructure *structure = gst_caps_get_structure(caps, 0);
- gint width, height, fps_n, fps_d;
-
- if (!gst_structure_get_int(structure, "width", &width))
- {
- GST_WARNING("Missing \"width\" value.");
- return;
- }
- if (!gst_structure_get_int(structure, "height", &height))
- {
- GST_WARNING("Missing \"height\" value.");
- return;
- }
- if (!gst_structure_get_fraction(structure, "framerate", &fps_n, &fps_d))
- {
- fps_n = 0;
- fps_d = 1;
- }
-
- format->major_type = WG_MAJOR_TYPE_VIDEO;
- format->u.video.format = WG_VIDEO_FORMAT_CINEPAK;
- format->u.video.width = width;
- format->u.video.height = height;
- format->u.video.fps_n = fps_n;
- format->u.video.fps_d = fps_d;
-}
-
-void wg_format_from_caps(struct wg_format *format, const GstCaps *caps)
-{
- const GstStructure *structure = gst_caps_get_structure(caps, 0);
- const char *name = gst_structure_get_name(structure);
-
- memset(format, 0, sizeof(*format));
-
- if (!strcmp(name, "audio/x-raw"))
- {
- GstAudioInfo info;
-
- if (gst_audio_info_from_caps(&info, caps))
- wg_format_from_audio_info(format, &info);
- }
- else if (!strcmp(name, "video/x-raw"))
- {
- GstVideoInfo info;
-
- if (gst_video_info_from_caps(&info, caps))
- wg_format_from_video_info(format, &info);
- }
- else if (!strcmp(name, "audio/mpeg"))
- {
- wg_format_from_caps_audio_mpeg(format, caps);
- }
- else if (!strcmp(name, "video/x-cinepak"))
- {
- wg_format_from_caps_video_cinepak(format, caps);
- }
- else
- {
- gchar *str = gst_caps_to_string(caps);
-
- GST_FIXME("Unhandled caps %s.", str);
- g_free(str);
- }
-}
-
-static GstAudioFormat wg_audio_format_to_gst(enum wg_audio_format format)
-{
- switch (format)
- {
- case WG_AUDIO_FORMAT_U8: return GST_AUDIO_FORMAT_U8;
- case WG_AUDIO_FORMAT_S16LE: return GST_AUDIO_FORMAT_S16LE;
- case WG_AUDIO_FORMAT_S24LE: return GST_AUDIO_FORMAT_S24LE;
- case WG_AUDIO_FORMAT_S32LE: return GST_AUDIO_FORMAT_S32LE;
- case WG_AUDIO_FORMAT_F32LE: return GST_AUDIO_FORMAT_F32LE;
- case WG_AUDIO_FORMAT_F64LE: return GST_AUDIO_FORMAT_F64LE;
- default: return GST_AUDIO_FORMAT_UNKNOWN;
- }
-}
-
-static void wg_channel_mask_to_gst(GstAudioChannelPosition *positions, uint32_t mask, uint32_t channel_count)
-{
- const uint32_t orig_mask = mask;
- unsigned int i;
- DWORD bit;
-
- static const GstAudioChannelPosition position_map[] =
- {
- GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT,
- GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT,
- GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER,
- GST_AUDIO_CHANNEL_POSITION_LFE1,
- GST_AUDIO_CHANNEL_POSITION_REAR_LEFT,
- GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT,
- GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER,
- GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER,
- GST_AUDIO_CHANNEL_POSITION_REAR_CENTER,
- GST_AUDIO_CHANNEL_POSITION_SIDE_LEFT,
- GST_AUDIO_CHANNEL_POSITION_SIDE_RIGHT,
- GST_AUDIO_CHANNEL_POSITION_TOP_CENTER,
- GST_AUDIO_CHANNEL_POSITION_TOP_FRONT_LEFT,
- GST_AUDIO_CHANNEL_POSITION_TOP_FRONT_CENTER,
- GST_AUDIO_CHANNEL_POSITION_TOP_FRONT_RIGHT,
- GST_AUDIO_CHANNEL_POSITION_TOP_REAR_LEFT,
- GST_AUDIO_CHANNEL_POSITION_TOP_REAR_CENTER,
- GST_AUDIO_CHANNEL_POSITION_TOP_REAR_RIGHT,
- };
-
- for (i = 0; i < channel_count; ++i)
- {
- positions[i] = GST_AUDIO_CHANNEL_POSITION_NONE;
- if (BitScanForward(&bit, mask))
- {
- if (bit < ARRAY_SIZE(position_map))
- positions[i] = position_map[bit];
- else
- GST_WARNING("Invalid channel mask %#x.\n", orig_mask);
- mask &= ~(1 << bit);
- }
- else
- {
- GST_WARNING("Incomplete channel mask %#x.\n", orig_mask);
- }
- }
-}
-
-static GstCaps *wg_format_to_caps_audio(const struct wg_format *format)
-{
- GstAudioChannelPosition positions[32];
- GstAudioFormat audio_format;
- GstAudioInfo info;
-
- if ((audio_format = wg_audio_format_to_gst(format->u.audio.format)) == GST_AUDIO_FORMAT_UNKNOWN)
- return NULL;
-
- wg_channel_mask_to_gst(positions, format->u.audio.channel_mask, format->u.audio.channels);
- gst_audio_info_set_format(&info, audio_format, format->u.audio.rate, format->u.audio.channels, positions);
- return gst_audio_info_to_caps(&info);
-}
-
-static GstVideoFormat wg_video_format_to_gst(enum wg_video_format format)
-{
- switch (format)
- {
- case WG_VIDEO_FORMAT_BGRA: return GST_VIDEO_FORMAT_BGRA;
- case WG_VIDEO_FORMAT_BGRx: return GST_VIDEO_FORMAT_BGRx;
- case WG_VIDEO_FORMAT_BGR: return GST_VIDEO_FORMAT_BGR;
- case WG_VIDEO_FORMAT_RGB15: return GST_VIDEO_FORMAT_RGB15;
- case WG_VIDEO_FORMAT_RGB16: return GST_VIDEO_FORMAT_RGB16;
- case WG_VIDEO_FORMAT_AYUV: return GST_VIDEO_FORMAT_AYUV;
- case WG_VIDEO_FORMAT_I420: return GST_VIDEO_FORMAT_I420;
- case WG_VIDEO_FORMAT_NV12: return GST_VIDEO_FORMAT_NV12;
- case WG_VIDEO_FORMAT_UYVY: return GST_VIDEO_FORMAT_UYVY;
- case WG_VIDEO_FORMAT_YUY2: return GST_VIDEO_FORMAT_YUY2;
- case WG_VIDEO_FORMAT_YV12: return GST_VIDEO_FORMAT_YV12;
- case WG_VIDEO_FORMAT_YVYU: return GST_VIDEO_FORMAT_YVYU;
- default: return GST_VIDEO_FORMAT_UNKNOWN;
- }
-}
-
-static GstCaps *wg_format_to_caps_video(const struct wg_format *format)
-{
- GstVideoFormat video_format;
- GstVideoInfo info;
- unsigned int i;
- GstCaps *caps;
-
- if ((video_format = wg_video_format_to_gst(format->u.video.format)) == GST_VIDEO_FORMAT_UNKNOWN)
- return NULL;
-
- gst_video_info_set_format(&info, video_format, format->u.video.width, abs(format->u.video.height));
- if ((caps = gst_video_info_to_caps(&info)))
- {
- /* Clear some fields that shouldn't prevent us from connecting. */
- for (i = 0; i < gst_caps_get_size(caps); ++i)
- {
- gst_structure_remove_fields(gst_caps_get_structure(caps, i),
- "framerate", "pixel-aspect-ratio", "colorimetry", "chroma-site", NULL);
- }
- }
- return caps;
-}
-
-GstCaps *wg_format_to_caps(const struct wg_format *format)
-{
- switch (format->major_type)
- {
- case WG_MAJOR_TYPE_UNKNOWN:
- return NULL;
- case WG_MAJOR_TYPE_AUDIO:
- return wg_format_to_caps_audio(format);
- case WG_MAJOR_TYPE_VIDEO:
- return wg_format_to_caps_video(format);
- }
- assert(0);
- return NULL;
-}
-
-bool wg_format_compare(const struct wg_format *a, const struct wg_format *b)
-{
- if (a->major_type != b->major_type)
- return false;
-
- switch (a->major_type)
- {
- case WG_MAJOR_TYPE_UNKNOWN:
- return false;
-
- case WG_MAJOR_TYPE_AUDIO:
- return a->u.audio.format == b->u.audio.format
- && a->u.audio.channels == b->u.audio.channels
- && a->u.audio.rate == b->u.audio.rate;
-
- case WG_MAJOR_TYPE_VIDEO:
- /* Do not compare FPS. */
- return a->u.video.format == b->u.video.format
- && a->u.video.width == b->u.video.width
- && abs(a->u.video.height) == abs(b->u.video.height);
- }
-
- assert(0);
- return false;
-}
diff --git a/dlls/winegstreamer/wg_parser.c b/dlls/winegstreamer/wg_parser.c
index 66f60d27477..0a6cf927187 100644
--- a/dlls/winegstreamer/wg_parser.c
+++ b/dlls/winegstreamer/wg_parser.c
@@ -37,7 +37,7 @@
#include "winternl.h"
#include "dshow.h"
-#include "unix_private.h"
+#include "unixlib.h"
typedef enum
{
@@ -51,7 +51,7 @@ typedef enum
* debug logging instead of Wine debug logging. In order to be safe we forbid
* any use of Wine debug logging in this entire file. */
-GST_DEBUG_CATEGORY(wine);
+GST_DEBUG_CATEGORY_STATIC(wine);
#define GST_CAT_DEFAULT wine
typedef BOOL (*init_gst_cb)(struct wg_parser *parser);
@@ -111,6 +111,399 @@ struct wg_parser_stream
uint64_t duration;
};
+static enum wg_audio_format wg_audio_format_from_gst(GstAudioFormat format)
+{
+ switch (format)
+ {
+ case GST_AUDIO_FORMAT_U8:
+ return WG_AUDIO_FORMAT_U8;
+ case GST_AUDIO_FORMAT_S16LE:
+ return WG_AUDIO_FORMAT_S16LE;
+ case GST_AUDIO_FORMAT_S24LE:
+ return WG_AUDIO_FORMAT_S24LE;
+ case GST_AUDIO_FORMAT_S32LE:
+ return WG_AUDIO_FORMAT_S32LE;
+ case GST_AUDIO_FORMAT_F32LE:
+ return WG_AUDIO_FORMAT_F32LE;
+ case GST_AUDIO_FORMAT_F64LE:
+ return WG_AUDIO_FORMAT_F64LE;
+ default:
+ return WG_AUDIO_FORMAT_UNKNOWN;
+ }
+}
+
+static uint32_t wg_channel_position_from_gst(GstAudioChannelPosition position)
+{
+ static const uint32_t position_map[] =
+ {
+ SPEAKER_FRONT_LEFT,
+ SPEAKER_FRONT_RIGHT,
+ SPEAKER_FRONT_CENTER,
+ SPEAKER_LOW_FREQUENCY,
+ SPEAKER_BACK_LEFT,
+ SPEAKER_BACK_RIGHT,
+ SPEAKER_FRONT_LEFT_OF_CENTER,
+ SPEAKER_FRONT_RIGHT_OF_CENTER,
+ SPEAKER_BACK_CENTER,
+ 0,
+ SPEAKER_SIDE_LEFT,
+ SPEAKER_SIDE_RIGHT,
+ SPEAKER_TOP_FRONT_LEFT,
+ SPEAKER_TOP_FRONT_RIGHT,
+ SPEAKER_TOP_FRONT_CENTER,
+ SPEAKER_TOP_CENTER,
+ SPEAKER_TOP_BACK_LEFT,
+ SPEAKER_TOP_BACK_RIGHT,
+ 0,
+ 0,
+ SPEAKER_TOP_BACK_CENTER,
+ };
+
+ if (position == GST_AUDIO_CHANNEL_POSITION_MONO)
+ return SPEAKER_FRONT_CENTER;
+
+ if (position >= 0 && position < ARRAY_SIZE(position_map))
+ return position_map[position];
+ return 0;
+}
+
+static uint32_t wg_channel_mask_from_gst(const GstAudioInfo *info)
+{
+ uint32_t mask = 0, position;
+ unsigned int i;
+
+ for (i = 0; i < GST_AUDIO_INFO_CHANNELS(info); ++i)
+ {
+ if (!(position = wg_channel_position_from_gst(GST_AUDIO_INFO_POSITION(info, i))))
+ {
+ GST_WARNING("Unsupported channel %#x.", GST_AUDIO_INFO_POSITION(info, i));
+ return 0;
+ }
+ /* Make sure it's also in WinMM order. WinMM mandates that channels be
+ * ordered, as it were, from least to most significant SPEAKER_* bit.
+ * Hence we fail if the current channel was already specified, or if any
+ * higher bit was already specified. */
+ if (mask & ~(position - 1))
+ {
+ GST_WARNING("Unsupported channel order.");
+ return 0;
+ }
+ mask |= position;
+ }
+ return mask;
+}
+
+static void wg_format_from_audio_info(struct wg_format *format, const GstAudioInfo *info)
+{
+ format->major_type = WG_MAJOR_TYPE_AUDIO;
+ format->u.audio.format = wg_audio_format_from_gst(GST_AUDIO_INFO_FORMAT(info));
+ format->u.audio.channels = GST_AUDIO_INFO_CHANNELS(info);
+ format->u.audio.channel_mask = wg_channel_mask_from_gst(info);
+ format->u.audio.rate = GST_AUDIO_INFO_RATE(info);
+}
+
+static enum wg_video_format wg_video_format_from_gst(GstVideoFormat format)
+{
+ switch (format)
+ {
+ case GST_VIDEO_FORMAT_BGRA:
+ return WG_VIDEO_FORMAT_BGRA;
+ case GST_VIDEO_FORMAT_BGRx:
+ return WG_VIDEO_FORMAT_BGRx;
+ case GST_VIDEO_FORMAT_BGR:
+ return WG_VIDEO_FORMAT_BGR;
+ case GST_VIDEO_FORMAT_RGB15:
+ return WG_VIDEO_FORMAT_RGB15;
+ case GST_VIDEO_FORMAT_RGB16:
+ return WG_VIDEO_FORMAT_RGB16;
+ case GST_VIDEO_FORMAT_AYUV:
+ return WG_VIDEO_FORMAT_AYUV;
+ case GST_VIDEO_FORMAT_I420:
+ return WG_VIDEO_FORMAT_I420;
+ case GST_VIDEO_FORMAT_NV12:
+ return WG_VIDEO_FORMAT_NV12;
+ case GST_VIDEO_FORMAT_UYVY:
+ return WG_VIDEO_FORMAT_UYVY;
+ case GST_VIDEO_FORMAT_YUY2:
+ return WG_VIDEO_FORMAT_YUY2;
+ case GST_VIDEO_FORMAT_YV12:
+ return WG_VIDEO_FORMAT_YV12;
+ case GST_VIDEO_FORMAT_YVYU:
+ return WG_VIDEO_FORMAT_YVYU;
+ default:
+ return WG_VIDEO_FORMAT_UNKNOWN;
+ }
+}
+
+static void wg_format_from_video_info(struct wg_format *format, const GstVideoInfo *info)
+{
+ format->major_type = WG_MAJOR_TYPE_VIDEO;
+ format->u.video.format = wg_video_format_from_gst(GST_VIDEO_INFO_FORMAT(info));
+ format->u.video.width = GST_VIDEO_INFO_WIDTH(info);
+ format->u.video.height = GST_VIDEO_INFO_HEIGHT(info);
+ format->u.video.fps_n = GST_VIDEO_INFO_FPS_N(info);
+ format->u.video.fps_d = GST_VIDEO_INFO_FPS_D(info);
+}
+
+static void wg_format_from_caps_audio_mpeg(struct wg_format *format, const GstCaps *caps)
+{
+ const GstStructure *structure = gst_caps_get_structure(caps, 0);
+ gint layer, channels, rate;
+
+ if (!gst_structure_get_int(structure, "layer", &layer))
+ {
+ GST_WARNING("Missing \"layer\" value.");
+ return;
+ }
+ if (!gst_structure_get_int(structure, "channels", &channels))
+ {
+ GST_WARNING("Missing \"channels\" value.");
+ return;
+ }
+ if (!gst_structure_get_int(structure, "rate", &rate))
+ {
+ GST_WARNING("Missing \"rate\" value.");
+ return;
+ }
+
+ format->major_type = WG_MAJOR_TYPE_AUDIO;
+
+ if (layer == 1)
+ format->u.audio.format = WG_AUDIO_FORMAT_MPEG1_LAYER1;
+ else if (layer == 2)
+ format->u.audio.format = WG_AUDIO_FORMAT_MPEG1_LAYER2;
+ else if (layer == 3)
+ format->u.audio.format = WG_AUDIO_FORMAT_MPEG1_LAYER3;
+
+ format->u.audio.channels = channels;
+ format->u.audio.rate = rate;
+}
+
+static void wg_format_from_caps_video_cinepak(struct wg_format *format, const GstCaps *caps)
+{
+ const GstStructure *structure = gst_caps_get_structure(caps, 0);
+ gint width, height, fps_n, fps_d;
+
+ if (!gst_structure_get_int(structure, "width", &width))
+ {
+ GST_WARNING("Missing \"width\" value.");
+ return;
+ }
+ if (!gst_structure_get_int(structure, "height", &height))
+ {
+ GST_WARNING("Missing \"height\" value.");
+ return;
+ }
+ if (!gst_structure_get_fraction(structure, "framerate", &fps_n, &fps_d))
+ {
+ fps_n = 0;
+ fps_d = 1;
+ }
+
+ format->major_type = WG_MAJOR_TYPE_VIDEO;
+ format->u.video.format = WG_VIDEO_FORMAT_CINEPAK;
+ format->u.video.width = width;
+ format->u.video.height = height;
+ format->u.video.fps_n = fps_n;
+ format->u.video.fps_d = fps_d;
+}
+
+static void wg_format_from_caps(struct wg_format *format, const GstCaps *caps)
+{
+ const GstStructure *structure = gst_caps_get_structure(caps, 0);
+ const char *name = gst_structure_get_name(structure);
+
+ memset(format, 0, sizeof(*format));
+
+ if (!strcmp(name, "audio/x-raw"))
+ {
+ GstAudioInfo info;
+
+ if (gst_audio_info_from_caps(&info, caps))
+ wg_format_from_audio_info(format, &info);
+ }
+ else if (!strcmp(name, "video/x-raw"))
+ {
+ GstVideoInfo info;
+
+ if (gst_video_info_from_caps(&info, caps))
+ wg_format_from_video_info(format, &info);
+ }
+ else if (!strcmp(name, "audio/mpeg"))
+ {
+ wg_format_from_caps_audio_mpeg(format, caps);
+ }
+ else if (!strcmp(name, "video/x-cinepak"))
+ {
+ wg_format_from_caps_video_cinepak(format, caps);
+ }
+ else
+ {
+ gchar *str = gst_caps_to_string(caps);
+
+ GST_FIXME("Unhandled caps %s.", str);
+ g_free(str);
+ }
+}
+
+static GstAudioFormat wg_audio_format_to_gst(enum wg_audio_format format)
+{
+ switch (format)
+ {
+ case WG_AUDIO_FORMAT_U8: return GST_AUDIO_FORMAT_U8;
+ case WG_AUDIO_FORMAT_S16LE: return GST_AUDIO_FORMAT_S16LE;
+ case WG_AUDIO_FORMAT_S24LE: return GST_AUDIO_FORMAT_S24LE;
+ case WG_AUDIO_FORMAT_S32LE: return GST_AUDIO_FORMAT_S32LE;
+ case WG_AUDIO_FORMAT_F32LE: return GST_AUDIO_FORMAT_F32LE;
+ case WG_AUDIO_FORMAT_F64LE: return GST_AUDIO_FORMAT_F64LE;
+ default: return GST_AUDIO_FORMAT_UNKNOWN;
+ }
+}
+
+static void wg_channel_mask_to_gst(GstAudioChannelPosition *positions, uint32_t mask, uint32_t channel_count)
+{
+ const uint32_t orig_mask = mask;
+ unsigned int i;
+ DWORD bit;
+
+ static const GstAudioChannelPosition position_map[] =
+ {
+ GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT,
+ GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT,
+ GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER,
+ GST_AUDIO_CHANNEL_POSITION_LFE1,
+ GST_AUDIO_CHANNEL_POSITION_REAR_LEFT,
+ GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT,
+ GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER,
+ GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER,
+ GST_AUDIO_CHANNEL_POSITION_REAR_CENTER,
+ GST_AUDIO_CHANNEL_POSITION_SIDE_LEFT,
+ GST_AUDIO_CHANNEL_POSITION_SIDE_RIGHT,
+ GST_AUDIO_CHANNEL_POSITION_TOP_CENTER,
+ GST_AUDIO_CHANNEL_POSITION_TOP_FRONT_LEFT,
+ GST_AUDIO_CHANNEL_POSITION_TOP_FRONT_CENTER,
+ GST_AUDIO_CHANNEL_POSITION_TOP_FRONT_RIGHT,
+ GST_AUDIO_CHANNEL_POSITION_TOP_REAR_LEFT,
+ GST_AUDIO_CHANNEL_POSITION_TOP_REAR_CENTER,
+ GST_AUDIO_CHANNEL_POSITION_TOP_REAR_RIGHT,
+ };
+
+ for (i = 0; i < channel_count; ++i)
+ {
+ positions[i] = GST_AUDIO_CHANNEL_POSITION_NONE;
+ if (BitScanForward(&bit, mask))
+ {
+ if (bit < ARRAY_SIZE(position_map))
+ positions[i] = position_map[bit];
+ else
+ GST_WARNING("Invalid channel mask %#x.\n", orig_mask);
+ mask &= ~(1 << bit);
+ }
+ else
+ {
+ GST_WARNING("Incomplete channel mask %#x.\n", orig_mask);
+ }
+ }
+}
+
+static GstCaps *wg_format_to_caps_audio(const struct wg_format *format)
+{
+ GstAudioChannelPosition positions[32];
+ GstAudioFormat audio_format;
+ GstAudioInfo info;
+
+ if ((audio_format = wg_audio_format_to_gst(format->u.audio.format)) == GST_AUDIO_FORMAT_UNKNOWN)
+ return NULL;
+
+ wg_channel_mask_to_gst(positions, format->u.audio.channel_mask, format->u.audio.channels);
+ gst_audio_info_set_format(&info, audio_format, format->u.audio.rate, format->u.audio.channels, positions);
+ return gst_audio_info_to_caps(&info);
+}
+
+static GstVideoFormat wg_video_format_to_gst(enum wg_video_format format)
+{
+ switch (format)
+ {
+ case WG_VIDEO_FORMAT_BGRA: return GST_VIDEO_FORMAT_BGRA;
+ case WG_VIDEO_FORMAT_BGRx: return GST_VIDEO_FORMAT_BGRx;
+ case WG_VIDEO_FORMAT_BGR: return GST_VIDEO_FORMAT_BGR;
+ case WG_VIDEO_FORMAT_RGB15: return GST_VIDEO_FORMAT_RGB15;
+ case WG_VIDEO_FORMAT_RGB16: return GST_VIDEO_FORMAT_RGB16;
+ case WG_VIDEO_FORMAT_AYUV: return GST_VIDEO_FORMAT_AYUV;
+ case WG_VIDEO_FORMAT_I420: return GST_VIDEO_FORMAT_I420;
+ case WG_VIDEO_FORMAT_NV12: return GST_VIDEO_FORMAT_NV12;
+ case WG_VIDEO_FORMAT_UYVY: return GST_VIDEO_FORMAT_UYVY;
+ case WG_VIDEO_FORMAT_YUY2: return GST_VIDEO_FORMAT_YUY2;
+ case WG_VIDEO_FORMAT_YV12: return GST_VIDEO_FORMAT_YV12;
+ case WG_VIDEO_FORMAT_YVYU: return GST_VIDEO_FORMAT_YVYU;
+ default: return GST_VIDEO_FORMAT_UNKNOWN;
+ }
+}
+
+static GstCaps *wg_format_to_caps_video(const struct wg_format *format)
+{
+ GstVideoFormat video_format;
+ GstVideoInfo info;
+ unsigned int i;
+ GstCaps *caps;
+
+ if ((video_format = wg_video_format_to_gst(format->u.video.format)) == GST_VIDEO_FORMAT_UNKNOWN)
+ return NULL;
+
+ gst_video_info_set_format(&info, video_format, format->u.video.width, abs(format->u.video.height));
+ if ((caps = gst_video_info_to_caps(&info)))
+ {
+ /* Clear some fields that shouldn't prevent us from connecting. */
+ for (i = 0; i < gst_caps_get_size(caps); ++i)
+ {
+ gst_structure_remove_fields(gst_caps_get_structure(caps, i),
+ "framerate", "pixel-aspect-ratio", "colorimetry", "chroma-site", NULL);
+ }
+ }
+ return caps;
+}
+
+static GstCaps *wg_format_to_caps(const struct wg_format *format)
+{
+ switch (format->major_type)
+ {
+ case WG_MAJOR_TYPE_UNKNOWN:
+ return NULL;
+ case WG_MAJOR_TYPE_AUDIO:
+ return wg_format_to_caps_audio(format);
+ case WG_MAJOR_TYPE_VIDEO:
+ return wg_format_to_caps_video(format);
+ }
+ assert(0);
+ return NULL;
+}
+
+static bool wg_format_compare(const struct wg_format *a, const struct wg_format *b)
+{
+ if (a->major_type != b->major_type)
+ return false;
+
+ switch (a->major_type)
+ {
+ case WG_MAJOR_TYPE_UNKNOWN:
+ return false;
+
+ case WG_MAJOR_TYPE_AUDIO:
+ return a->u.audio.format == b->u.audio.format
+ && a->u.audio.channels == b->u.audio.channels
+ && a->u.audio.rate == b->u.audio.rate;
+
+ case WG_MAJOR_TYPE_VIDEO:
+ /* Do not compare FPS. */
+ return a->u.video.format == b->u.video.format
+ && a->u.video.width == b->u.video.width
+ && abs(a->u.video.height) == abs(b->u.video.height);
+ }
+
+ assert(0);
+ return false;
+}
+
static NTSTATUS wg_parser_get_stream_count(void *args)
{
struct wg_parser_get_stream_count_params *params = args;
--
2.34.1

View File

@ -1,63 +0,0 @@
From 75d383ab1c6b3c3872b895164c816d11de1d821c Mon Sep 17 00:00:00 2001
From: Derek Lesho <dlesho@codeweavers.com>
Date: Tue, 9 Mar 2021 16:53:09 -0500
Subject: [PATCH 13/88] 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 | 9 ++++++++-
1 file changed, 8 insertions(+), 1 deletion(-)
diff --git a/dlls/winegstreamer/wg_parser.c b/dlls/winegstreamer/wg_parser.c
index b93b2c182ae..d7412409a27 100644
--- a/dlls/winegstreamer/wg_parser.c
+++ b/dlls/winegstreamer/wg_parser.c
@@ -75,7 +75,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
@@ -1528,9 +1528,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);
@@ -1695,6 +1698,8 @@ static NTSTATUS wg_parser_connect(void *args)
goto out;
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)
{
@@ -1833,6 +1838,8 @@ static NTSTATUS wg_parser_disconnect(void *args)
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);
--
2.34.1

View File

@ -1,60 +0,0 @@
From c8a074d72e06a8e44cb9390126e656800d249e08 Mon Sep 17 00:00:00 2001
From: Derek Lesho <dlesho@codeweavers.com>
Date: Wed, 10 Mar 2021 10:43:03 -0500
Subject: [PATCH 14/88] 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 d7412409a27..c6e8bbcb26b 100644
--- a/dlls/winegstreamer/wg_parser.c
+++ b/dlls/winegstreamer/wg_parser.c
@@ -1449,6 +1449,7 @@ static void *push_data(void *arg)
{
struct wg_parser *parser = arg;
GstBuffer *buffer;
+ GstSegment *segment;
guint max_size;
GST_DEBUG("Starting push thread.");
@@ -1461,6 +1462,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;
@@ -1595,6 +1602,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;
@@ -1628,7 +1636,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.34.1

View File

@ -1,391 +0,0 @@
From 95180a07deb9e543627a8705da2bc73ccfff70a5 Mon Sep 17 00:00:00 2001
From: Derek Lesho <dlesho@codeweavers.com>
Date: Wed, 10 Mar 2021 13:09:51 -0500
Subject: [PATCH 15/88] 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/main.c | 3 +
dlls/winegstreamer/mfplat.c | 1 +
dlls/winegstreamer/winegstreamer_classes.idl | 6 +
6 files changed, 314 insertions(+)
create mode 100644 dlls/winegstreamer/decode_transform.c
diff --git a/dlls/winegstreamer/Makefile.in b/dlls/winegstreamer/Makefile.in
index c53e914e246..3da8c614ed2 100644
--- a/dlls/winegstreamer/Makefile.in
+++ b/dlls/winegstreamer/Makefile.in
@@ -8,6 +8,7 @@ EXTRALIBS = $(GSTREAMER_LIBS) $(PTHREAD_LIBS)
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 3584f465218..588aa50bccd 100644
--- a/dlls/winegstreamer/gst_private.h
+++ b/dlls/winegstreamer/gst_private.h
@@ -119,6 +119,8 @@ HRESULT winegstreamer_stream_handler_create(REFIID riid, void **obj);
HRESULT audio_converter_create(REFIID riid, void **ret);
+HRESULT decode_transform_create(REFIID riid, void **obj) DECLSPEC_HIDDEN;
+
struct wm_stream
{
struct wm_reader *reader;
diff --git a/dlls/winegstreamer/main.c b/dlls/winegstreamer/main.c
index 51a71d3b4a5..8f487655748 100644
--- a/dlls/winegstreamer/main.c
+++ b/dlls/winegstreamer/main.c
@@ -547,6 +547,9 @@ HRESULT WINAPI DllRegisterServer(void)
init_gstreamer();
+ if (FAILED(hr = mfplat_DllRegisterServer()))
+ return hr;
+
if (FAILED(hr = __wine_register_resources()))
return hr;
diff --git a/dlls/winegstreamer/mfplat.c b/dlls/winegstreamer/mfplat.c
index a111bbe196d..8b455a67aa2 100644
--- a/dlls/winegstreamer/mfplat.c
+++ b/dlls/winegstreamer/mfplat.c
@@ -408,6 +408,7 @@ class_objects[] =
{ &CLSID_VideoProcessorMFT, &video_processor_create },
{ &CLSID_GStreamerByteStreamHandler, &winegstreamer_stream_handler_create },
{ &CLSID_WINEAudioConverter, &audio_converter_create },
+ { &CLSID_MSH264DecoderMFT, &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 90dc1dc839b..022f5f80980 100644
--- a/dlls/winegstreamer/winegstreamer_classes.idl
+++ b/dlls/winegstreamer/winegstreamer_classes.idl
@@ -73,3 +73,9 @@ coclass WINEAudioConverter { }
uuid(2eeb4adf-4578-4d10-bca7-bb955f56320a)
]
coclass CWMADecMediaObject {};
+
+[
+ threading(both),
+ uuid(62ce7e72-4c71-4d20-b15d-452831a87d9d)
+]
+coclass CMSH264DecoderMFT { }
--
2.34.1

View File

@ -1,158 +0,0 @@
From 26157534099bf6653456d66d964c5c2f09f9a9a7 Mon Sep 17 00:00:00 2001
From: Derek Lesho <dlesho@codeweavers.com>
Date: Tue, 14 Dec 2021 13:36:27 +0100
Subject: [PATCH 16/88] 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 588aa50bccd..b9379487ac2 100644
--- a/dlls/winegstreamer/gst_private.h
+++ b/dlls/winegstreamer/gst_private.h
@@ -119,7 +119,11 @@ HRESULT winegstreamer_stream_handler_create(REFIID riid, void **obj);
HRESULT audio_converter_create(REFIID riid, void **ret);
-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;
struct wm_stream
{
diff --git a/dlls/winegstreamer/mfplat.c b/dlls/winegstreamer/mfplat.c
index 8b455a67aa2..93ddb90a070 100644
--- a/dlls/winegstreamer/mfplat.c
+++ b/dlls/winegstreamer/mfplat.c
@@ -398,6 +398,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;
@@ -408,7 +413,7 @@ class_objects[] =
{ &CLSID_VideoProcessorMFT, &video_processor_create },
{ &CLSID_GStreamerByteStreamHandler, &winegstreamer_stream_handler_create },
{ &CLSID_WINEAudioConverter, &audio_converter_create },
- { &CLSID_MSH264DecoderMFT, &decode_transform_create },
+ { &CLSID_MSH264DecoderMFT, &h264_decoder_create },
};
HRESULT mfplat_get_class_object(REFCLSID rclsid, REFIID riid, void **obj)
--
2.34.1

View File

@ -1,57 +0,0 @@
From bfa940843cf60483a21e9dc135328d19f839f13a Mon Sep 17 00:00:00 2001
From: Derek Lesho <dlesho@codeweavers.com>
Date: Wed, 10 Mar 2021 14:23:09 -0500
Subject: [PATCH 17/88] 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.34.1

View File

@ -1,305 +0,0 @@
From 29aad7626e6a5bcdabdacb579ff3e9b707ed8452 Mon Sep 17 00:00:00 2001
From: Derek Lesho <dlesho@codeweavers.com>
Date: Thu, 11 Mar 2021 12:33:02 -0500
Subject: [PATCH 18/88] winegstreamer: Implement ::SetInputType for decode
transform.
Signed-off-by: Derek Lesho <dlesho@codeweavers.com>
---
dlls/winegstreamer/decode_transform.c | 80 ++++++++++++++++++++++++++-
dlls/winegstreamer/mfplat.c | 17 +++++-
dlls/winegstreamer/quartz_parser.c | 1 +
dlls/winegstreamer/unixlib.h | 10 ++++
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/mfplat.c b/dlls/winegstreamer/mfplat.c
index 93ddb90a070..4fe11b7b6b8 100644
--- a/dlls/winegstreamer/mfplat.c
+++ b/dlls/winegstreamer/mfplat.c
@@ -554,6 +554,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
@@ -741,10 +742,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 45313ebda27..0328b5ed4f5 100644
--- a/dlls/winegstreamer/quartz_parser.c
+++ b/dlls/winegstreamer/quartz_parser.c
@@ -271,6 +271,7 @@ unsigned int wg_format_get_max_size(const struct wg_format *format)
* but as long as every sample fits into our allocator, we're fine. */
return width * height * 3;
+ case WG_VIDEO_FORMAT_H264:
case WG_VIDEO_FORMAT_UNKNOWN:
FIXME("Cannot guess maximum sample size for unknown video format.\n");
return 0;
diff --git a/dlls/winegstreamer/unixlib.h b/dlls/winegstreamer/unixlib.h
index 82bb534b938..f3db631d16d 100644
--- a/dlls/winegstreamer/unixlib.h
+++ b/dlls/winegstreamer/unixlib.h
@@ -62,9 +62,19 @@ struct wg_format
WG_VIDEO_FORMAT_YVYU,
WG_VIDEO_FORMAT_CINEPAK,
+
+ WG_VIDEO_FORMAT_H264,
} format;
int32_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/wg_parser.c b/dlls/winegstreamer/wg_parser.c
index c6e8bbcb26b..c2141fae2af 100644
--- a/dlls/winegstreamer/wg_parser.c
+++ b/dlls/winegstreamer/wg_parser.c
@@ -406,6 +406,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];
@@ -447,6 +463,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:
+ GST_ERROR("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:
+ GST_ERROR("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;
@@ -655,6 +730,7 @@ static NTSTATUS wg_parser_stream_enable(void *args)
case WG_VIDEO_FORMAT_YVYU:
case WG_VIDEO_FORMAT_UNKNOWN:
case WG_VIDEO_FORMAT_CINEPAK:
+ case WG_VIDEO_FORMAT_H264:
break;
}
--
2.34.1

View File

@ -1,116 +0,0 @@
From 760c4df96ca2e4deb5c7c7e26fb81713a9393e5e Mon Sep 17 00:00:00 2001
From: Derek Lesho <dlesho@codeweavers.com>
Date: Thu, 11 Mar 2021 12:58:32 -0500
Subject: [PATCH 19/88] 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.34.1

View File

@ -1,106 +0,0 @@
From 372d42fdb36cef1e845eb8ac9d461d5f03974605 Mon Sep 17 00:00:00 2001
From: Derek Lesho <dlesho@codeweavers.com>
Date: Thu, 11 Mar 2021 14:40:32 -0500
Subject: [PATCH 20/88] 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.34.1

View File

@ -1,30 +0,0 @@
From 95e4c7c7d5de17f6635f7028b364cacbdadb2e58 Mon Sep 17 00:00:00 2001
From: Derek Lesho <dlesho@codeweavers.com>
Date: Fri, 19 Mar 2021 16:55:15 -0400
Subject: [PATCH 21/88] 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 dadd161bcc9..fb282d850ff 100644
--- a/dlls/winegstreamer/decode_transform.c
+++ b/dlls/winegstreamer/decode_transform.c
@@ -216,9 +216,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.34.1

View File

@ -1,56 +0,0 @@
From 8f392bb6b5de063a22fbb9ceb6e77a8f49bd7745 Mon Sep 17 00:00:00 2001
From: Derek Lesho <dlesho@codeweavers.com>
Date: Fri, 19 Mar 2021 16:57:11 -0400
Subject: [PATCH 22/88] 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 4fe11b7b6b8..a4494822500 100644
--- a/dlls/winegstreamer/mfplat.c
+++ b/dlls/winegstreamer/mfplat.c
@@ -463,6 +463,20 @@ static const GUID *const wma_decoder_output_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;
@@ -499,6 +513,17 @@ mfts[] =
ARRAY_SIZE(wma_decoder_output_types),
wma_decoder_output_types,
},
+ {
+ &CLSID_MSH264DecoderMFT,
+ &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.34.1

View File

@ -1,214 +0,0 @@
From 8234bc8886ba39e341ff4c771ac41f5529d67088 Mon Sep 17 00:00:00 2001
From: Derek Lesho <dlesho@codeweavers.com>
Date: Fri, 19 Mar 2021 16:59:29 -0400
Subject: [PATCH 23/88] winegstreamer: Introduce AAC decoder transform.
Signed-off-by: Derek Lesho <dlesho@codeweavers.com>
---
dlls/winegstreamer/decode_transform.c | 10 ++++
dlls/winegstreamer/gst_private.h | 1 +
dlls/winegstreamer/mfplat.c | 58 +++++++++++++++++++-
dlls/winegstreamer/quartz_parser.c | 2 +
dlls/winegstreamer/unixlib.h | 16 ++++++
dlls/winegstreamer/winegstreamer_classes.idl | 6 ++
6 files changed, 92 insertions(+), 1 deletion(-)
diff --git a/dlls/winegstreamer/decode_transform.c b/dlls/winegstreamer/decode_transform.c
index fb282d850ff..4967fc49012 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 mf_decoder
diff --git a/dlls/winegstreamer/gst_private.h b/dlls/winegstreamer/gst_private.h
index b9379487ac2..73d5e88b164 100644
--- a/dlls/winegstreamer/gst_private.h
+++ b/dlls/winegstreamer/gst_private.h
@@ -122,6 +122,7 @@ HRESULT audio_converter_create(REFIID riid, void **ret);
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 a4494822500..e22cd51c8a9 100644
--- a/dlls/winegstreamer/mfplat.c
+++ b/dlls/winegstreamer/mfplat.c
@@ -414,6 +414,7 @@ class_objects[] =
{ &CLSID_GStreamerByteStreamHandler, &winegstreamer_stream_handler_create },
{ &CLSID_WINEAudioConverter, &audio_converter_create },
{ &CLSID_MSH264DecoderMFT, &h264_decoder_create },
+ { &CLSID_MSAACDecMFT, &aac_decoder_create },
};
HRESULT mfplat_get_class_object(REFCLSID rclsid, REFIID riid, void **obj)
@@ -620,7 +621,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);
IMFMediaType_SetUINT32(type, &MF_MT_ALL_SAMPLES_INDEPENDENT, TRUE);
IMFMediaType_SetUINT32(type, &MF_MT_AUDIO_BLOCK_ALIGNMENT, format->u.audio.channels * audio_formats[i].depth / 8);
@@ -710,6 +712,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");
@@ -722,6 +726,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 0328b5ed4f5..8ea9291904e 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:
@@ -313,6 +314,7 @@ unsigned int wg_format_get_max_size(const struct wg_format *format)
case WG_AUDIO_FORMAT_MPEG1_LAYER3:
return 40000;
+ case WG_AUDIO_FORMAT_AAC:
case WG_AUDIO_FORMAT_UNKNOWN:
FIXME("Cannot guess maximum sample size for unknown audio format.\n");
return 0;
diff --git a/dlls/winegstreamer/unixlib.h b/dlls/winegstreamer/unixlib.h
index f3db631d16d..d9c675ea873 100644
--- a/dlls/winegstreamer/unixlib.h
+++ b/dlls/winegstreamer/unixlib.h
@@ -92,11 +92,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;
};
diff --git a/dlls/winegstreamer/winegstreamer_classes.idl b/dlls/winegstreamer/winegstreamer_classes.idl
index 022f5f80980..630522f30b1 100644
--- a/dlls/winegstreamer/winegstreamer_classes.idl
+++ b/dlls/winegstreamer/winegstreamer_classes.idl
@@ -79,3 +79,9 @@ coclass CWMADecMediaObject {};
uuid(62ce7e72-4c71-4d20-b15d-452831a87d9d)
]
coclass CMSH264DecoderMFT { }
+
+[
+ threading(both),
+ uuid(32d186a7-218f-4c75-8876-dd77273a8999)
+]
+coclass CMSAACDecMFT { }
--
2.34.1

View File

@ -1,45 +0,0 @@
From 2b8e7b14bfb8ad19d767bb378b24869f574f04f5 Mon Sep 17 00:00:00 2001
From: Derek Lesho <dlesho@codeweavers.com>
Date: Fri, 19 Mar 2021 17:00:51 -0400
Subject: [PATCH 24/88] 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 c2141fae2af..1d34437318e 100644
--- a/dlls/winegstreamer/wg_parser.c
+++ b/dlls/winegstreamer/wg_parser.c
@@ -1196,7 +1196,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);
@@ -1753,7 +1753,7 @@ static gboolean src_event_cb(GstPad *pad, GstObject *parent, GstEvent *event)
static NTSTATUS wg_parser_connect(void *args)
{
- 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);
const struct wg_parser_connect_params *params = args;
struct wg_parser *parser = params->parser;
@@ -1772,7 +1772,7 @@ static NTSTATUS wg_parser_connect(void *args)
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.34.1

View File

@ -1,73 +0,0 @@
From 5eef24de0657d410169e9d6a3f0c62e7e1ebded3 Mon Sep 17 00:00:00 2001
From: Derek Lesho <dlesho@codeweavers.com>
Date: Wed, 17 Mar 2021 15:12:20 -0400
Subject: [PATCH 26/88] winegstreamer: Implement ::Get(Input/Output)StreamInfo
for audio conversion transform.
Signed-off-by: Derek Lesho <dlesho@codeweavers.com>
---
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 d5723cdf58f..56aa96770b7 100644
--- a/dlls/winegstreamer/audioconvert.c
+++ b/dlls/winegstreamer/audioconvert.c
@@ -115,16 +115,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, %lu, %p.\n", iface, id, info);
+ struct audio_converter *converter = impl_audio_converter_from_IMFTransform(iface);
- return E_NOTIMPL;
+ TRACE("%p, %lu, %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;
+ 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;
}
static HRESULT WINAPI audio_converter_GetOutputStreamInfo(IMFTransform *iface, DWORD id, MFT_OUTPUT_STREAM_INFO *info)
{
- FIXME("%p. %lu, %p.\n", iface, id, info);
+ struct audio_converter *converter = impl_audio_converter_from_IMFTransform(iface);
- return E_NOTIMPL;
+ TRACE("%p. %lu, %p.\n", iface, id, info);
+
+ if (id != 0)
+ return MF_E_INVALIDSTREAMNUMBER;
+
+ 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.34.1

View File

@ -1,101 +0,0 @@
From baf0a7e95e8601833e46769c16745d742431b1a4 Mon Sep 17 00:00:00 2001
From: Derek Lesho <dlesho@codeweavers.com>
Date: Wed, 17 Mar 2021 15:19:32 -0400
Subject: [PATCH 27/88] winegstreamer: Semi-stub Get*Attributes functions for
audio converter transform.
Signed-off-by: Derek Lesho <dlesho@codeweavers.com>
---
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 56aa96770b7..a4258c6aecd 100644
--- a/dlls/winegstreamer/audioconvert.c
+++ b/dlls/winegstreamer/audioconvert.c
@@ -35,6 +35,7 @@ struct audio_converter
IMFMediaType *input_type;
IMFMediaType *output_type;
CRITICAL_SECTION cs;
+ IMFAttributes *attributes, *output_attributes;
};
static struct audio_converter *impl_audio_converter_from_IMFTransform(IMFTransform *iface)
@@ -80,6 +81,10 @@ static ULONG WINAPI audio_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);
free(transform);
}
@@ -163,9 +168,14 @@ static HRESULT WINAPI audio_converter_GetOutputStreamInfo(IMFTransform *iface, D
static HRESULT WINAPI audio_converter_GetAttributes(IMFTransform *iface, IMFAttributes **attributes)
{
- FIXME("%p, %p.\n", iface, attributes);
+ struct audio_converter *converter = impl_audio_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 audio_converter_GetInputStreamAttributes(IMFTransform *iface, DWORD id,
@@ -179,9 +189,17 @@ static HRESULT WINAPI audio_converter_GetInputStreamAttributes(IMFTransform *ifa
static HRESULT WINAPI audio_converter_GetOutputStreamAttributes(IMFTransform *iface, DWORD id,
IMFAttributes **attributes)
{
- FIXME("%p, %lu, %p.\n", iface, id, attributes);
+ struct audio_converter *converter = impl_audio_converter_from_IMFTransform(iface);
- return E_NOTIMPL;
+ TRACE("%p, %lu, %p.\n", iface, id, attributes);
+
+ if (id != 0)
+ return MF_E_INVALIDSTREAMNUMBER;
+
+ *attributes = converter->output_attributes;
+ IMFAttributes_AddRef(*attributes);
+
+ return S_OK;
}
static HRESULT WINAPI audio_converter_DeleteInputStream(IMFTransform *iface, DWORD id)
@@ -601,6 +619,7 @@ static const IMFTransformVtbl audio_converter_vtbl =
HRESULT audio_converter_create(REFIID riid, void **ret)
{
struct audio_converter *object;
+ HRESULT hr;
TRACE("%s %p\n", debugstr_guid(riid), ret);
@@ -613,6 +632,18 @@ HRESULT audio_converter_create(REFIID riid, void **ret)
InitializeCriticalSection(&object->cs);
object->cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": audio_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;
+ }
+
*ret = &object->IMFTransform_iface;
return S_OK;
}
--
2.34.1

View File

@ -1,388 +0,0 @@
From aec53333c8c27975efa46d99d8e87cd91d93ec33 Mon Sep 17 00:00:00 2001
From: Derek Lesho <dlesho@codeweavers.com>
Date: Wed, 17 Mar 2021 15:35:20 -0400
Subject: [PATCH 28/88] winegstreamer: Introduce color conversion transform.
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 | 298 +++++++++++++++++++
dlls/winegstreamer/gst_private.h | 1 +
dlls/winegstreamer/mfplat.c | 1 +
dlls/winegstreamer/winegstreamer_classes.idl | 6 +
include/wmcodecdsp.idl | 5 +
6 files changed, 312 insertions(+)
create mode 100644 dlls/winegstreamer/colorconvert.c
diff --git a/dlls/winegstreamer/Makefile.in b/dlls/winegstreamer/Makefile.in
index 3da8c614ed2..74bcc35364b 100644
--- a/dlls/winegstreamer/Makefile.in
+++ b/dlls/winegstreamer/Makefile.in
@@ -8,6 +8,7 @@ EXTRALIBS = $(GSTREAMER_LIBS) $(PTHREAD_LIBS)
C_SRCS = \
audioconvert.c \
+ colorconvert.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..1f0d061a30c
--- /dev/null
+++ b/dlls/winegstreamer/colorconvert.c
@@ -0,0 +1,298 @@
+/* GStreamer Color Converter
+ *
+ * Copyright 2020 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 "wine/debug.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(mfplat);
+
+struct color_converter
+{
+ IMFTransform IMFTransform_iface;
+ LONG refcount;
+};
+
+static struct color_converter *impl_color_converter_from_IMFTransform(IMFTransform *iface)
+{
+ return CONTAINING_RECORD(iface, struct color_converter, IMFTransform_iface);
+}
+
+static HRESULT WINAPI color_converter_QueryInterface(IMFTransform *iface, REFIID riid, void **obj)
+{
+ TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), obj);
+
+ if (IsEqualGUID(riid, &IID_IMFTransform) ||
+ IsEqualGUID(riid, &IID_IUnknown))
+ {
+ *obj = iface;
+ IMFTransform_AddRef(iface);
+ return S_OK;
+ }
+
+ WARN("Unsupported %s.\n", debugstr_guid(riid));
+ *obj = NULL;
+ return E_NOINTERFACE;
+}
+
+static ULONG WINAPI color_converter_AddRef(IMFTransform *iface)
+{
+ struct color_converter *transform = impl_color_converter_from_IMFTransform(iface);
+ ULONG refcount = InterlockedIncrement(&transform->refcount);
+
+ TRACE("%p, refcount %u.\n", iface, refcount);
+
+ return refcount;
+}
+
+static ULONG WINAPI color_converter_Release(IMFTransform *iface)
+{
+ struct color_converter *transform = impl_color_converter_from_IMFTransform(iface);
+ ULONG refcount = InterlockedDecrement(&transform->refcount);
+
+ TRACE("%p, refcount %u.\n", iface, refcount);
+
+ if (!refcount)
+ {
+ free(transform);
+ }
+
+ return refcount;
+}
+
+static HRESULT WINAPI color_converter_GetStreamLimits(IMFTransform *iface, DWORD *input_minimum, DWORD *input_maximum,
+ DWORD *output_minimum, DWORD *output_maximum)
+{
+ TRACE("%p, %p, %p, %p, %p.\n", iface, input_minimum, input_maximum, output_minimum, output_maximum);
+
+ *input_minimum = *input_maximum = *output_minimum = *output_maximum = 1;
+
+ return S_OK;
+}
+
+static HRESULT WINAPI color_converter_GetStreamCount(IMFTransform *iface, DWORD *inputs, DWORD *outputs)
+{
+ TRACE("%p, %p, %p.\n", iface, inputs, outputs);
+
+ *inputs = *outputs = 1;
+
+ return S_OK;
+}
+
+static HRESULT WINAPI color_converter_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 color_converter_GetInputStreamInfo(IMFTransform *iface, DWORD id, MFT_INPUT_STREAM_INFO *info)
+{
+ FIXME("%p %u %p.\n", iface, id, info);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI color_converter_GetOutputStreamInfo(IMFTransform *iface, DWORD id, MFT_OUTPUT_STREAM_INFO *info)
+{
+ FIXME("%p %u %p.\n", iface, id, info);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI color_converter_GetAttributes(IMFTransform *iface, IMFAttributes **attributes)
+{
+ FIXME("%p, %p.\n", iface, attributes);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI color_converter_GetInputStreamAttributes(IMFTransform *iface, DWORD id,
+ IMFAttributes **attributes)
+{
+ FIXME("%p, %u, %p.\n", iface, id, attributes);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI color_converter_GetOutputStreamAttributes(IMFTransform *iface, DWORD id,
+ IMFAttributes **attributes)
+{
+ FIXME("%p, %u, %p.\n", iface, id, attributes);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI color_converter_DeleteInputStream(IMFTransform *iface, DWORD id)
+{
+ TRACE("%p, %u.\n", iface, id);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI color_converter_AddInputStreams(IMFTransform *iface, DWORD streams, DWORD *ids)
+{
+ TRACE("%p, %u, %p.\n", iface, streams, ids);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI color_converter_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 color_converter_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 color_converter_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 color_converter_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 color_converter_GetInputCurrentType(IMFTransform *iface, DWORD id, IMFMediaType **type)
+{
+ FIXME("%p, %u, %p.\n", iface, id, type);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI color_converter_GetOutputCurrentType(IMFTransform *iface, DWORD id, IMFMediaType **type)
+{
+ FIXME("%p, %u, %p.\n", iface, id, type);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI color_converter_GetInputStatus(IMFTransform *iface, DWORD id, DWORD *flags)
+{
+ FIXME("%p, %u, %p.\n", iface, id, flags);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI color_converter_GetOutputStatus(IMFTransform *iface, DWORD *flags)
+{
+ FIXME("%p, %p.\n", iface, flags);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI color_converter_SetOutputBounds(IMFTransform *iface, LONGLONG lower, LONGLONG upper)
+{
+ FIXME("%p, %s, %s.\n", iface, wine_dbgstr_longlong(lower), wine_dbgstr_longlong(upper));
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI color_converter_ProcessEvent(IMFTransform *iface, DWORD id, IMFMediaEvent *event)
+{
+ TRACE("%p, %u, %p.\n", iface, id, event);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI color_converter_ProcessMessage(IMFTransform *iface, MFT_MESSAGE_TYPE message, ULONG_PTR param)
+{
+ FIXME("%p, %u %lu.\n", iface, message, param);
+
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI color_converter_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 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);
+
+ return E_NOTIMPL;
+}
+
+static const IMFTransformVtbl color_converter_vtbl =
+{
+ color_converter_QueryInterface,
+ color_converter_AddRef,
+ color_converter_Release,
+ color_converter_GetStreamLimits,
+ color_converter_GetStreamCount,
+ color_converter_GetStreamIDs,
+ color_converter_GetInputStreamInfo,
+ color_converter_GetOutputStreamInfo,
+ color_converter_GetAttributes,
+ color_converter_GetInputStreamAttributes,
+ color_converter_GetOutputStreamAttributes,
+ color_converter_DeleteInputStream,
+ color_converter_AddInputStreams,
+ color_converter_GetInputAvailableType,
+ color_converter_GetOutputAvailableType,
+ color_converter_SetInputType,
+ color_converter_SetOutputType,
+ color_converter_GetInputCurrentType,
+ color_converter_GetOutputCurrentType,
+ color_converter_GetInputStatus,
+ color_converter_GetOutputStatus,
+ color_converter_SetOutputBounds,
+ color_converter_ProcessEvent,
+ color_converter_ProcessMessage,
+ color_converter_ProcessInput,
+ color_converter_ProcessOutput,
+};
+
+HRESULT color_converter_create(REFIID riid, void **ret)
+{
+ struct color_converter *object;
+
+ TRACE("%s %p\n", debugstr_guid(riid), ret);
+
+ if (!(object = calloc(1, sizeof(*object))))
+ return E_OUTOFMEMORY;
+
+ object->IMFTransform_iface.lpVtbl = &color_converter_vtbl;
+ object->refcount = 1;
+
+ *ret = &object->IMFTransform_iface;
+ return S_OK;
+}
diff --git a/dlls/winegstreamer/gst_private.h b/dlls/winegstreamer/gst_private.h
index 73d5e88b164..d3271518f8f 100644
--- a/dlls/winegstreamer/gst_private.h
+++ b/dlls/winegstreamer/gst_private.h
@@ -118,6 +118,7 @@ void mf_media_type_to_wg_format(IMFMediaType *type, struct wg_format *format);
HRESULT winegstreamer_stream_handler_create(REFIID riid, void **obj);
HRESULT audio_converter_create(REFIID riid, void **ret);
+HRESULT color_converter_create(REFIID riid, void **ret);
enum decoder_type
{
diff --git a/dlls/winegstreamer/mfplat.c b/dlls/winegstreamer/mfplat.c
index e22cd51c8a9..6f6ec956b2b 100644
--- a/dlls/winegstreamer/mfplat.c
+++ b/dlls/winegstreamer/mfplat.c
@@ -413,6 +413,7 @@ class_objects[] =
{ &CLSID_VideoProcessorMFT, &video_processor_create },
{ &CLSID_GStreamerByteStreamHandler, &winegstreamer_stream_handler_create },
{ &CLSID_WINEAudioConverter, &audio_converter_create },
+ { &CLSID_CColorConvertDMO, &color_converter_create },
{ &CLSID_MSH264DecoderMFT, &h264_decoder_create },
{ &CLSID_MSAACDecMFT, &aac_decoder_create },
};
diff --git a/dlls/winegstreamer/winegstreamer_classes.idl b/dlls/winegstreamer/winegstreamer_classes.idl
index 630522f30b1..5762430a5cd 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(98230571-0087-4204-b020-3282538e57d3)
+]
+coclass CColorConvertDMO { }
diff --git a/include/wmcodecdsp.idl b/include/wmcodecdsp.idl
index ae2a42419b4..711179fe1d2 100644
--- a/include/wmcodecdsp.idl
+++ b/include/wmcodecdsp.idl
@@ -49,3 +49,8 @@ coclass CWMADecMediaObject {};
uuid(93af0c51-2275-45d2-a35b-f2ba21caed00)
]
coclass AACMFTEncoder {};
+
+[
+ uuid(98230571-0087-4204-b020-3282538e57d3)
+]
+coclass CColorConvertDMO {}
--
2.34.1

View File

@ -1,81 +0,0 @@
From e0a8b0048e9507ad457cb6b3b9a535331528dd71 Mon Sep 17 00:00:00 2001
From: Derek Lesho <dlesho@codeweavers.com>
Date: Wed, 17 Mar 2021 15:41:33 -0400
Subject: [PATCH 30/88] winegstreamer: Implement ::GetInputAvailableType 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 1f0d061a30c..078782daaed 100644
--- a/dlls/winegstreamer/colorconvert.c
+++ b/dlls/winegstreamer/colorconvert.c
@@ -26,6 +26,24 @@
WINE_DEFAULT_DEBUG_CHANNEL(mfplat);
+static const GUID *raw_types[] = {
+ &MFVideoFormat_RGB24,
+ &MFVideoFormat_RGB32,
+ &MFVideoFormat_RGB555,
+ &MFVideoFormat_RGB8,
+ &MFVideoFormat_AYUV,
+ &MFVideoFormat_I420,
+ &MFVideoFormat_IYUV,
+ &MFVideoFormat_NV11,
+ &MFVideoFormat_NV12,
+ &MFVideoFormat_UYVY,
+ &MFVideoFormat_v216,
+ &MFVideoFormat_v410,
+ &MFVideoFormat_YUY2,
+ &MFVideoFormat_YVYU,
+ &MFVideoFormat_YVYU,
+};
+
struct color_converter
{
IMFTransform IMFTransform_iface;
@@ -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)
{
- FIXME("%p, %u, %u, %p.\n", iface, id, index, type);
+ 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;
+
+ 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_GetOutputAvailableType(IMFTransform *iface, DWORD id, DWORD index,
--
2.34.1

View File

@ -1,122 +0,0 @@
From c396ea3ccf731d454fddb3a3f7c8e04dc0e5be8b Mon Sep 17 00:00:00 2001
From: Derek Lesho <dlesho@codeweavers.com>
Date: Wed, 17 Mar 2021 16:01:18 -0400
Subject: [PATCH 31/88] winegstreamer: Implement ::SetInputType for color
conversion transform.
Signed-off-by: Derek Lesho <dlesho@codeweavers.com>
---
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 078782daaed..06186ed7846 100644
--- a/dlls/winegstreamer/colorconvert.c
+++ b/dlls/winegstreamer/colorconvert.c
@@ -48,6 +48,8 @@ struct color_converter
{
IMFTransform IMFTransform_iface;
LONG refcount;
+ IMFMediaType *input_type;
+ CRITICAL_SECTION cs;
};
static struct color_converter *impl_color_converter_from_IMFTransform(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);
free(transform);
}
@@ -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);
+ struct color_converter *converter = impl_color_converter_from_IMFTransform(iface);
+ 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->input_type)
+ {
+ IMFMediaType_Release(converter->input_type);
+ converter->input_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;
+
+ if (flags & MFT_SET_TYPE_TEST_ONLY)
+ return S_OK;
+
+ EnterCriticalSection(&converter->cs);
+
+ hr = S_OK;
+
+ if (!converter->input_type)
+ hr = MFCreateMediaType(&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;
+ }
+
+ LeaveCriticalSection(&converter->cs);
+
+ return hr;
}
static HRESULT WINAPI color_converter_SetOutputType(IMFTransform *iface, DWORD id, IMFMediaType *type, DWORD flags)
@@ -337,6 +405,9 @@ HRESULT color_converter_create(REFIID riid, void **ret)
object->IMFTransform_iface.lpVtbl = &color_converter_vtbl;
object->refcount = 1;
+ InitializeCriticalSection(&object->cs);
+ object->cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": color_converter_lock");
+
*ret = &object->IMFTransform_iface;
return S_OK;
}
--
2.34.1

View File

@ -1,64 +0,0 @@
From c5ccac06781882e1debd710e2f0c3e1aaf46565a Mon Sep 17 00:00:00 2001
From: Derek Lesho <dlesho@codeweavers.com>
Date: Wed, 17 Mar 2021 16:04:31 -0400
Subject: [PATCH 32/88] 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.34.1

View File

@ -1,153 +0,0 @@
From 75d114aad6addbf24d1ecc22ca223aae02586b9c Mon Sep 17 00:00:00 2001
From: Derek Lesho <dlesho@codeweavers.com>
Date: Wed, 17 Mar 2021 16:26:28 -0400
Subject: [PATCH 33/88] 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.34.1

View File

@ -1,38 +0,0 @@
From 112153e5fd44f225c80b6abbec0bffa36da0bbf3 Mon Sep 17 00:00:00 2001
From: Derek Lesho <dlesho@codeweavers.com>
Date: Wed, 17 Mar 2021 16:50:47 -0400
Subject: [PATCH 34/88] winegstreamer: Implement ::ProcessMessage for color
conversion MFT.
Signed-off-by: Derek Lesho <dlesho@codeweavers.com>
---
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 e001c6c827e..0e8980659a5 100644
--- a/dlls/winegstreamer/colorconvert.c
+++ b/dlls/winegstreamer/colorconvert.c
@@ -472,9 +472,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)
{
- FIXME("%p, %u %lu.\n", iface, message, param);
+ TRACE("%p, %u %lu.\n", iface, message, param);
- return E_NOTIMPL;
+ switch(message)
+ {
+ case MFT_MESSAGE_COMMAND_FLUSH:
+ case MFT_MESSAGE_NOTIFY_BEGIN_STREAMING:
+ return S_OK;
+ default:
+ FIXME("Unhandled message type %x.\n", message);
+ return E_NOTIMPL;
+ }
}
static HRESULT WINAPI color_converter_ProcessInput(IMFTransform *iface, DWORD id, IMFSample *sample, DWORD flags)
--
2.34.1

View File

@ -1,95 +0,0 @@
From 6a2f654147260fa022d1f045506dd4ed5c6ec1e4 Mon Sep 17 00:00:00 2001
From: Derek Lesho <dlesho@codeweavers.com>
Date: Wed, 17 Mar 2021 17:01:11 -0400
Subject: [PATCH 35/88] 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 0e8980659a5..db4ca4e3fbe 100644
--- a/dlls/winegstreamer/colorconvert.c
+++ b/dlls/winegstreamer/colorconvert.c
@@ -133,16 +133,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.34.1

View File

@ -1,26 +0,0 @@
From 7dad9c2c92351194857e9722a0dd72d280abac0f Mon Sep 17 00:00:00 2001
From: Derek Lesho <dlesho@codeweavers.com>
Date: Thu, 18 Mar 2021 14:53:49 -0400
Subject: [PATCH 37/88] 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 a4258c6aecd..afa6bd682a6 100644
--- a/dlls/winegstreamer/audioconvert.c
+++ b/dlls/winegstreamer/audioconvert.c
@@ -563,6 +563,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.34.1

View File

@ -1,54 +0,0 @@
From fc96686a97ff86e036a4324299392c66250a77fc Mon Sep 17 00:00:00 2001
From: Andrew Eikum <aeikum@codeweavers.com>
Date: Mon, 18 Oct 2021 12:29:34 -0500
Subject: [PATCH 39/88] winegstreamer: Implement
IMFTransform::GetOutputCurrentType in colorconvert
CW-Bug-Id: #19465
---
dlls/winegstreamer/colorconvert.c | 28 ++++++++++++++++++++++++++--
1 file changed, 26 insertions(+), 2 deletions(-)
diff --git a/dlls/winegstreamer/colorconvert.c b/dlls/winegstreamer/colorconvert.c
index db4ca4e3fbe..baf429d42f9 100644
--- a/dlls/winegstreamer/colorconvert.c
+++ b/dlls/winegstreamer/colorconvert.c
@@ -493,9 +493,33 @@ static HRESULT WINAPI color_converter_GetInputCurrentType(IMFTransform *iface, D
static HRESULT WINAPI color_converter_GetOutputCurrentType(IMFTransform *iface, DWORD id, IMFMediaType **type)
{
- FIXME("%p, %u, %p.\n", iface, id, type);
+ struct color_converter *converter = impl_color_converter_from_IMFTransform(iface);
+ IMFMediaType *ret;
+ HRESULT hr;
- return E_NOTIMPL;
+ 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.34.1

View File

@ -1,178 +0,0 @@
From 5f724ac4f148607141e93868ba97edb4c0135cbd Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?R=C3=A9mi=20Bernon?= <rbernon@codeweavers.com>
Date: Tue, 14 Dec 2021 22:31:29 +0100
Subject: [PATCH 40/88] winegstreamer: Implement stream draining support.
---
dlls/winegstreamer/gst_private.h | 1 +
dlls/winegstreamer/main.c | 5 +++
dlls/winegstreamer/unixlib.h | 2 +
dlls/winegstreamer/wg_parser.c | 70 +++++++++++++++++++++++++++++++-
4 files changed, 77 insertions(+), 1 deletion(-)
diff --git a/dlls/winegstreamer/gst_private.h b/dlls/winegstreamer/gst_private.h
index d3271518f8f..6149ae5959c 100644
--- a/dlls/winegstreamer/gst_private.h
+++ b/dlls/winegstreamer/gst_private.h
@@ -95,6 +95,7 @@ uint64_t wg_parser_stream_get_duration(struct wg_parser_stream *stream);
/* start_pos and stop_pos are in 100-nanosecond units. */
void 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);
+bool wg_parser_stream_drain(struct wg_parser_stream *stream);
unsigned int wg_format_get_max_size(const struct wg_format *format);
diff --git a/dlls/winegstreamer/main.c b/dlls/winegstreamer/main.c
index 8f487655748..66b7a1195ee 100644
--- a/dlls/winegstreamer/main.c
+++ b/dlls/winegstreamer/main.c
@@ -254,6 +254,11 @@ void wg_parser_stream_seek(struct wg_parser_stream *stream, double rate,
__wine_unix_call(unix_handle, unix_wg_parser_stream_seek, &params);
}
+bool wg_parser_stream_drain(struct wg_parser_stream *stream)
+{
+ return !__wine_unix_call(unix_handle, unix_wg_parser_stream_drain, stream);
+}
+
BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, void *reserved)
{
if (reason == DLL_PROCESS_ATTACH)
diff --git a/dlls/winegstreamer/unixlib.h b/dlls/winegstreamer/unixlib.h
index d9c675ea873..fc9d0c3c80d 100644
--- a/dlls/winegstreamer/unixlib.h
+++ b/dlls/winegstreamer/unixlib.h
@@ -271,6 +271,8 @@ enum unix_funcs
unix_wg_parser_stream_get_duration,
unix_wg_parser_stream_seek,
+
+ unix_wg_parser_stream_drain,
};
#endif /* __WINE_WINEGSTREAMER_UNIXLIB_H */
diff --git a/dlls/winegstreamer/wg_parser.c b/dlls/winegstreamer/wg_parser.c
index 1d34437318e..f70c1a449c7 100644
--- a/dlls/winegstreamer/wg_parser.c
+++ b/dlls/winegstreamer/wg_parser.c
@@ -87,7 +87,7 @@ struct wg_parser
GstFlowReturn ret;
} read_request;
- bool flushing, sink_connected;
+ bool flushing, sink_connected, draining;
bool unlimited_buffering;
};
@@ -769,6 +769,16 @@ static NTSTATUS wg_parser_stream_get_event(void *args)
*params->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;
+
+ /* 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;
@@ -859,6 +869,44 @@ static NTSTATUS wg_parser_stream_seek(void *args)
return S_OK;
}
+static NTSTATUS wg_parser_stream_drain(void *args)
+{
+ struct wg_parser_stream *stream = args;
+ 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 NTSTATUS wg_parser_stream_notify_qos(void *args)
{
const struct wg_parser_stream_notify_qos_params *params = args;
@@ -1431,6 +1479,7 @@ static GstFlowReturn src_getrange_cb(GstPad *pad, GstObject *parent,
{
struct wg_parser *parser = gst_pad_get_element_private(pad);
GstFlowReturn ret;
+ unsigned int i;
GST_LOG("pad %p, offset %" G_GINT64_MODIFIER "u, size %u, buffer %p.", pad, offset, size, *buffer);
@@ -1452,6 +1501,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.size);
parser->read_request.buffer = *buffer;
parser->read_request.offset = offset;
@@ -1464,7 +1521,16 @@ static GstFlowReturn src_getrange_cb(GstPad *pad, GstObject *parent,
* read_thread() not running. */
while (!parser->read_request.done)
+ {
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);
+ }
+ }
*buffer = parser->read_request.buffer;
ret = parser->read_request.ret;
@@ -2208,4 +2274,6 @@ const unixlib_entry_t __wine_unix_call_funcs[] =
X(wg_parser_stream_get_duration),
X(wg_parser_stream_seek),
+
+ X(wg_parser_stream_drain),
};
--
2.34.1

View File

@ -1,436 +0,0 @@
From 7a63ae845a7d1d630ae838ddebc25a20c54df889 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?R=C3=A9mi=20Bernon?= <rbernon@codeweavers.com>
Date: Wed, 15 Dec 2021 10:25:48 +0100
Subject: [PATCH 45/88] winegstreamer: Implement unseekable stream support.
---
dlls/winegstreamer/gst_private.h | 2 +
dlls/winegstreamer/main.c | 14 +++
dlls/winegstreamer/unixlib.h | 9 ++
dlls/winegstreamer/wg_parser.c | 197 ++++++++++++++++++++++++++++---
4 files changed, 203 insertions(+), 19 deletions(-)
diff --git a/dlls/winegstreamer/gst_private.h b/dlls/winegstreamer/gst_private.h
index c156d87450c..6e7c53782c8 100644
--- a/dlls/winegstreamer/gst_private.h
+++ b/dlls/winegstreamer/gst_private.h
@@ -68,6 +68,8 @@ struct wg_parser *wg_parser_create(enum wg_parser_type type, bool unlimited_buff
void wg_parser_destroy(struct wg_parser *parser);
HRESULT wg_parser_connect(struct wg_parser *parser, uint64_t file_size);
+HRESULT wg_parser_connect_unseekable(struct wg_parser *parser, const struct wg_format *in_format,
+ uint32_t stream_count, const struct wg_format *out_formats);
void wg_parser_disconnect(struct wg_parser *parser);
void wg_parser_begin_flush(struct wg_parser *parser);
diff --git a/dlls/winegstreamer/main.c b/dlls/winegstreamer/main.c
index db05594f464..316becdbc97 100644
--- a/dlls/winegstreamer/main.c
+++ b/dlls/winegstreamer/main.c
@@ -91,6 +91,20 @@ HRESULT wg_parser_connect(struct wg_parser *parser, uint64_t file_size)
return __wine_unix_call(unix_handle, unix_wg_parser_connect, &params);
}
+HRESULT wg_parser_connect_unseekable(struct wg_parser *parser, const struct wg_format *in_format,
+ uint32_t stream_count, const struct wg_format *out_formats)
+{
+ struct wg_parser_connect_unseekable_params params =
+ {
+ .parser = parser,
+ .in_format = in_format,
+ .stream_count = stream_count,
+ .out_formats = out_formats,
+ };
+
+ return __wine_unix_call(unix_handle, unix_wg_parser_connect_unseekable, &params);
+}
+
void wg_parser_disconnect(struct wg_parser *parser)
{
__wine_unix_call(unix_handle, unix_wg_parser_disconnect, parser);
diff --git a/dlls/winegstreamer/unixlib.h b/dlls/winegstreamer/unixlib.h
index f20ee5bb52f..e5d87716734 100644
--- a/dlls/winegstreamer/unixlib.h
+++ b/dlls/winegstreamer/unixlib.h
@@ -175,6 +175,14 @@ struct wg_parser_connect_params
UINT64 file_size;
};
+struct wg_parser_connect_unseekable_params
+{
+ struct wg_parser *parser;
+ const struct wg_format *in_format;
+ UINT32 stream_count;
+ const struct wg_format *out_formats;
+};
+
struct wg_parser_get_next_read_offset_params
{
struct wg_parser *parser;
@@ -258,6 +266,7 @@ enum unix_funcs
unix_wg_parser_destroy,
unix_wg_parser_connect,
+ unix_wg_parser_connect_unseekable,
unix_wg_parser_disconnect,
unix_wg_parser_begin_flush,
diff --git a/dlls/winegstreamer/wg_parser.c b/dlls/winegstreamer/wg_parser.c
index 0b67a6836c4..ab850b899f3 100644
--- a/dlls/winegstreamer/wg_parser.c
+++ b/dlls/winegstreamer/wg_parser.c
@@ -61,7 +61,7 @@ struct wg_parser
init_gst_cb init_gst;
struct wg_parser_stream **streams;
- unsigned int stream_count;
+ unsigned int stream_count, expected_stream_count;
GstElement *container, *decodebin;
GstBus *bus;
@@ -75,7 +75,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
@@ -90,6 +90,7 @@ struct wg_parser
bool flushing, sink_connected, draining;
bool unlimited_buffering;
+ struct wg_format input_format;
};
struct wg_parser_stream
@@ -600,6 +601,9 @@ static NTSTATUS wg_parser_begin_flush(void *args)
struct wg_parser *parser = args;
unsigned int i;
+ if (!parser->seekable)
+ return S_OK;
+
pthread_mutex_lock(&parser->mutex);
parser->flushing = true;
pthread_mutex_unlock(&parser->mutex);
@@ -617,6 +621,9 @@ static NTSTATUS wg_parser_end_flush(void *args)
{
struct wg_parser *parser = args;
+ if (!parser->seekable)
+ return S_OK;
+
pthread_mutex_lock(&parser->mutex);
parser->flushing = false;
pthread_mutex_unlock(&parser->mutex);
@@ -711,7 +718,9 @@ static NTSTATUS wg_parser_stream_get_preferred_format(void *args)
{
const struct wg_parser_stream_get_preferred_format_params *params = args;
- *params->format = params->stream->preferred_format;
+ if (params->stream->has_caps)
+ *params->format = params->stream->preferred_format;
+
return S_OK;
}
@@ -721,6 +730,9 @@ static NTSTATUS wg_parser_stream_enable(void *args)
struct wg_parser_stream *stream = params->stream;
const struct wg_format *format = params->format;
+ if (!stream->parser->seekable)
+ return S_OK;
+
stream->current_format = *format;
stream->enabled = true;
@@ -867,6 +879,9 @@ static NTSTATUS wg_parser_stream_seek(void *args)
DWORD stop_flags = params->stop_flags;
GstSeekFlags flags = 0;
+ if (!params->stream->parser->seekable)
+ return E_FAIL;
+
if (start_flags & AM_SEEKING_SeekToKeyFrame)
flags |= GST_SEEK_FLAG_KEY_UNIT;
if (start_flags & AM_SEEKING_Segment)
@@ -1246,14 +1261,27 @@ static GstElement *create_element(const char *name, const char *plugin_set)
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);
@@ -1575,7 +1603,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;
@@ -1589,15 +1617,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;
@@ -1607,16 +1662,31 @@ static gboolean src_query_cb(GstPad *pad, GstObject *parent, GstQuery *query)
static void *push_data(void *arg)
{
struct wg_parser *parser = arg;
+ ULONG alloc_size = 16384;
+ GstCaps *caps = NULL;
GstSegment *segment;
GstBuffer *buffer;
+ unsigned int i;
guint max_size;
GST_DEBUG("Starting push thread.");
+ if (parser->input_format.major_type)
+ caps = wg_format_to_caps(&parser->input_format);
+
+ if (parser->input_format.major_type == WG_MAJOR_TYPE_VIDEO)
+ {
+ GstVideoInfo info;
+ gst_video_info_from_caps(&info, caps);
+ alloc_size = info.size;
+ }
+
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 (caps) gst_pad_push_event(parser->my_src, gst_event_new_caps(caps));
+
segment = gst_segment_new();
gst_segment_init(segment, GST_FORMAT_BYTES);
gst_pad_push_event(parser->my_src, gst_event_new_segment(segment));
@@ -1626,13 +1696,47 @@ 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(16384, max_size - parser->next_offset);
+ size = parser->seekable ? min(alloc_size, max_size - parser->next_offset) : alloc_size;
buffer = NULL;
- if ((ret = src_getrange_cb(parser->my_src, NULL, parser->next_offset, size, &buffer)) < 0)
+ if ((ret = src_getrange_cb(parser->my_src, NULL, parser->next_offset, size, &buffer) < 0))
{
+ /* When we are in unseekable push mode, the pushing pad is responsible for handling flushing. */
+ if (!parser->seekable && ret == GST_FLOW_FLUSHING)
+ {
+ 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)
+ {
+ 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;
+ }
+
GST_ERROR("Failed to read data, ret %s.", gst_flow_get_name(ret));
break;
}
@@ -1827,16 +1931,11 @@ static gboolean src_event_cb(GstPad *pad, GstObject *parent, GstEvent *event)
return ret;
}
-static NTSTATUS wg_parser_connect(void *args)
+static HRESULT wg_parser_connect_inner(struct wg_parser *parser)
{
GstStaticPadTemplate src_template = GST_STATIC_PAD_TEMPLATE("wine_src",
GST_PAD_SRC, GST_PAD_ALWAYS, GST_STATIC_CAPS_ANY);
- const struct wg_parser_connect_params *params = args;
- struct wg_parser *parser = params->parser;
- unsigned int i;
- int ret;
- parser->file_size = params->file_size;
parser->sink_connected = true;
if (!parser->bus)
@@ -1859,6 +1958,23 @@ static NTSTATUS wg_parser_connect(void *args)
parser->next_pull_offset = 0;
parser->error = false;
+ return S_OK;
+}
+
+static NTSTATUS wg_parser_connect(void *args)
+{
+ const struct wg_parser_connect_params *params = args;
+ struct wg_parser *parser = params->parser;
+ unsigned int i;
+ HRESULT hr;
+ int ret;
+
+ parser->seekable = true;
+ parser->file_size = params->file_size;
+
+ if ((hr = wg_parser_connect_inner(parser)))
+ return hr;
+
if (!parser->init_gst(parser))
goto out;
@@ -1988,6 +2104,45 @@ out:
return E_FAIL;
}
+static NTSTATUS wg_parser_connect_unseekable(void *args)
+{
+ const struct wg_parser_connect_unseekable_params *params = args;
+ const struct wg_format *out_formats = params->out_formats;
+ const struct wg_format *in_format = params->in_format;
+ uint32_t stream_count = params->stream_count;
+ struct wg_parser *parser = params->parser;
+ 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];
+ 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 NTSTATUS wg_parser_disconnect(void *args)
{
struct wg_parser *parser = args;
@@ -2037,6 +2192,9 @@ static BOOL decodebin_parser_init_gst(struct wg_parser *parser)
if (!(element = create_element("decodebin", "base")))
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;
@@ -2262,6 +2420,7 @@ const unixlib_entry_t __wine_unix_call_funcs[] =
X(wg_parser_destroy),
X(wg_parser_connect),
+ X(wg_parser_connect_unseekable),
X(wg_parser_disconnect),
X(wg_parser_begin_flush),
--
2.34.1

View File

@ -1,676 +0,0 @@
From 4518afa81504bbbd86fd3ee62683169730255277 Mon Sep 17 00:00:00 2001
From: Derek Lesho <dlesho@codeweavers.com>
Date: Fri, 19 Mar 2021 16:53:02 -0400
Subject: [PATCH 46/88] winegstreamer: Implement ::Process(Input/Output) for
decoder transform.
---
dlls/winegstreamer/decode_transform.c | 542 +++++++++++++++++++++++++-
dlls/winegstreamer/wg_parser.c | 4 +
2 files changed, 540 insertions(+), 6 deletions(-)
diff --git a/dlls/winegstreamer/decode_transform.c b/dlls/winegstreamer/decode_transform.c
index 4967fc49012..c2b70c10f41 100644
--- a/dlls/winegstreamer/decode_transform.c
+++ b/dlls/winegstreamer/decode_transform.c
@@ -61,14 +61,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)
@@ -124,7 +157,35 @@ static ULONG WINAPI mf_decoder_Release(IMFTransform *iface)
decoder->output_type = NULL;
}
+ if (decoder->wg_parser)
+ {
+ /* NULL wg_parser is possible if the wg_parser creation failed. */
+
+ if (decoder->wg_stream)
+ wg_parser_disconnect(decoder->wg_parser);
+
+ EnterCriticalSection(&decoder->event_cs);
+ decoder->helper_thread_shutdown = TRUE;
+ WakeAllConditionVariable(&decoder->event_cv);
+ LeaveCriticalSection(&decoder->event_cs);
+
+ EnterCriticalSection(&decoder->help_cs);
+ WakeAllConditionVariable(&decoder->help_cv);
+ LeaveCriticalSection(&decoder->help_cs);
+
+ if (WaitForSingleObject(decoder->helper_thread, 10000) != WAIT_OBJECT_0)
+ FIXME("Failed waiting for helper thread to terminate.\n");
+ CloseHandle(decoder->helper_thread);
+ if (WaitForSingleObject(decoder->read_thread, 10000) != WAIT_OBJECT_0)
+ FIXME("Failed waiting for read thread to terminate.\n");
+ CloseHandle(decoder->read_thread);
+
+ wg_parser_destroy(decoder->wg_parser);
+ }
+
DeleteCriticalSection(&decoder->cs);
+ DeleteCriticalSection(&decoder->help_cs);
+ DeleteCriticalSection(&decoder->event_cs);
heap_free(decoder);
}
@@ -351,6 +412,12 @@ static HRESULT WINAPI mf_decoder_SetInputType(IMFTransform *iface, DWORD id, IMF
EnterCriticalSection(&decoder->cs);
+ if (decoder->wg_stream)
+ {
+ decoder->wg_stream = NULL;
+ wg_parser_disconnect(decoder->wg_parser);
+ }
+
if (decoder->input_type)
{
IMFMediaType_Release(decoder->input_type);
@@ -389,6 +456,12 @@ static HRESULT WINAPI mf_decoder_SetInputType(IMFTransform *iface, DWORD id, IMF
hr = S_OK;
+ if (decoder->wg_stream)
+ {
+ decoder->wg_stream = NULL;
+ wg_parser_disconnect(decoder->wg_parser);
+ }
+
if (!decoder->input_type)
hr = MFCreateMediaType(&decoder->input_type);
@@ -398,6 +471,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;
}
@@ -422,6 +505,12 @@ static HRESULT WINAPI mf_decoder_SetOutputType(IMFTransform *iface, DWORD id, IM
EnterCriticalSection(&decoder->cs);
+ if (decoder->wg_stream)
+ {
+ decoder->wg_stream = NULL;
+ wg_parser_disconnect(decoder->wg_parser);
+ }
+
if (decoder->output_type)
{
IMFMediaType_Release(decoder->output_type);
@@ -460,6 +549,12 @@ static HRESULT WINAPI mf_decoder_SetOutputType(IMFTransform *iface, DWORD id, IM
hr = S_OK;
+ if (decoder->wg_stream)
+ {
+ decoder->wg_stream = NULL;
+ wg_parser_disconnect(decoder->wg_parser);
+ }
+
if (!decoder->output_type)
hr = MFCreateMediaType(&decoder->output_type);
@@ -469,6 +564,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;
}
@@ -515,6 +620,117 @@ 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)
+ {
+ LeaveCriticalSection(&decoder->help_cs);
+ return 0;
+ }
+
+ switch(decoder->help_request.type)
+ {
+ case HELP_REQ_START_PARSER:
+ {
+ struct wg_format input_format, output_format;
+
+ 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);
+
+ wg_parser_connect_unseekable(decoder->wg_parser, &input_format, 1, &output_format);
+
+ EnterCriticalSection(&decoder->event_cs);
+ while (!decoder->helper_thread_shutdown && decoder->event.type != PIPELINE_EVENT_NONE)
+ SleepConditionVariableCS(&decoder->event_cv, &decoder->event_cs, INFINITE);
+
+ if (decoder->helper_thread_shutdown)
+ {
+ LeaveCriticalSection(&decoder->event_cs);
+ return 0;
+ }
+
+ decoder->event.type = PIPELINE_EVENT_PARSER_STARTED;
+ decoder->event.u.parser_started.stream = 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;
+ uint64_t offset;
+ uint32_t size;
+
+ for (;;)
+ {
+ if (decoder->helper_thread_shutdown)
+ break;
+
+ if (!wg_parser_get_next_read_offset(decoder->wg_parser, &offset, &size))
+ continue;
+
+ EnterCriticalSection(&decoder->event_cs);
+ while (!decoder->helper_thread_shutdown && decoder->event.type != PIPELINE_EVENT_NONE)
+ SleepConditionVariableCS(&decoder->event_cv, &decoder->event_cs, INFINITE);
+
+ if (decoder->helper_thread_shutdown)
+ {
+ LeaveCriticalSection(&decoder->event_cs);
+ break;
+ }
+
+ decoder->event.type = PIPELINE_EVENT_READ_REQUEST;
+ WakeAllConditionVariable(&decoder->event_cv);
+ while (!decoder->helper_thread_shutdown && 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);
@@ -524,17 +740,315 @@ 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;
- 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 && !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 (!wg_parser_get_next_read_offset(decoder->wg_parser, &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");
+ wg_parser_push_data(decoder->wg_parser, WG_READ_FAILURE, NULL, 0);
+ IMFMediaBuffer_Unlock(buffer);
+ hr = E_FAIL;
+ goto done;
+ }
+
+ wg_parser_push_data(decoder->wg_parser, WG_READ_SUCCESS, buffer_data, 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 (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 (!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 (!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))
+ 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 =
@@ -570,6 +1084,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);
@@ -583,6 +1098,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);
+
+ if (!(parser = wg_parser_create(WG_PARSER_DECODEBIN, TRUE)))
+ {
+ 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;
+
+ object->helper_thread = CreateThread(NULL, 0, helper_thread_func, object, 0, NULL);
+ object->read_thread = CreateThread(NULL, 0, read_thread_func, object, 0, NULL);
*obj = &object->IMFTransform_iface;
return S_OK;
diff --git a/dlls/winegstreamer/wg_parser.c b/dlls/winegstreamer/wg_parser.c
index ab850b899f3..3d6202a209a 100644
--- a/dlls/winegstreamer/wg_parser.c
+++ b/dlls/winegstreamer/wg_parser.c
@@ -2150,9 +2150,13 @@ static NTSTATUS wg_parser_disconnect(void *args)
/* Unblock all of our streams. */
pthread_mutex_lock(&parser->mutex);
+ parser->flushing = true;
+ parser->no_more_pads = true;
+ pthread_cond_signal(&parser->init_cond);
for (i = 0; i < parser->stream_count; ++i)
{
parser->streams[i]->flushing = true;
+ pthread_cond_signal(&parser->streams[i]->event_cond);
pthread_cond_signal(&parser->streams[i]->event_empty_cond);
}
pthread_mutex_unlock(&parser->mutex);
--
2.34.1

View File

@ -1,121 +0,0 @@
From d152c0c2bbd0bcb42b45fcde8f0ce2f13ba90eec Mon Sep 17 00:00:00 2001
From: Derek Lesho <dlesho@codeweavers.com>
Date: Fri, 19 Mar 2021 16:54:03 -0400
Subject: [PATCH 47/88] winegstreamer: Implement ::ProcessMessage for decoder
transform.
---
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 c2b70c10f41..6f1363ff1f3 100644
--- a/dlls/winegstreamer/decode_transform.c
+++ b/dlls/winegstreamer/decode_transform.c
@@ -733,9 +733,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);
+
+ wg_parser_push_data(decoder->wg_parser, WG_READ_EOS, NULL, 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);
+
+ wg_parser_push_data(decoder->wg_parser, WG_READ_FLUSHING, NULL, 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.34.1

View File

@ -1,485 +0,0 @@
From 12a15d2c61816d3d0f55da07fd349088a6042db0 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?R=C3=A9mi=20Bernon?= <rbernon@codeweavers.com>
Date: Wed, 15 Dec 2021 10:59:45 +0100
Subject: [PATCH 48/88] winegstreamer: Implement ::Process(Input/Output) for
audio conversion transform.
---
dlls/winegstreamer/audioconvert.c | 277 +++++++++++++++++++++++++++++-
dlls/winegstreamer/unixlib.h | 1 +
dlls/winegstreamer/wg_parser.c | 61 +++++++
3 files changed, 332 insertions(+), 7 deletions(-)
diff --git a/dlls/winegstreamer/audioconvert.c b/dlls/winegstreamer/audioconvert.c
index afa6bd682a6..e7c1fb97f23 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;
IMFAttributes *attributes, *output_attributes;
};
@@ -85,6 +89,10 @@ static ULONG WINAPI audio_converter_Release(IMFTransform *iface)
IMFAttributes_Release(transform->attributes);
if (transform->output_attributes)
IMFAttributes_Release(transform->output_attributes);
+ if (transform->stream)
+ wg_parser_disconnect(transform->parser);
+ if (transform->parser)
+ wg_parser_destroy(transform->parser);
free(transform);
}
@@ -324,6 +332,7 @@ fail:
static HRESULT WINAPI audio_converter_SetInputType(IMFTransform *iface, DWORD id, IMFMediaType *type, DWORD flags)
{
GUID major_type, subtype;
+ struct wg_format format;
UINT32 unused;
HRESULT hr;
@@ -343,6 +352,11 @@ static HRESULT WINAPI audio_converter_SetInputType(IMFTransform *iface, DWORD id
if (converter->input_type)
{
+ if (converter->stream)
+ {
+ wg_parser_disconnect(converter->parser);
+ converter->stream = NULL;
+ }
IMFMediaType_Release(converter->input_type);
converter->input_type = NULL;
}
@@ -369,6 +383,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;
@@ -388,6 +406,21 @@ static HRESULT WINAPI audio_converter_SetInputType(IMFTransform *iface, DWORD id
converter->input_type = NULL;
}
+ if (converter->stream)
+ {
+ 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 = wg_parser_connect_unseekable(converter->parser, &format, 1, &output_format)))
+ converter->stream = wg_parser_get_stream(converter->parser, 0);
+ }
+
LeaveCriticalSection(&converter->cs);
return hr;
@@ -397,6 +430,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;
UINT32 unused;
HRESULT hr;
@@ -405,9 +439,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)
@@ -417,6 +448,11 @@ static HRESULT WINAPI audio_converter_SetOutputType(IMFTransform *iface, DWORD i
if (converter->output_type)
{
+ if (converter->stream)
+ {
+ wg_parser_disconnect(converter->parser);
+ converter->stream = NULL;
+ }
IMFMediaType_Release(converter->output_type);
converter->output_type = NULL;
}
@@ -443,6 +479,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;
@@ -462,6 +502,21 @@ static HRESULT WINAPI audio_converter_SetOutputType(IMFTransform *iface, DWORD i
converter->output_type = NULL;
}
+ if (converter->stream)
+ {
+ 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 = wg_parser_connect_unseekable(converter->parser, &input_format, 1, &format)))
+ converter->stream = wg_parser_get_stream(converter->parser, 0);
+ }
+
LeaveCriticalSection(&converter->cs);
return hr;
@@ -574,17 +629,218 @@ 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, %lu, %p, %#lx.\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;
+ HRESULT hr;
- return E_NOTIMPL;
+ TRACE("%p, %lu, %p, %#lx.\n", iface, id, sample, flags);
+
+ if (flags)
+ WARN("Unsupported flags %#lx.\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 (!wg_parser_get_next_read_offset(converter->parser, &offset, &size))
+ continue;
+
+ wg_parser_push_data(converter->parser, WG_READ_SUCCESS, buffer_data, min(buffer_size, 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, %#lx, %lu, %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, %#lx, %lu, %p, %p.\n", iface, flags, count, samples, status);
+
+ if (flags)
+ WARN("Unsupported flags %#lx.\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 (;;)
+ {
+ 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, %lu\n", event.type);
+ continue;
+ }
+ break;
+ }
+
+ if (!samples[0].pSample)
+ {
+ if (FAILED(hr = MFCreateMemoryBuffer(event.u.buffer.size, &buffer)))
+ {
+ ERR("Failed to create buffer, hr %#lx.\n", hr);
+ goto done;
+ }
+
+ if (FAILED(hr = MFCreateSample(&allocated_sample)))
+ {
+ ERR("Failed to create sample, hr %#lx.\n", hr);
+ goto done;
+ }
+
+ samples[0].pSample = allocated_sample;
+
+ if (FAILED(hr = IMFSample_AddBuffer(samples[0].pSample, buffer)))
+ {
+ ERR("Failed to add buffer, hr %#lx.\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 %#lx.\n", hr);
+ goto done;
+ }
+
+ if (FAILED(hr = IMFMediaBuffer_GetMaxLength(buffer, &buffer_len)))
+ {
+ ERR("Failed to get buffer size, hr %#lx.\n", hr);
+ goto done;
+ }
+
+ if (buffer_len < event.u.buffer.size)
+ {
+ WARN("Client's buffer is smaller (%lu bytes) than the output sample (%lu 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 %#lx.\n", hr);
+ goto done;
+ }
+
+ if (FAILED(hr = IMFMediaBuffer_Lock(buffer, &buffer_data, NULL, NULL)))
+ {
+ ERR("Failed to lock buffer hr %#lx.\n", hr);
+ goto done;
+ }
+
+ if (!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);
+
+ 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 =
@@ -645,6 +901,13 @@ HRESULT audio_converter_create(REFIID riid, void **ret)
return hr;
}
+ if (!(object->parser = wg_parser_create(WG_PARSER_AUDIOCONV, true)))
+ {
+ 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/unixlib.h b/dlls/winegstreamer/unixlib.h
index e5d87716734..df5e48ef3c9 100644
--- a/dlls/winegstreamer/unixlib.h
+++ b/dlls/winegstreamer/unixlib.h
@@ -160,6 +160,7 @@ enum wg_parser_type
WG_PARSER_AVIDEMUX,
WG_PARSER_MPEGAUDIOPARSE,
WG_PARSER_WAVPARSE,
+ WG_PARSER_AUDIOCONV,
};
struct wg_parser_create_params
diff --git a/dlls/winegstreamer/wg_parser.c b/dlls/winegstreamer/wg_parser.c
index 3d6202a209a..ee59951d2de 100644
--- a/dlls/winegstreamer/wg_parser.c
+++ b/dlls/winegstreamer/wg_parser.c
@@ -2327,6 +2327,66 @@ static BOOL wave_parser_init_gst(struct wg_parser *parser)
return TRUE;
}
+static BOOL audio_convert_init_gst(struct wg_parser *parser)
+{
+ struct wg_parser_stream *stream;
+ GstElement *convert, *resampler;
+ int ret;
+
+ if (parser->seekable)
+ return FALSE;
+
+ if (parser->expected_stream_count != 1)
+ return FALSE;
+
+ if (parser->input_format.major_type != WG_MAJOR_TYPE_AUDIO)
+ return FALSE;
+
+ if (!(convert = create_element("audioconvert", "base")))
+ return FALSE;
+
+ gst_bin_add(GST_BIN(parser->container), convert);
+
+ if (!(resampler = create_element("audioresample", "base")))
+ 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");
+ if ((ret = gst_pad_link(parser->my_src, parser->their_sink)) < 0)
+ {
+ GST_ERROR("Failed to link sink pads, error %d.\n", ret);
+ return FALSE;
+ }
+
+ if (!(stream = create_stream(parser)))
+ return FALSE;
+
+ stream->their_src = gst_element_get_static_pad(resampler, "src");
+ gst_object_ref(stream->their_src);
+ if ((ret = gst_pad_link(stream->their_src, stream->my_sink)) < 0)
+ {
+ GST_ERROR("Failed to link source pads, error %d.\n", ret);
+ return FALSE;
+ }
+ gst_pad_set_active(stream->my_sink, 1);
+
+ parser->no_more_pads = true;
+
+ 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)
+ {
+ GST_ERROR("Failed to play stream.\n");
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
static void init_gstreamer_once(void)
{
char arg0[] = "wine";
@@ -2373,6 +2433,7 @@ static NTSTATUS wg_parser_create(void *args)
[WG_PARSER_AVIDEMUX] = avi_parser_init_gst,
[WG_PARSER_MPEGAUDIOPARSE] = mpeg_audio_parser_init_gst,
[WG_PARSER_WAVPARSE] = wave_parser_init_gst,
+ [WG_PARSER_AUDIOCONV] = audio_convert_init_gst,
};
static pthread_once_t once = PTHREAD_ONCE_INIT;
--
2.34.1

View File

@ -1,472 +0,0 @@
From f0c91d2a459177e0abb5d26d54a87d27276e554c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?R=C3=A9mi=20Bernon?= <rbernon@codeweavers.com>
Date: Wed, 15 Dec 2021 13:30:39 +0100
Subject: [PATCH 49/88] winegstreamer: Implement ::Process(Input/Output) for
color conversion transform.
---
dlls/winegstreamer/colorconvert.c | 276 +++++++++++++++++++++++++++++-
dlls/winegstreamer/unixlib.h | 1 +
dlls/winegstreamer/wg_parser.c | 54 ++++++
3 files changed, 326 insertions(+), 5 deletions(-)
diff --git a/dlls/winegstreamer/colorconvert.c b/dlls/winegstreamer/colorconvert.c
index baf429d42f9..99788bf7f92 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)
+ wg_parser_disconnect(transform->parser);
+ if (transform->parser)
+ wg_parser_destroy(transform->parser);
free(transform);
}
@@ -319,6 +327,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;
@@ -336,6 +345,11 @@ static HRESULT WINAPI color_converter_SetInputType(IMFTransform *iface, DWORD id
if (converter->input_type)
{
+ if (converter->stream)
+ {
+ wg_parser_disconnect(converter->parser);
+ converter->stream = NULL;
+ }
IMFMediaType_Release(converter->input_type);
converter->input_type = NULL;
}
@@ -375,6 +389,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;
@@ -394,6 +412,21 @@ static HRESULT WINAPI color_converter_SetInputType(IMFTransform *iface, DWORD id
converter->input_type = NULL;
}
+ if (converter->stream)
+ {
+ 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 = wg_parser_connect_unseekable(converter->parser, &format, 1, &output_format)))
+ converter->stream = wg_parser_get_stream(converter->parser, 0);
+ }
+
LeaveCriticalSection(&converter->cs);
return hr;
@@ -404,6 +437,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;
@@ -421,6 +455,11 @@ static HRESULT WINAPI color_converter_SetOutputType(IMFTransform *iface, DWORD i
if (converter->output_type)
{
+ if (converter->stream)
+ {
+ wg_parser_disconnect(converter->parser);
+ converter->stream = NULL;
+ }
IMFMediaType_Release(converter->output_type);
converter->output_type = NULL;
}
@@ -460,6 +499,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;
@@ -479,9 +522,24 @@ static HRESULT WINAPI color_converter_SetOutputType(IMFTransform *iface, DWORD i
converter->output_type = NULL;
}
+ if (converter->stream)
+ {
+ 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 = wg_parser_connect_unseekable(converter->parser, &input_format, 1, &format)))
+ converter->stream = 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)
@@ -567,17 +625,218 @@ 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;
+ 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 (!wg_parser_get_next_read_offset(converter->parser, &offset, &size))
+ continue;
+
+ wg_parser_push_data(converter->parser, WG_READ_SUCCESS, buffer_data, min(buffer_size, 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 (;;)
+ {
+ 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 (!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);
+
+ 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 =
@@ -625,6 +884,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 = wg_parser_create(WG_PARSER_VIDEOCONV, true)))
+ {
+ 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;
}
diff --git a/dlls/winegstreamer/unixlib.h b/dlls/winegstreamer/unixlib.h
index df5e48ef3c9..17b5c606014 100644
--- a/dlls/winegstreamer/unixlib.h
+++ b/dlls/winegstreamer/unixlib.h
@@ -161,6 +161,7 @@ enum wg_parser_type
WG_PARSER_MPEGAUDIOPARSE,
WG_PARSER_WAVPARSE,
WG_PARSER_AUDIOCONV,
+ WG_PARSER_VIDEOCONV,
};
struct wg_parser_create_params
diff --git a/dlls/winegstreamer/wg_parser.c b/dlls/winegstreamer/wg_parser.c
index ee59951d2de..06e07b874bf 100644
--- a/dlls/winegstreamer/wg_parser.c
+++ b/dlls/winegstreamer/wg_parser.c
@@ -2387,6 +2387,59 @@ static BOOL audio_convert_init_gst(struct wg_parser *parser)
return TRUE;
}
+static BOOL video_convert_init_gst(struct wg_parser *parser)
+{
+ struct wg_parser_stream *stream;
+ GstElement *convert;
+ int ret;
+
+ if (parser->seekable)
+ return FALSE;
+
+ if (parser->expected_stream_count != 1)
+ return FALSE;
+
+ if (parser->input_format.major_type != WG_MAJOR_TYPE_VIDEO)
+ return FALSE;
+
+ if (!(convert = create_element("videoconvert", "base")))
+ return FALSE;
+
+ gst_bin_add(GST_BIN(parser->container), convert);
+
+ parser->their_sink = gst_element_get_static_pad(convert, "sink");
+ if ((ret = gst_pad_link(parser->my_src, parser->their_sink)) < 0)
+ {
+ GST_ERROR("Failed to link sink pads, error %d.\n", ret);
+ return FALSE;
+ }
+
+ if (!(stream = create_stream(parser)))
+ return FALSE;
+
+ stream->their_src = gst_element_get_static_pad(convert, "src");
+ gst_object_ref(stream->their_src);
+ if ((ret = gst_pad_link(stream->their_src, stream->my_sink)) < 0)
+ {
+ GST_ERROR("Failed to link source pads, error %d.\n", ret);
+ return FALSE;
+ }
+ gst_pad_set_active(stream->my_sink, 1);
+
+ parser->no_more_pads = true;
+
+ 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)
+ {
+ GST_ERROR("Failed to play stream.\n");
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
static void init_gstreamer_once(void)
{
char arg0[] = "wine";
@@ -2434,6 +2487,7 @@ static NTSTATUS wg_parser_create(void *args)
[WG_PARSER_MPEGAUDIOPARSE] = mpeg_audio_parser_init_gst,
[WG_PARSER_WAVPARSE] = wave_parser_init_gst,
[WG_PARSER_AUDIOCONV] = audio_convert_init_gst,
+ [WG_PARSER_VIDEOCONV] = video_convert_init_gst,
};
static pthread_once_t once = PTHREAD_ONCE_INIT;
--
2.34.1

View File

@ -1,97 +0,0 @@
From 39b907ca8de07e2bc78f173083fea717970847a2 Mon Sep 17 00:00:00 2001
From: Derek Lesho <dlesho@codeweavers.com>
Date: Mon, 22 Mar 2021 15:50:51 -0400
Subject: [PATCH 51/88] winegstreamer: Implement MFT_MESSAGE_COMMAND_FLUSH for
media converters.
---
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 e7c1fb97f23..f8d5833aa22 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, %Iu.\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)
+ wg_parser_stream_get_event(converter->stream, &event);
+
+ 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 99788bf7f92..6cad0c1706d 100644
--- a/dlls/winegstreamer/colorconvert.c
+++ b/dlls/winegstreamer/colorconvert.c
@@ -610,11 +610,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)
+ wg_parser_stream_get_event(converter->stream, &event);
+
+ 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:
@@ -664,7 +684,10 @@ static HRESULT WINAPI color_converter_ProcessInput(IMFTransform *iface, DWORD id
for (;;)
{
if (!wg_parser_get_next_read_offset(converter->parser, &offset, &size))
+ {
+ TRACE("sink unconnected\n");
continue;
+ }
wg_parser_push_data(converter->parser, WG_READ_SUCCESS, buffer_data, min(buffer_size, size));
--
2.34.1

View File

@ -1,48 +0,0 @@
From 78f397bed7e11787011ffdb4dead4ee54a18730f Mon Sep 17 00:00:00 2001
From: Andrew Eikum <aeikum@codeweavers.com>
Date: Fri, 7 Jan 2022 10:04:49 -0600
Subject: [PATCH 54/88] winegstreamer: Feed full buffer in audio converter
ProcessInput
In push mode, we can ignore the size of the request. wg_parser will
forward the entire buffer to gst.
CW-Bug-Id: #19859
---
dlls/winegstreamer/audioconvert.c | 17 ++++++-----------
1 file changed, 6 insertions(+), 11 deletions(-)
diff --git a/dlls/winegstreamer/audioconvert.c b/dlls/winegstreamer/audioconvert.c
index 28d449e9f9b..58daf388a30 100644
--- a/dlls/winegstreamer/audioconvert.c
+++ b/dlls/winegstreamer/audioconvert.c
@@ -685,20 +685,15 @@ static HRESULT WINAPI audio_converter_ProcessInput(IMFTransform *iface, DWORD id
if (FAILED(hr = IMFMediaBuffer_Lock(buffer, &buffer_data, NULL, &buffer_size)))
goto done;
- for (;;)
+ if (!wg_parser_get_next_read_offset(converter->parser, &offset, &size))
{
- if (!wg_parser_get_next_read_offset(converter->parser, &offset, &size))
- continue;
-
- wg_parser_push_data(converter->parser, WG_READ_SUCCESS, buffer_data, min(buffer_size, size));
-
- if (buffer_size <= size)
- break;
-
- buffer_data += size;
- buffer_size -= size;
+ hr = MF_E_UNEXPECTED;
+ IMFMediaBuffer_Unlock(buffer);
+ goto done;
}
+ wg_parser_push_data(converter->parser, WG_READ_SUCCESS, buffer_data, buffer_size);
+
IMFMediaBuffer_Unlock(buffer);
converter->buffer_inflight = TRUE;
if (FAILED(IMFSample_GetSampleTime(sample, &converter->buffer_pts)))
--
2.34.1

View File

@ -1,29 +0,0 @@
From c25b5225beb33b0a4403b296e06439c7b8e712b9 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?R=C3=A9mi=20Bernon?= <rbernon@codeweavers.com>
Date: Mon, 17 Jan 2022 14:06:43 +0100
Subject: [PATCH 56/88] winegstreamer: Return S_OK from WMA decoder
ProcessMessage.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=51931
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=52391
CW-Bug-Id: #19854
---
dlls/winegstreamer/wma_decoder.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/dlls/winegstreamer/wma_decoder.c b/dlls/winegstreamer/wma_decoder.c
index 78316059052..847387d3c22 100644
--- a/dlls/winegstreamer/wma_decoder.c
+++ b/dlls/winegstreamer/wma_decoder.c
@@ -486,7 +486,7 @@ static HRESULT WINAPI transform_ProcessEvent(IMFTransform *iface, DWORD id, IMFM
static HRESULT WINAPI transform_ProcessMessage(IMFTransform *iface, MFT_MESSAGE_TYPE message, ULONG_PTR param)
{
FIXME("iface %p, message %#x, param %p stub!\n", iface, message, (void *)param);
- return E_NOTIMPL;
+ return S_OK;
}
static HRESULT WINAPI transform_ProcessInput(IMFTransform *iface, DWORD id, IMFSample *sample, DWORD flags)
--
2.34.1

View File

@ -1,326 +0,0 @@
From ba6442e42f35798a759c625916ad7b58e1672eb0 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?R=C3=A9mi=20Bernon?= <rbernon@codeweavers.com>
Date: Wed, 26 Jan 2022 21:24:07 +0100
Subject: [PATCH 57/88] winegstreamer: Introduce new wg_transform struct.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=51931
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=52391
CW-Bug-Id: #19854
---
dlls/winegstreamer/Makefile.in | 1 +
dlls/winegstreamer/gst_private.h | 3 ++
dlls/winegstreamer/main.c | 14 +++++++
dlls/winegstreamer/unix_private.h | 31 ++++++++++++++
dlls/winegstreamer/unixlib.h | 8 ++++
dlls/winegstreamer/wg_parser.c | 20 +++++++--
dlls/winegstreamer/wg_transform.c | 69 +++++++++++++++++++++++++++++++
dlls/winegstreamer/wma_decoder.c | 20 +++++++++
8 files changed, 162 insertions(+), 4 deletions(-)
create mode 100644 dlls/winegstreamer/unix_private.h
create mode 100644 dlls/winegstreamer/wg_transform.c
diff --git a/dlls/winegstreamer/Makefile.in b/dlls/winegstreamer/Makefile.in
index 74bcc35364b..294d3b199a5 100644
--- a/dlls/winegstreamer/Makefile.in
+++ b/dlls/winegstreamer/Makefile.in
@@ -15,6 +15,7 @@ C_SRCS = \
mfplat.c \
quartz_parser.c \
wg_parser.c \
+ wg_transform.c \
wm_asyncreader.c \
wm_reader.c \
wm_syncreader.c \
diff --git a/dlls/winegstreamer/gst_private.h b/dlls/winegstreamer/gst_private.h
index f1c7bc60428..416dfae01de 100644
--- a/dlls/winegstreamer/gst_private.h
+++ b/dlls/winegstreamer/gst_private.h
@@ -100,6 +100,9 @@ void 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);
bool wg_parser_stream_drain(struct wg_parser_stream *stream);
+struct wg_transform *wg_transform_create(void) DECLSPEC_HIDDEN;
+void wg_transform_destroy(struct wg_transform *transform) DECLSPEC_HIDDEN;
+
unsigned int wg_format_get_max_size(const struct wg_format *format);
HRESULT avi_splitter_create(IUnknown *outer, IUnknown **out);
diff --git a/dlls/winegstreamer/main.c b/dlls/winegstreamer/main.c
index 74f0dd04e83..6938d111926 100644
--- a/dlls/winegstreamer/main.c
+++ b/dlls/winegstreamer/main.c
@@ -288,6 +288,20 @@ bool wg_parser_stream_drain(struct wg_parser_stream *stream)
return !__wine_unix_call(unix_handle, unix_wg_parser_stream_drain, stream);
}
+struct wg_transform *wg_transform_create(void)
+{
+ struct wg_transform_create_params params = {0};
+
+ if (__wine_unix_call(unix_handle, unix_wg_transform_create, &params))
+ return NULL;
+ return params.transform;
+}
+
+void wg_transform_destroy(struct wg_transform *transform)
+{
+ __wine_unix_call(unix_handle, unix_wg_transform_destroy, transform);
+}
+
BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, void *reserved)
{
if (reason == DLL_PROCESS_ATTACH)
diff --git a/dlls/winegstreamer/unix_private.h b/dlls/winegstreamer/unix_private.h
new file mode 100644
index 00000000000..375d33e7728
--- /dev/null
+++ b/dlls/winegstreamer/unix_private.h
@@ -0,0 +1,31 @@
+/*
+ * winegstreamer Unix library interface
+ *
+ * Copyright 2020-2021 Zebediah Figura for CodeWeavers
+ *
+ * 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
+ */
+
+#ifndef __WINE_WINEGSTREAMER_UNIX_PRIVATE_H
+#define __WINE_WINEGSTREAMER_UNIX_PRIVATE_H
+
+#include "unixlib.h"
+
+extern bool init_gstreamer(void) DECLSPEC_HIDDEN;
+
+extern NTSTATUS wg_transform_create(void *args) DECLSPEC_HIDDEN;
+extern NTSTATUS wg_transform_destroy(void *args) DECLSPEC_HIDDEN;
+
+#endif /* __WINE_WINEGSTREAMER_UNIX_PRIVATE_H */
diff --git a/dlls/winegstreamer/unixlib.h b/dlls/winegstreamer/unixlib.h
index 5946621fb9d..25e130d834a 100644
--- a/dlls/winegstreamer/unixlib.h
+++ b/dlls/winegstreamer/unixlib.h
@@ -279,6 +279,11 @@ struct wg_parser_stream_seek_params
DWORD start_flags, stop_flags;
};
+struct wg_transform_create_params
+{
+ struct wg_transform *transform;
+};
+
enum unix_funcs
{
unix_wg_parser_create,
@@ -310,6 +315,9 @@ enum unix_funcs
unix_wg_parser_stream_get_language,
unix_wg_parser_stream_seek,
+ unix_wg_transform_create,
+ unix_wg_transform_destroy,
+
unix_wg_parser_stream_drain,
};
diff --git a/dlls/winegstreamer/wg_parser.c b/dlls/winegstreamer/wg_parser.c
index 833671df20c..b8662c4417d 100644
--- a/dlls/winegstreamer/wg_parser.c
+++ b/dlls/winegstreamer/wg_parser.c
@@ -37,7 +37,7 @@
#include "winternl.h"
#include "dshow.h"
-#include "unixlib.h"
+#include "unix_private.h"
typedef enum
{
@@ -51,7 +51,7 @@ typedef enum
* debug logging instead of Wine debug logging. In order to be safe we forbid
* any use of Wine debug logging in this entire file. */
-GST_DEBUG_CATEGORY_STATIC(wine);
+GST_DEBUG_CATEGORY(wine);
#define GST_CAT_DEFAULT wine
typedef BOOL (*init_gst_cb)(struct wg_parser *parser);
@@ -2569,6 +2569,16 @@ static void init_gstreamer_once(void)
gst_version_string(), GST_VERSION_MAJOR, GST_VERSION_MINOR, GST_VERSION_MICRO);
}
+bool init_gstreamer(void)
+{
+ static pthread_once_t init_once = PTHREAD_ONCE_INIT;
+
+ if (pthread_once(&init_once, init_gstreamer_once))
+ return false;
+
+ return true;
+}
+
static NTSTATUS wg_parser_create(void *args)
{
static const init_gst_cb init_funcs[] =
@@ -2581,11 +2591,10 @@ static NTSTATUS wg_parser_create(void *args)
[WG_PARSER_VIDEOCONV] = video_convert_init_gst,
};
- static pthread_once_t once = PTHREAD_ONCE_INIT;
struct wg_parser_create_params *params = args;
struct wg_parser *parser;
- if (pthread_once(&once, init_gstreamer_once))
+ if (!init_gstreamer())
return E_FAIL;
if (!(parser = calloc(1, sizeof(*parser))))
@@ -2655,5 +2664,8 @@ const unixlib_entry_t __wine_unix_call_funcs[] =
X(wg_parser_stream_get_language),
X(wg_parser_stream_seek),
+ X(wg_transform_create),
+ X(wg_transform_destroy),
+
X(wg_parser_stream_drain),
};
diff --git a/dlls/winegstreamer/wg_transform.c b/dlls/winegstreamer/wg_transform.c
new file mode 100644
index 00000000000..822740da0d7
--- /dev/null
+++ b/dlls/winegstreamer/wg_transform.c
@@ -0,0 +1,69 @@
+/*
+ * GStreamer transform backend
+ *
+ * Copyright 2022 Rémi Bernon for CodeWeavers
+ *
+ * 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
+ */
+
+#if 0
+#pragma makedep unix
+#endif
+
+#include "config.h"
+
+#include <assert.h>
+#include <stdarg.h>
+#include <stdio.h>
+
+#include <gst/gst.h>
+#include <gst/video/video.h>
+#include <gst/audio/audio.h>
+
+#include "winternl.h"
+#include "dshow.h"
+
+#include "unix_private.h"
+
+GST_DEBUG_CATEGORY_EXTERN(wine);
+#define GST_CAT_DEFAULT wine
+
+struct wg_transform
+{
+};
+
+NTSTATUS wg_transform_destroy(void *args)
+{
+ struct wg_transform *transform = args;
+
+ free(transform);
+ return S_OK;
+}
+
+NTSTATUS wg_transform_create(void *args)
+{
+ struct wg_transform_create_params *params = args;
+ struct wg_transform *transform;
+
+ if (!init_gstreamer())
+ return E_FAIL;
+
+ if (!(transform = calloc(1, sizeof(*transform))))
+ return E_OUTOFMEMORY;
+
+ GST_INFO("Created winegstreamer transform %p.", transform);
+ params->transform = transform;
+ return S_OK;
+}
diff --git a/dlls/winegstreamer/wma_decoder.c b/dlls/winegstreamer/wma_decoder.c
index 847387d3c22..1544e8e4c9b 100644
--- a/dlls/winegstreamer/wma_decoder.c
+++ b/dlls/winegstreamer/wma_decoder.c
@@ -53,6 +53,8 @@ struct wma_decoder
LONG refcount;
IMFMediaType *input_type;
IMFMediaType *output_type;
+
+ struct wg_transform *wg_transform;
};
static inline struct wma_decoder *impl_from_IUnknown(IUnknown *iface)
@@ -60,6 +62,19 @@ static inline struct wma_decoder *impl_from_IUnknown(IUnknown *iface)
return CONTAINING_RECORD(iface, struct wma_decoder, IUnknown_inner);
}
+static HRESULT try_create_wg_transform(struct wma_decoder *decoder)
+{
+ if (decoder->wg_transform)
+ wg_transform_destroy(decoder->wg_transform);
+
+ decoder->wg_transform = wg_transform_create();
+ if (decoder->wg_transform)
+ return S_OK;
+
+ WARN("Failed to create wg_transform.\n");
+ return E_FAIL;
+}
+
static HRESULT WINAPI unknown_QueryInterface(IUnknown *iface, REFIID iid, void **out)
{
struct wma_decoder *decoder = impl_from_IUnknown(iface);
@@ -104,6 +119,8 @@ static ULONG WINAPI unknown_Release(IUnknown *iface)
if (!refcount)
{
+ if (decoder->wg_transform)
+ wg_transform_destroy(decoder->wg_transform);
if (decoder->input_type)
IMFMediaType_Release(decoder->input_type);
if (decoder->output_type)
@@ -438,6 +455,9 @@ static HRESULT WINAPI transform_SetOutputType(IMFTransform *iface, DWORD id, IMF
if (FAILED(hr = IMFMediaType_CopyAllItems(type, (IMFAttributes *)decoder->output_type)))
goto failed;
+ if (FAILED(hr = try_create_wg_transform(decoder)))
+ goto failed;
+
return S_OK;
failed:
--
2.34.1

View File

@ -1,185 +0,0 @@
From 19ae522a9a7170b0d07a1f6810858020cd9d9f1e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?R=C3=A9mi=20Bernon?= <rbernon@codeweavers.com>
Date: Fri, 21 Jan 2022 14:02:52 +0100
Subject: [PATCH 58/88] winegstreamer: Introduce new wg_encoded_format struct.
And use it for decoder transform input types.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=51931
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=52391
CW-Bug-Id: #19854
---
dlls/winegstreamer/gst_private.h | 1 +
dlls/winegstreamer/mfplat.c | 84 ++++++++++++++++++++++++++++++++
dlls/winegstreamer/unixlib.h | 25 ++++++++++
dlls/winegstreamer/wma_decoder.c | 12 +++++
4 files changed, 122 insertions(+)
diff --git a/dlls/winegstreamer/gst_private.h b/dlls/winegstreamer/gst_private.h
index 416dfae01de..551dcc549c7 100644
--- a/dlls/winegstreamer/gst_private.h
+++ b/dlls/winegstreamer/gst_private.h
@@ -121,6 +121,7 @@ extern HRESULT mfplat_DllRegisterServer(void);
IMFMediaType *mf_media_type_from_wg_format(const struct wg_format *format);
void mf_media_type_to_wg_format(IMFMediaType *type, struct wg_format *format);
+void mf_media_type_to_wg_encoded_format(IMFMediaType *type, struct wg_encoded_format *format);
HRESULT winegstreamer_stream_handler_create(REFIID riid, void **obj);
diff --git a/dlls/winegstreamer/mfplat.c b/dlls/winegstreamer/mfplat.c
index 54874ad43ee..ca64ce3f7b9 100644
--- a/dlls/winegstreamer/mfplat.c
+++ b/dlls/winegstreamer/mfplat.c
@@ -892,3 +892,87 @@ void mf_media_type_to_wg_format(IMFMediaType *type, struct wg_format *format)
else
FIXME("Unrecognized major type %s.\n", debugstr_guid(&major_type));
}
+
+static void mf_media_type_to_wg_encoded_format_wma(IMFMediaType *type, struct wg_encoded_format *format,
+ UINT32 version)
+{
+ UINT32 rate, depth, channels, block_align, bytes_per_second, codec_data_len;
+ BYTE codec_data[64];
+
+ if (FAILED(IMFMediaType_GetUINT32(type, &MF_MT_AUDIO_SAMPLES_PER_SECOND, &rate)))
+ {
+ FIXME("Sample rate is not set.\n");
+ return;
+ }
+ if (FAILED(IMFMediaType_GetUINT32(type, &MF_MT_AUDIO_NUM_CHANNELS, &channels)))
+ {
+ FIXME("Channel count is not set.\n");
+ return;
+ }
+ if (FAILED(IMFMediaType_GetUINT32(type, &MF_MT_AUDIO_BLOCK_ALIGNMENT, &block_align)))
+ {
+ FIXME("Block alignment is not set.\n");
+ return;
+ }
+ if (FAILED(IMFMediaType_GetUINT32(type, &MF_MT_AUDIO_BITS_PER_SAMPLE, &depth)))
+ {
+ FIXME("Depth is not set.\n");
+ return;
+ }
+ if (FAILED(IMFMediaType_GetBlob(type, &MF_MT_USER_DATA, codec_data, sizeof(codec_data), &codec_data_len)))
+ {
+ FIXME("Codec data is not set.\n");
+ return;
+ }
+ if (FAILED(IMFMediaType_GetUINT32(type, &MF_MT_AUDIO_AVG_BYTES_PER_SECOND, &bytes_per_second)))
+ {
+ FIXME("Bitrate is not set.\n");
+ bytes_per_second = 0;
+ }
+
+ format->encoded_type = WG_ENCODED_TYPE_WMA;
+ format->u.xwma.version = version;
+ format->u.xwma.bitrate = bytes_per_second * 8;
+ format->u.xwma.rate = rate;
+ format->u.xwma.depth = depth;
+ format->u.xwma.channels = channels;
+ format->u.xwma.block_align = block_align;
+ format->u.xwma.codec_data_len = codec_data_len;
+ memcpy(format->u.xwma.codec_data, codec_data, codec_data_len);
+}
+
+void mf_media_type_to_wg_encoded_format(IMFMediaType *type, struct wg_encoded_format *format)
+{
+ GUID major_type, subtype;
+
+ memset(format, 0, sizeof(*format));
+
+ if (FAILED(IMFMediaType_GetMajorType(type, &major_type)))
+ {
+ FIXME("Major type is not set.\n");
+ return;
+ }
+ if (FAILED(IMFMediaType_GetGUID(type, &MF_MT_SUBTYPE, &subtype)))
+ {
+ FIXME("Subtype is not set.\n");
+ return;
+ }
+
+ if (IsEqualGUID(&major_type, &MFMediaType_Audio))
+ {
+ if (IsEqualGUID(&subtype, &MEDIASUBTYPE_MSAUDIO1))
+ mf_media_type_to_wg_encoded_format_wma(type, format, 1);
+ else if (IsEqualGUID(&subtype, &MFAudioFormat_WMAudioV8))
+ mf_media_type_to_wg_encoded_format_wma(type, format, 2);
+ else if (IsEqualGUID(&subtype, &MFAudioFormat_WMAudioV9))
+ mf_media_type_to_wg_encoded_format_wma(type, format, 3);
+ else if (IsEqualGUID(&subtype, &MFAudioFormat_WMAudio_Lossless))
+ mf_media_type_to_wg_encoded_format_wma(type, format, 4);
+ else
+ FIXME("Unimplemented audio subtype %s.\n", debugstr_guid(&subtype));
+ }
+ else
+ {
+ FIXME("Unimplemented major type %s.\n", debugstr_guid(&major_type));
+ }
+}
diff --git a/dlls/winegstreamer/unixlib.h b/dlls/winegstreamer/unixlib.h
index 25e130d834a..7d3eceb6a51 100644
--- a/dlls/winegstreamer/unixlib.h
+++ b/dlls/winegstreamer/unixlib.h
@@ -125,6 +125,31 @@ struct wg_rect
uint32_t bottom;
};
+struct wg_encoded_format
+{
+ enum wg_encoded_type
+ {
+ WG_ENCODED_TYPE_UNKNOWN,
+ WG_ENCODED_TYPE_WMA,
+ WG_ENCODED_TYPE_XMA,
+ } encoded_type;
+
+ union
+ {
+ struct
+ {
+ uint32_t version;
+ uint32_t bitrate;
+ uint32_t rate;
+ uint32_t depth;
+ uint32_t channels;
+ uint32_t block_align;
+ uint32_t codec_data_len;
+ unsigned char codec_data[64];
+ } xwma;
+ } u;
+};
+
enum wg_parser_event_type
{
WG_PARSER_EVENT_NONE = 0,
diff --git a/dlls/winegstreamer/wma_decoder.c b/dlls/winegstreamer/wma_decoder.c
index 1544e8e4c9b..2b543426524 100644
--- a/dlls/winegstreamer/wma_decoder.c
+++ b/dlls/winegstreamer/wma_decoder.c
@@ -64,8 +64,20 @@ static inline struct wma_decoder *impl_from_IUnknown(IUnknown *iface)
static HRESULT try_create_wg_transform(struct wma_decoder *decoder)
{
+ struct wg_encoded_format input_format;
+ struct wg_format output_format;
+
if (decoder->wg_transform)
wg_transform_destroy(decoder->wg_transform);
+ decoder->wg_transform = NULL;
+
+ mf_media_type_to_wg_encoded_format(decoder->input_type, &input_format);
+ if (input_format.encoded_type == WG_ENCODED_TYPE_UNKNOWN)
+ return MF_E_INVALIDMEDIATYPE;
+
+ mf_media_type_to_wg_format(decoder->output_type, &output_format);
+ if (output_format.major_type == WG_MAJOR_TYPE_UNKNOWN)
+ return MF_E_INVALIDMEDIATYPE;
decoder->wg_transform = wg_transform_create();
if (decoder->wg_transform)
--
2.34.1

View File

@ -1,236 +0,0 @@
From 1f48e9be35754d7197b77711dc86ef0033eb381b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?R=C3=A9mi=20Bernon?= <rbernon@codeweavers.com>
Date: Fri, 21 Jan 2022 14:22:59 +0100
Subject: [PATCH 59/88] winegstreamer: Create static pads on wg_transform
struct.
With caps created from the input / output formats.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=51931
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=52391
CW-Bug-Id: #19854
---
dlls/winegstreamer/gst_private.h | 3 +-
dlls/winegstreamer/main.c | 9 ++-
dlls/winegstreamer/unix_private.h | 1 +
dlls/winegstreamer/unixlib.h | 2 +
dlls/winegstreamer/wg_parser.c | 2 +-
dlls/winegstreamer/wg_transform.c | 93 +++++++++++++++++++++++++++++++
dlls/winegstreamer/wma_decoder.c | 2 +-
7 files changed, 107 insertions(+), 5 deletions(-)
diff --git a/dlls/winegstreamer/gst_private.h b/dlls/winegstreamer/gst_private.h
index 551dcc549c7..6432ae37fc0 100644
--- a/dlls/winegstreamer/gst_private.h
+++ b/dlls/winegstreamer/gst_private.h
@@ -100,7 +100,8 @@ void 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);
bool wg_parser_stream_drain(struct wg_parser_stream *stream);
-struct wg_transform *wg_transform_create(void) DECLSPEC_HIDDEN;
+struct wg_transform *wg_transform_create(const struct wg_encoded_format *input_format,
+ const struct wg_format *output_format) DECLSPEC_HIDDEN;
void wg_transform_destroy(struct wg_transform *transform) DECLSPEC_HIDDEN;
unsigned int wg_format_get_max_size(const struct wg_format *format);
diff --git a/dlls/winegstreamer/main.c b/dlls/winegstreamer/main.c
index 6938d111926..d3e87973fdf 100644
--- a/dlls/winegstreamer/main.c
+++ b/dlls/winegstreamer/main.c
@@ -288,9 +288,14 @@ bool wg_parser_stream_drain(struct wg_parser_stream *stream)
return !__wine_unix_call(unix_handle, unix_wg_parser_stream_drain, stream);
}
-struct wg_transform *wg_transform_create(void)
+struct wg_transform *wg_transform_create(const struct wg_encoded_format *input_format,
+ const struct wg_format *output_format)
{
- struct wg_transform_create_params params = {0};
+ struct wg_transform_create_params params =
+ {
+ .input_format = input_format,
+ .output_format = output_format,
+ };
if (__wine_unix_call(unix_handle, unix_wg_transform_create, &params))
return NULL;
diff --git a/dlls/winegstreamer/unix_private.h b/dlls/winegstreamer/unix_private.h
index 375d33e7728..38349eb5e8d 100644
--- a/dlls/winegstreamer/unix_private.h
+++ b/dlls/winegstreamer/unix_private.h
@@ -24,6 +24,7 @@
#include "unixlib.h"
extern bool init_gstreamer(void) DECLSPEC_HIDDEN;
+extern GstCaps *wg_format_to_caps(const struct wg_format *format) DECLSPEC_HIDDEN;
extern NTSTATUS wg_transform_create(void *args) DECLSPEC_HIDDEN;
extern NTSTATUS wg_transform_destroy(void *args) DECLSPEC_HIDDEN;
diff --git a/dlls/winegstreamer/unixlib.h b/dlls/winegstreamer/unixlib.h
index 7d3eceb6a51..51ffc5d3efe 100644
--- a/dlls/winegstreamer/unixlib.h
+++ b/dlls/winegstreamer/unixlib.h
@@ -307,6 +307,8 @@ struct wg_parser_stream_seek_params
struct wg_transform_create_params
{
struct wg_transform *transform;
+ const struct wg_encoded_format *input_format;
+ const struct wg_format *output_format;
};
enum unix_funcs
diff --git a/dlls/winegstreamer/wg_parser.c b/dlls/winegstreamer/wg_parser.c
index b8662c4417d..2970e2464a2 100644
--- a/dlls/winegstreamer/wg_parser.c
+++ b/dlls/winegstreamer/wg_parser.c
@@ -541,7 +541,7 @@ static GstCaps *wg_format_to_caps_video(const struct wg_format *format)
return caps;
}
-static GstCaps *wg_format_to_caps(const struct wg_format *format)
+GstCaps *wg_format_to_caps(const struct wg_format *format)
{
switch (format->major_type)
{
diff --git a/dlls/winegstreamer/wg_transform.c b/dlls/winegstreamer/wg_transform.c
index 822740da0d7..146cdd87ae7 100644
--- a/dlls/winegstreamer/wg_transform.c
+++ b/dlls/winegstreamer/wg_transform.c
@@ -42,12 +42,77 @@ GST_DEBUG_CATEGORY_EXTERN(wine);
struct wg_transform
{
+ GstPad *my_src, *my_sink;
};
+static GstCaps *wg_format_to_caps_xwma(const struct wg_encoded_format *format)
+{
+ GstBuffer *buffer;
+ GstCaps *caps;
+
+ if (format->encoded_type == WG_ENCODED_TYPE_WMA)
+ caps = gst_caps_new_empty_simple("audio/x-wma");
+ else
+ caps = gst_caps_new_empty_simple("audio/x-xma");
+
+ if (format->u.xwma.version)
+ gst_caps_set_simple(caps, "wmaversion", G_TYPE_INT, format->u.xwma.version, NULL);
+ if (format->u.xwma.bitrate)
+ gst_caps_set_simple(caps, "bitrate", G_TYPE_INT, format->u.xwma.bitrate, NULL);
+ if (format->u.xwma.rate)
+ gst_caps_set_simple(caps, "rate", G_TYPE_INT, format->u.xwma.rate, NULL);
+ if (format->u.xwma.depth)
+ gst_caps_set_simple(caps, "depth", G_TYPE_INT, format->u.xwma.depth, NULL);
+ if (format->u.xwma.channels)
+ gst_caps_set_simple(caps, "channels", G_TYPE_INT, format->u.xwma.channels, NULL);
+ if (format->u.xwma.block_align)
+ gst_caps_set_simple(caps, "block_align", G_TYPE_INT, format->u.xwma.block_align, NULL);
+
+ if (format->u.xwma.codec_data_len)
+ {
+ buffer = gst_buffer_new_and_alloc(format->u.xwma.codec_data_len);
+ gst_buffer_fill(buffer, 0, format->u.xwma.codec_data, format->u.xwma.codec_data_len);
+ gst_caps_set_simple(caps, "codec_data", GST_TYPE_BUFFER, buffer, NULL);
+ gst_buffer_unref(buffer);
+ }
+
+ return caps;
+}
+
+static GstCaps *wg_encoded_format_to_caps(const struct wg_encoded_format *format)
+{
+ switch (format->encoded_type)
+ {
+ case WG_ENCODED_TYPE_UNKNOWN:
+ return NULL;
+ case WG_ENCODED_TYPE_WMA:
+ case WG_ENCODED_TYPE_XMA:
+ return wg_format_to_caps_xwma(format);
+ }
+ assert(0);
+ return NULL;
+}
+
+static GstFlowReturn transform_sink_chain_cb(GstPad *pad, GstObject *parent, GstBuffer *buffer)
+{
+ struct wg_transform *transform = gst_pad_get_element_private(pad);
+
+ GST_INFO("transform %p, buffer %p.", transform, buffer);
+
+ gst_buffer_unref(buffer);
+
+ return GST_FLOW_OK;
+}
+
NTSTATUS wg_transform_destroy(void *args)
{
struct wg_transform *transform = args;
+ if (transform->my_sink)
+ g_object_unref(transform->my_sink);
+ if (transform->my_src)
+ g_object_unref(transform->my_src);
+
free(transform);
return S_OK;
}
@@ -55,7 +120,11 @@ NTSTATUS wg_transform_destroy(void *args)
NTSTATUS wg_transform_create(void *args)
{
struct wg_transform_create_params *params = args;
+ struct wg_encoded_format input_format = *params->input_format;
+ struct wg_format output_format = *params->output_format;
+ GstCaps *src_caps, *sink_caps;
struct wg_transform *transform;
+ GstPadTemplate *template;
if (!init_gstreamer())
return E_FAIL;
@@ -63,7 +132,31 @@ NTSTATUS wg_transform_create(void *args)
if (!(transform = calloc(1, sizeof(*transform))))
return E_OUTOFMEMORY;
+ src_caps = wg_encoded_format_to_caps(&input_format);
+ assert(src_caps);
+ sink_caps = wg_format_to_caps(&output_format);
+ assert(sink_caps);
+
+ template = gst_pad_template_new("src", GST_PAD_SRC, GST_PAD_ALWAYS, src_caps);
+ assert(template);
+ transform->my_src = gst_pad_new_from_template(template, "src");
+ g_object_unref(template);
+ assert(transform->my_src);
+
+ template = gst_pad_template_new("sink", GST_PAD_SINK, GST_PAD_ALWAYS, sink_caps);
+ assert(template);
+ transform->my_sink = gst_pad_new_from_template(template, "sink");
+ g_object_unref(template);
+ assert(transform->my_sink);
+
+ gst_pad_set_element_private(transform->my_sink, transform);
+ gst_pad_set_chain_function(transform->my_sink, transform_sink_chain_cb);
+
GST_INFO("Created winegstreamer transform %p.", transform);
params->transform = transform;
+
+ gst_caps_unref(src_caps);
+ gst_caps_unref(sink_caps);
+
return S_OK;
}
diff --git a/dlls/winegstreamer/wma_decoder.c b/dlls/winegstreamer/wma_decoder.c
index 2b543426524..db6c8a677f6 100644
--- a/dlls/winegstreamer/wma_decoder.c
+++ b/dlls/winegstreamer/wma_decoder.c
@@ -79,7 +79,7 @@ static HRESULT try_create_wg_transform(struct wma_decoder *decoder)
if (output_format.major_type == WG_MAJOR_TYPE_UNKNOWN)
return MF_E_INVALIDMEDIATYPE;
- decoder->wg_transform = wg_transform_create();
+ decoder->wg_transform = wg_transform_create(&input_format, &output_format);
if (decoder->wg_transform)
return S_OK;
--
2.34.1

View File

@ -1,207 +0,0 @@
From 855ce2096c36de51d227cb07a88a73e51c34d3a9 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?R=C3=A9mi=20Bernon?= <rbernon@codeweavers.com>
Date: Fri, 21 Jan 2022 14:24:27 +0100
Subject: [PATCH 60/88] winegstreamer: Lookup, create and link a decoder
element.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=51931
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=52391
CW-Bug-Id: #19854
---
dlls/winegstreamer/wg_transform.c | 140 +++++++++++++++++++++++++++++-
1 file changed, 138 insertions(+), 2 deletions(-)
diff --git a/dlls/winegstreamer/wg_transform.c b/dlls/winegstreamer/wg_transform.c
index 146cdd87ae7..a436d8316dd 100644
--- a/dlls/winegstreamer/wg_transform.c
+++ b/dlls/winegstreamer/wg_transform.c
@@ -42,7 +42,9 @@ GST_DEBUG_CATEGORY_EXTERN(wine);
struct wg_transform
{
+ GstElement *container;
GstPad *my_src, *my_sink;
+ GstPad *their_sink, *their_src;
};
static GstCaps *wg_format_to_caps_xwma(const struct wg_encoded_format *format)
@@ -108,6 +110,22 @@ NTSTATUS wg_transform_destroy(void *args)
{
struct wg_transform *transform = args;
+ if (transform->container)
+ gst_element_set_state(transform->container, GST_STATE_NULL);
+
+ if (transform->their_src && transform->my_sink)
+ gst_pad_unlink(transform->their_src, transform->my_sink);
+ if (transform->their_sink && transform->my_src)
+ gst_pad_unlink(transform->my_src, transform->their_sink);
+
+ if (transform->their_sink)
+ g_object_unref(transform->their_sink);
+ if (transform->their_src)
+ g_object_unref(transform->their_src);
+
+ if (transform->container)
+ g_object_unref(transform->container);
+
if (transform->my_sink)
g_object_unref(transform->my_sink);
if (transform->my_src)
@@ -117,14 +135,85 @@ NTSTATUS wg_transform_destroy(void *args)
return S_OK;
}
+static GstElement *try_create_transform(GstCaps *src_caps, GstCaps *sink_caps)
+{
+ GstElement *element = NULL;
+ GList *tmp, *transforms;
+ gchar *type;
+
+ transforms = gst_element_factory_list_get_elements(GST_ELEMENT_FACTORY_TYPE_ANY,
+ GST_RANK_MARGINAL);
+
+ tmp = gst_element_factory_list_filter(transforms, src_caps, GST_PAD_SINK, FALSE);
+ gst_plugin_feature_list_free(transforms);
+ transforms = tmp;
+
+ tmp = gst_element_factory_list_filter(transforms, sink_caps, GST_PAD_SRC, FALSE);
+ gst_plugin_feature_list_free(transforms);
+ transforms = tmp;
+
+ transforms = g_list_sort(transforms, gst_plugin_feature_rank_compare_func);
+ for (tmp = transforms; tmp != NULL && element == NULL; tmp = tmp->next)
+ {
+ type = gst_plugin_feature_get_name(GST_PLUGIN_FEATURE(tmp->data));
+ element = gst_element_factory_create(GST_ELEMENT_FACTORY(tmp->data), NULL);
+ if (!element)
+ GST_WARNING("Failed to create %s element.", type);
+ }
+ gst_plugin_feature_list_free(transforms);
+
+ if (element)
+ GST_INFO("Created %s element %p.", type, element);
+ else
+ {
+ gchar *src_str = gst_caps_to_string(src_caps), *sink_str = gst_caps_to_string(sink_caps);
+ GST_WARNING("Failed to create transform matching caps %s / %s.", src_str, sink_str);
+ g_free(sink_str);
+ g_free(src_str);
+ }
+
+ return element;
+}
+
+static bool transform_append_element(struct wg_transform *transform, GstElement *element,
+ GstElement **first, GstElement **last)
+{
+ gchar *name = gst_element_get_name(element);
+
+ if (!gst_bin_add(GST_BIN(transform->container), element))
+ {
+ GST_ERROR("Failed to add %s element to bin.", name);
+ g_free(name);
+ return false;
+ }
+
+ if (*last && !gst_element_link(*last, element))
+ {
+ GST_ERROR("Failed to link %s element.", name);
+ g_free(name);
+ return false;
+ }
+
+ GST_INFO("Created %s element %p.", name, element);
+ g_free(name);
+
+ if (!*first)
+ *first = element;
+
+ *last = element;
+ return true;
+}
+
NTSTATUS wg_transform_create(void *args)
{
struct wg_transform_create_params *params = args;
struct wg_encoded_format input_format = *params->input_format;
struct wg_format output_format = *params->output_format;
- GstCaps *src_caps, *sink_caps;
+ GstElement *first = NULL, *last = NULL, *element;
struct wg_transform *transform;
+ GstCaps *src_caps, *sink_caps;
GstPadTemplate *template;
+ int ret;
if (!init_gstreamer())
return E_FAIL;
@@ -137,6 +226,24 @@ NTSTATUS wg_transform_create(void *args)
sink_caps = wg_format_to_caps(&output_format);
assert(sink_caps);
+ transform->container = gst_bin_new("wg_transform");
+ assert(transform->container);
+
+ if (!(element = try_create_transform(src_caps, sink_caps)) ||
+ !transform_append_element(transform, element, &first, &last))
+ goto failed;
+
+ if (!(transform->their_sink = gst_element_get_static_pad(first, "sink")))
+ {
+ GST_ERROR("Failed to find target sink pad.");
+ goto failed;
+ }
+ if (!(transform->their_src = gst_element_get_static_pad(last, "src")))
+ {
+ GST_ERROR("Failed to find target src pad.");
+ goto failed;
+ }
+
template = gst_pad_template_new("src", GST_PAD_SRC, GST_PAD_ALWAYS, src_caps);
assert(template);
transform->my_src = gst_pad_new_from_template(template, "src");
@@ -152,11 +259,40 @@ NTSTATUS wg_transform_create(void *args)
gst_pad_set_element_private(transform->my_sink, transform);
gst_pad_set_chain_function(transform->my_sink, transform_sink_chain_cb);
+ if ((ret = gst_pad_link(transform->my_src, transform->their_sink)) < 0)
+ {
+ GST_ERROR("Failed to link sink pads, error %d.", ret);
+ goto failed;
+ }
+ if ((ret = gst_pad_link(transform->their_src, transform->my_sink)) < 0)
+ {
+ GST_ERROR("Failed to link source pads, error %d.", ret);
+ goto failed;
+ }
+
+ if (!(ret = gst_pad_set_active(transform->my_sink, 1)))
+ GST_WARNING("Failed to activate my_sink.");
+ if (!(ret = gst_pad_set_active(transform->my_src, 1)))
+ GST_WARNING("Failed to activate my_src.");
+
+ gst_element_set_state(transform->container, GST_STATE_PAUSED);
+ ret = gst_element_get_state(transform->container, NULL, NULL, -1);
+ if (ret == GST_STATE_CHANGE_FAILURE)
+ {
+ GST_ERROR("Failed to play stream.\n");
+ goto failed;
+ }
+
GST_INFO("Created winegstreamer transform %p.", transform);
params->transform = transform;
+failed:
gst_caps_unref(src_caps);
gst_caps_unref(sink_caps);
- return S_OK;
+ if (params->transform)
+ return S_OK;
+
+ wg_transform_destroy(transform);
+ return E_FAIL;
}
--
2.34.1

View File

@ -1,59 +0,0 @@
From 6cc21e8ca6164debd05e7a98b7c20cc65714518b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?R=C3=A9mi=20Bernon?= <rbernon@codeweavers.com>
Date: Fri, 21 Jan 2022 14:25:20 +0100
Subject: [PATCH 61/88] winegstreamer: Send stream-start and caps events on
creation.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=51931
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=52391
CW-Bug-Id: #19854
---
dlls/winegstreamer/wg_transform.c | 25 +++++++++++++++++++++++++
1 file changed, 25 insertions(+)
diff --git a/dlls/winegstreamer/wg_transform.c b/dlls/winegstreamer/wg_transform.c
index a436d8316dd..d87b8cfa2c4 100644
--- a/dlls/winegstreamer/wg_transform.c
+++ b/dlls/winegstreamer/wg_transform.c
@@ -213,6 +213,7 @@ NTSTATUS wg_transform_create(void *args)
struct wg_transform *transform;
GstCaps *src_caps, *sink_caps;
GstPadTemplate *template;
+ GstSegment *segment;
int ret;
if (!init_gstreamer())
@@ -283,6 +284,30 @@ NTSTATUS wg_transform_create(void *args)
goto failed;
}
+ if (!gst_pad_push_event(transform->my_src, gst_event_new_stream_start("stream")))
+ {
+ GST_ERROR("Failed to send stream-start.");
+ goto failed;
+ }
+
+ if (!gst_pad_push_event(transform->my_src, gst_event_new_caps(src_caps)))
+ {
+ GST_ERROR("Failed to set stream caps.");
+ goto failed;
+ }
+
+ segment = gst_segment_new();
+ gst_segment_init(segment, GST_FORMAT_TIME);
+ segment->start = 0;
+ segment->stop = -1;
+ ret = gst_pad_push_event(transform->my_src, gst_event_new_segment(segment));
+ gst_segment_free(segment);
+ if (!ret)
+ {
+ GST_ERROR("Failed to start new segment.");
+ goto failed;
+ }
+
GST_INFO("Created winegstreamer transform %p.", transform);
params->transform = transform;
--
2.34.1

View File

@ -1,100 +0,0 @@
From b90b4207c326a3faf0e6ff5fb0649bd8a081fab7 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?R=C3=A9mi=20Bernon?= <rbernon@codeweavers.com>
Date: Fri, 21 Jan 2022 14:25:58 +0100
Subject: [PATCH 62/88] winegstreamer: Add an audioconverter and audioresampler
elements.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=51931
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=52391
CW-Bug-Id: #19854
---
dlls/winegstreamer/unix_private.h | 1 +
dlls/winegstreamer/wg_parser.c | 2 +-
dlls/winegstreamer/wg_transform.c | 23 +++++++++++++++++++++--
3 files changed, 23 insertions(+), 3 deletions(-)
diff --git a/dlls/winegstreamer/unix_private.h b/dlls/winegstreamer/unix_private.h
index 38349eb5e8d..e6b0f3636f7 100644
--- a/dlls/winegstreamer/unix_private.h
+++ b/dlls/winegstreamer/unix_private.h
@@ -24,6 +24,7 @@
#include "unixlib.h"
extern bool init_gstreamer(void) DECLSPEC_HIDDEN;
+extern GstElement *create_element(const char *name, const char *plugin_set) DECLSPEC_HIDDEN;
extern GstCaps *wg_format_to_caps(const struct wg_format *format) DECLSPEC_HIDDEN;
extern NTSTATUS wg_transform_create(void *args) DECLSPEC_HIDDEN;
diff --git a/dlls/winegstreamer/wg_parser.c b/dlls/winegstreamer/wg_parser.c
index 2970e2464a2..02bf639962f 100644
--- a/dlls/winegstreamer/wg_parser.c
+++ b/dlls/winegstreamer/wg_parser.c
@@ -1280,7 +1280,7 @@ static gboolean sink_query_cb(GstPad *pad, GstObject *parent, GstQuery *query)
}
}
-static GstElement *create_element(const char *name, const char *plugin_set)
+GstElement *create_element(const char *name, const char *plugin_set)
{
GstElement *element;
diff --git a/dlls/winegstreamer/wg_transform.c b/dlls/winegstreamer/wg_transform.c
index d87b8cfa2c4..d96923594e2 100644
--- a/dlls/winegstreamer/wg_transform.c
+++ b/dlls/winegstreamer/wg_transform.c
@@ -210,9 +210,10 @@ NTSTATUS wg_transform_create(void *args)
struct wg_encoded_format input_format = *params->input_format;
struct wg_format output_format = *params->output_format;
GstElement *first = NULL, *last = NULL, *element;
+ GstCaps *raw_caps, *src_caps, *sink_caps;
struct wg_transform *transform;
- GstCaps *src_caps, *sink_caps;
GstPadTemplate *template;
+ const gchar *media_type;
GstSegment *segment;
int ret;
@@ -226,14 +227,31 @@ NTSTATUS wg_transform_create(void *args)
assert(src_caps);
sink_caps = wg_format_to_caps(&output_format);
assert(sink_caps);
+ media_type = gst_structure_get_name(gst_caps_get_structure(sink_caps, 0));
+ raw_caps = gst_caps_new_empty_simple(media_type);
+ assert(raw_caps);
transform->container = gst_bin_new("wg_transform");
assert(transform->container);
- if (!(element = try_create_transform(src_caps, sink_caps)) ||
+ if (!(element = try_create_transform(src_caps, raw_caps)) ||
!transform_append_element(transform, element, &first, &last))
goto failed;
+ switch (output_format.major_type)
+ {
+ case WG_MAJOR_TYPE_AUDIO:
+ if (!(element = create_element("audioconvert", "base")) ||
+ !transform_append_element(transform, element, &first, &last))
+ goto failed;
+ if (!(element = create_element("audioresample", "base")) ||
+ !transform_append_element(transform, element, &first, &last))
+ goto failed;
+ break;
+ default:
+ break;
+ }
+
if (!(transform->their_sink = gst_element_get_static_pad(first, "sink")))
{
GST_ERROR("Failed to find target sink pad.");
@@ -312,6 +330,7 @@ NTSTATUS wg_transform_create(void *args)
params->transform = transform;
failed:
+ gst_caps_unref(raw_caps);
gst_caps_unref(src_caps);
gst_caps_unref(sink_caps);
--
2.34.1

View File

@ -1,249 +0,0 @@
From cd2746f22bdea18808282efbdfa6e599c5b7a5d7 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?R=C3=A9mi=20Bernon?= <rbernon@codeweavers.com>
Date: Fri, 21 Jan 2022 14:28:54 +0100
Subject: [PATCH 63/88] winegstreamer: Implement WMA decoder ProcessInput.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=51931
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=52391
CW-Bug-Id: #19854
---
dlls/mf/tests/mf.c | 6 -----
dlls/winegstreamer/gst_private.h | 1 +
dlls/winegstreamer/main.c | 12 +++++++++
dlls/winegstreamer/unix_private.h | 1 +
dlls/winegstreamer/unixlib.h | 9 +++++++
dlls/winegstreamer/wg_parser.c | 2 ++
dlls/winegstreamer/wg_transform.c | 22 ++++++++++++++++
dlls/winegstreamer/wma_decoder.c | 43 +++++++++++++++++++++++++++++--
8 files changed, 88 insertions(+), 8 deletions(-)
diff --git a/dlls/mf/tests/mf.c b/dlls/mf/tests/mf.c
index 07f4c28052d..d78f0051714 100644
--- a/dlls/mf/tests/mf.c
+++ b/dlls/mf/tests/mf.c
@@ -6207,25 +6207,20 @@ static void test_wma_decoder(void)
sample = create_sample(wma_encoded_data, wma_block_size / 2);
hr = IMFTransform_ProcessInput(transform, 0, sample, 0);
- todo_wine
ok(hr == S_OK, "ProcessInput returned %#x\n", hr);
ret = IMFSample_Release(sample);
ok(ret == 0, "Release returned %u\n", ret);
sample = create_sample(wma_encoded_data + wma_block_size, wma_block_size - wma_block_size / 2);
hr = IMFTransform_ProcessInput(transform, 0, sample, 0);
- todo_wine
ok(hr == S_OK, "ProcessInput returned %#x\n", hr);
ret = IMFSample_Release(sample);
ok(ret == 0, "Release returned %u\n", ret);
sample = create_sample(wma_encoded_data, wma_block_size);
hr = IMFTransform_ProcessInput(transform, 0, sample, 0);
- todo_wine
ok(hr == S_OK, "ProcessInput returned %#x\n", hr);
hr = IMFTransform_ProcessInput(transform, 0, sample, 0);
- todo_wine
ok(hr == MF_E_NOTACCEPTING, "ProcessInput returned %#x\n", hr);
ret = IMFSample_Release(sample);
- todo_wine
ok(ret == 1, "Release returned %u\n", ret);
/* As output_info.dwFlags doesn't have MFT_OUTPUT_STREAM_CAN_PROVIDE_SAMPLES
@@ -6248,7 +6243,6 @@ static void test_wma_decoder(void)
sample = create_sample(wma_encoded_data, wma_block_size);
hr = IMFTransform_ProcessInput(transform, 0, sample, 0);
- todo_wine
ok(hr == MF_E_NOTACCEPTING, "ProcessInput returned %#x\n", hr);
ret = IMFSample_Release(sample);
ok(ret == 0, "Release returned %u\n", ret);
diff --git a/dlls/winegstreamer/gst_private.h b/dlls/winegstreamer/gst_private.h
index 6432ae37fc0..8c7e1795fea 100644
--- a/dlls/winegstreamer/gst_private.h
+++ b/dlls/winegstreamer/gst_private.h
@@ -103,6 +103,7 @@ bool wg_parser_stream_drain(struct wg_parser_stream *stream);
struct wg_transform *wg_transform_create(const struct wg_encoded_format *input_format,
const struct wg_format *output_format) DECLSPEC_HIDDEN;
void wg_transform_destroy(struct wg_transform *transform) DECLSPEC_HIDDEN;
+HRESULT wg_transform_push_data(struct wg_transform *transform, const void *data, uint32_t size) DECLSPEC_HIDDEN;
unsigned int wg_format_get_max_size(const struct wg_format *format);
diff --git a/dlls/winegstreamer/main.c b/dlls/winegstreamer/main.c
index d3e87973fdf..cb21b54f7df 100644
--- a/dlls/winegstreamer/main.c
+++ b/dlls/winegstreamer/main.c
@@ -307,6 +307,18 @@ void wg_transform_destroy(struct wg_transform *transform)
__wine_unix_call(unix_handle, unix_wg_transform_destroy, transform);
}
+HRESULT wg_transform_push_data(struct wg_transform *transform, const void *data, uint32_t size)
+{
+ struct wg_transform_push_data_params params =
+ {
+ .transform = transform,
+ .data = data,
+ .size = size,
+ };
+
+ return __wine_unix_call(unix_handle, unix_wg_transform_push_data, &params);
+}
+
BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, void *reserved)
{
if (reason == DLL_PROCESS_ATTACH)
diff --git a/dlls/winegstreamer/unix_private.h b/dlls/winegstreamer/unix_private.h
index e6b0f3636f7..baa7f81926c 100644
--- a/dlls/winegstreamer/unix_private.h
+++ b/dlls/winegstreamer/unix_private.h
@@ -29,5 +29,6 @@ extern GstCaps *wg_format_to_caps(const struct wg_format *format) DECLSPEC_HIDDE
extern NTSTATUS wg_transform_create(void *args) DECLSPEC_HIDDEN;
extern NTSTATUS wg_transform_destroy(void *args) DECLSPEC_HIDDEN;
+extern NTSTATUS wg_transform_push_data(void *args) DECLSPEC_HIDDEN;
#endif /* __WINE_WINEGSTREAMER_UNIX_PRIVATE_H */
diff --git a/dlls/winegstreamer/unixlib.h b/dlls/winegstreamer/unixlib.h
index 51ffc5d3efe..b361fea36d1 100644
--- a/dlls/winegstreamer/unixlib.h
+++ b/dlls/winegstreamer/unixlib.h
@@ -311,6 +311,13 @@ struct wg_transform_create_params
const struct wg_format *output_format;
};
+struct wg_transform_push_data_params
+{
+ struct wg_transform *transform;
+ const void *data;
+ UINT32 size;
+};
+
enum unix_funcs
{
unix_wg_parser_create,
@@ -346,6 +353,8 @@ enum unix_funcs
unix_wg_transform_destroy,
unix_wg_parser_stream_drain,
+
+ unix_wg_transform_push_data,
};
#endif /* __WINE_WINEGSTREAMER_UNIXLIB_H */
diff --git a/dlls/winegstreamer/wg_parser.c b/dlls/winegstreamer/wg_parser.c
index 02bf639962f..a5dfa0cf7ee 100644
--- a/dlls/winegstreamer/wg_parser.c
+++ b/dlls/winegstreamer/wg_parser.c
@@ -2668,4 +2668,6 @@ const unixlib_entry_t __wine_unix_call_funcs[] =
X(wg_transform_destroy),
X(wg_parser_stream_drain),
+
+ X(wg_transform_push_data),
};
diff --git a/dlls/winegstreamer/wg_transform.c b/dlls/winegstreamer/wg_transform.c
index d96923594e2..2137c4c8821 100644
--- a/dlls/winegstreamer/wg_transform.c
+++ b/dlls/winegstreamer/wg_transform.c
@@ -34,6 +34,7 @@
#include "winternl.h"
#include "dshow.h"
+#include "mferror.h"
#include "unix_private.h"
@@ -340,3 +341,24 @@ failed:
wg_transform_destroy(transform);
return E_FAIL;
}
+
+NTSTATUS wg_transform_push_data(void *args)
+{
+ struct wg_transform_push_data_params *params = args;
+ struct wg_transform *transform = params->transform;
+ GstBuffer *buffer;
+ GstFlowReturn ret;
+
+ buffer = gst_buffer_new_and_alloc(params->size);
+ gst_buffer_fill(buffer, 0, params->data, params->size);
+
+ ret = gst_pad_push(transform->my_src, buffer);
+ if (ret)
+ {
+ GST_ERROR("Failed to push buffer %d", ret);
+ return MF_E_NOTACCEPTING;
+ }
+
+ GST_INFO("Pushed %u bytes", params->size);
+ return S_OK;
+}
diff --git a/dlls/winegstreamer/wma_decoder.c b/dlls/winegstreamer/wma_decoder.c
index db6c8a677f6..c9472bde019 100644
--- a/dlls/winegstreamer/wma_decoder.c
+++ b/dlls/winegstreamer/wma_decoder.c
@@ -54,6 +54,7 @@ struct wma_decoder
IMFMediaType *input_type;
IMFMediaType *output_type;
+ IMFSample *input_sample;
struct wg_transform *wg_transform;
};
@@ -131,6 +132,8 @@ static ULONG WINAPI unknown_Release(IUnknown *iface)
if (!refcount)
{
+ if (decoder->input_sample)
+ IMFSample_Release(decoder->input_sample);
if (decoder->wg_transform)
wg_transform_destroy(decoder->wg_transform);
if (decoder->input_type)
@@ -523,8 +526,44 @@ static HRESULT WINAPI transform_ProcessMessage(IMFTransform *iface, MFT_MESSAGE_
static HRESULT WINAPI transform_ProcessInput(IMFTransform *iface, DWORD id, IMFSample *sample, DWORD flags)
{
- FIXME("iface %p, id %lu, sample %p, flags %#lx stub!\n", iface, id, sample, flags);
- return E_NOTIMPL;
+ struct wma_decoder *decoder = impl_from_IMFTransform(iface);
+ IMFMediaBuffer *media_buffer;
+ MFT_INPUT_STREAM_INFO info;
+ DWORD buffer_size;
+ BYTE *buffer;
+ HRESULT hr;
+
+ TRACE("iface %p, id %lu, sample %p, flags %#lx.\n", iface, id, sample, flags);
+
+ if (FAILED(hr = IMFTransform_GetInputStreamInfo(iface, 0, &info)))
+ return hr;
+
+ if (!decoder->wg_transform)
+ return MF_E_TRANSFORM_TYPE_NOT_SET;
+
+ if (decoder->input_sample)
+ return MF_E_NOTACCEPTING;
+
+ if (FAILED(hr = IMFSample_ConvertToContiguousBuffer(sample, &media_buffer)))
+ return hr;
+
+ if (FAILED(hr = IMFMediaBuffer_GetCurrentLength(media_buffer, &buffer_size)))
+ return hr;
+
+ if (!(buffer_size = (buffer_size / info.cbSize) * info.cbSize))
+ return S_OK;
+
+ if (FAILED(hr = IMFMediaBuffer_Lock(media_buffer, &buffer, NULL, NULL)))
+ goto done;
+
+ if (SUCCEEDED(hr = wg_transform_push_data(decoder->wg_transform, buffer, buffer_size)))
+ IMFSample_AddRef((decoder->input_sample = sample));
+
+ IMFMediaBuffer_Unlock(media_buffer);
+
+done:
+ IMFMediaBuffer_Release(media_buffer);
+ return hr;
}
static HRESULT WINAPI transform_ProcessOutput(IMFTransform *iface, DWORD flags, DWORD count,
--
2.34.1

View File

@ -1,407 +0,0 @@
From 4c1eae2084677337da00722ed93e9b3032c8a6db Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?R=C3=A9mi=20Bernon?= <rbernon@codeweavers.com>
Date: Fri, 21 Jan 2022 14:31:44 +0100
Subject: [PATCH 64/88] winegstreamer: Implement WMA decoder ProcessOutput.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=51931
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=52391
CW-Bug-Id: #19854
---
dlls/mf/tests/mf.c | 19 ++------
dlls/winegstreamer/gst_private.h | 1 +
dlls/winegstreamer/main.c | 11 +++++
dlls/winegstreamer/unix_private.h | 1 +
dlls/winegstreamer/unixlib.h | 19 ++++++++
dlls/winegstreamer/wg_parser.c | 1 +
dlls/winegstreamer/wg_transform.c | 76 ++++++++++++++++++++++++++++++-
dlls/winegstreamer/wma_decoder.c | 59 +++++++++++++++++++++++-
8 files changed, 169 insertions(+), 18 deletions(-)
diff --git a/dlls/mf/tests/mf.c b/dlls/mf/tests/mf.c
index d78f0051714..4a81191bcf6 100644
--- a/dlls/mf/tests/mf.c
+++ b/dlls/mf/tests/mf.c
@@ -6229,16 +6229,13 @@ static void test_wma_decoder(void)
status = 0xdeadbeef;
memset(&output, 0, sizeof(output));
hr = IMFTransform_ProcessOutput(transform, 0, 1, &output, &status);
- todo_wine
ok(hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "ProcessOutput returned %#x\n", hr);
ok(output.dwStreamID == 0, "got dwStreamID %u\n", output.dwStreamID);
ok(!output.pSample, "got pSample %p\n", output.pSample);
- todo_wine
ok(output.dwStatus == MFT_OUTPUT_DATA_BUFFER_NO_SAMPLE ||
broken(output.dwStatus == (MFT_OUTPUT_DATA_BUFFER_INCOMPLETE|MFT_OUTPUT_DATA_BUFFER_NO_SAMPLE)) /* Win7 */,
"got dwStatus %#x\n", output.dwStatus);
ok(!output.pEvents, "got pEvents %p\n", output.pEvents);
- todo_wine
ok(status == 0, "got status %#x\n", status);
sample = create_sample(wma_encoded_data, wma_block_size);
@@ -6250,14 +6247,11 @@ static void test_wma_decoder(void)
status = 0xdeadbeef;
memset(&output, 0, sizeof(output));
hr = IMFTransform_ProcessOutput(transform, 0, 1, &output, &status);
- todo_wine
ok(hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "ProcessOutput returned %#x\n", hr);
ok(!output.pSample, "got pSample %p\n", output.pSample);
- todo_wine
ok(output.dwStatus == MFT_OUTPUT_DATA_BUFFER_NO_SAMPLE ||
broken(output.dwStatus == (MFT_OUTPUT_DATA_BUFFER_INCOMPLETE|MFT_OUTPUT_DATA_BUFFER_NO_SAMPLE)) /* Win7 */,
"got dwStatus %#x\n", output.dwStatus);
- todo_wine
ok(status == 0, "got status %#x\n", status);
i = 1;
@@ -6291,7 +6285,6 @@ static void test_wma_decoder(void)
hr = IMFTransform_ProcessOutput(transform, 0, 1, &output, &status);
}
- todo_wine
ok(hr == S_OK, "ProcessOutput returned %#x\n", hr);
ok(output.pSample == sample, "got pSample %p\n", output.pSample);
@@ -6304,7 +6297,8 @@ static void test_wma_decoder(void)
"got dwStatus %#x\n", output.dwStatus);
ok(status == 0, "got status %#x\n", status);
if (output.dwStatus == MFT_OUTPUT_DATA_BUFFER_INCOMPLETE ||
- broken(output.dwStatus == (MFT_OUTPUT_DATA_BUFFER_INCOMPLETE|7)))
+ broken(output.dwStatus == (MFT_OUTPUT_DATA_BUFFER_INCOMPLETE|7)) ||
+ !strcmp(winetest_platform, "wine"))
{
check_sample(sample, wma_decoded_data, sizeof(wma_decoded_data), NULL);
i += sizeof(wma_decoded_data);
@@ -6323,14 +6317,12 @@ static void test_wma_decoder(void)
output.pSample = sample;
hr = IMFTransform_ProcessOutput(transform, 0, 1, &output, &status);
}
- todo_wine
- ok(i == 0xe000, "ProcessOutput produced %#x bytes\n", i);
+ if (!strcmp(winetest_platform, "wine")) ok(i == 0x10000, "ProcessOutput produced %#x bytes\n", i);
+ else ok(i == 0xe000, "ProcessOutput produced %#x bytes\n", i);
- todo_wine
ok(hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "ProcessOutput returned %#x\n", hr);
ok(output.pSample == sample, "got pSample %p\n", output.pSample);
ok(output.dwStatus == 0, "got dwStatus %#x\n", output.dwStatus);
- todo_wine
ok(status == 0, "got status %#x\n", status);
ret = IMFSample_Release(sample);
ok(ret == 0, "Release returned %u\n", ret);
@@ -6340,13 +6332,11 @@ static void test_wma_decoder(void)
memset(&output, 0, sizeof(output));
output.pSample = sample;
hr = IMFTransform_ProcessOutput(transform, 0, 1, &output, &status);
- todo_wine
ok(hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "ProcessOutput returned %#x\n", hr);
ok(output.pSample == sample, "got pSample %p\n", output.pSample);
ok(output.dwStatus == 0 ||
broken(output.dwStatus == (MFT_OUTPUT_DATA_BUFFER_INCOMPLETE|7)) /* Win7 */,
"got dwStatus %#x\n", output.dwStatus);
- todo_wine
ok(status == 0, "got status %#x\n", status);
check_sample(sample, NULL, 0, NULL);
ret = IMFSample_Release(sample);
@@ -6354,7 +6344,6 @@ static void test_wma_decoder(void)
sample = create_sample(wma_encoded_data, wma_block_size);
hr = IMFTransform_ProcessInput(transform, 0, sample, 0);
- todo_wine
ok(hr == S_OK, "ProcessInput returned %#x\n", hr);
ret = IMFTransform_Release(transform);
diff --git a/dlls/winegstreamer/gst_private.h b/dlls/winegstreamer/gst_private.h
index 8c7e1795fea..af30e944865 100644
--- a/dlls/winegstreamer/gst_private.h
+++ b/dlls/winegstreamer/gst_private.h
@@ -104,6 +104,7 @@ struct wg_transform *wg_transform_create(const struct wg_encoded_format *input_f
const struct wg_format *output_format) DECLSPEC_HIDDEN;
void wg_transform_destroy(struct wg_transform *transform) DECLSPEC_HIDDEN;
HRESULT wg_transform_push_data(struct wg_transform *transform, const void *data, uint32_t size) DECLSPEC_HIDDEN;
+HRESULT wg_transform_read_data(struct wg_transform *transform, struct wg_sample *sample) DECLSPEC_HIDDEN;
unsigned int wg_format_get_max_size(const struct wg_format *format);
diff --git a/dlls/winegstreamer/main.c b/dlls/winegstreamer/main.c
index cb21b54f7df..fd73bfc289a 100644
--- a/dlls/winegstreamer/main.c
+++ b/dlls/winegstreamer/main.c
@@ -319,6 +319,17 @@ HRESULT wg_transform_push_data(struct wg_transform *transform, const void *data,
return __wine_unix_call(unix_handle, unix_wg_transform_push_data, &params);
}
+HRESULT wg_transform_read_data(struct wg_transform *transform, struct wg_sample *sample)
+{
+ struct wg_transform_read_data_params params =
+ {
+ .transform = transform,
+ .sample = sample,
+ };
+
+ return __wine_unix_call(unix_handle, unix_wg_transform_read_data, &params);
+}
+
BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, void *reserved)
{
if (reason == DLL_PROCESS_ATTACH)
diff --git a/dlls/winegstreamer/unix_private.h b/dlls/winegstreamer/unix_private.h
index baa7f81926c..1b055436ba5 100644
--- a/dlls/winegstreamer/unix_private.h
+++ b/dlls/winegstreamer/unix_private.h
@@ -30,5 +30,6 @@ extern GstCaps *wg_format_to_caps(const struct wg_format *format) DECLSPEC_HIDDE
extern NTSTATUS wg_transform_create(void *args) DECLSPEC_HIDDEN;
extern NTSTATUS wg_transform_destroy(void *args) DECLSPEC_HIDDEN;
extern NTSTATUS wg_transform_push_data(void *args) DECLSPEC_HIDDEN;
+extern NTSTATUS wg_transform_read_data(void *args) DECLSPEC_HIDDEN;
#endif /* __WINE_WINEGSTREAMER_UNIX_PRIVATE_H */
diff --git a/dlls/winegstreamer/unixlib.h b/dlls/winegstreamer/unixlib.h
index b361fea36d1..0df245408ee 100644
--- a/dlls/winegstreamer/unixlib.h
+++ b/dlls/winegstreamer/unixlib.h
@@ -318,6 +318,24 @@ struct wg_transform_push_data_params
UINT32 size;
};
+enum wg_sample_flags
+{
+ WG_SAMPLE_FLAG_INCOMPLETE = 1,
+};
+
+struct wg_sample
+{
+ UINT32 flags;
+ BYTE *data;
+ UINT32 size;
+};
+
+struct wg_transform_read_data_params
+{
+ struct wg_transform *transform;
+ struct wg_sample *sample;
+};
+
enum unix_funcs
{
unix_wg_parser_create,
@@ -355,6 +373,7 @@ enum unix_funcs
unix_wg_parser_stream_drain,
unix_wg_transform_push_data,
+ unix_wg_transform_read_data,
};
#endif /* __WINE_WINEGSTREAMER_UNIXLIB_H */
diff --git a/dlls/winegstreamer/wg_parser.c b/dlls/winegstreamer/wg_parser.c
index a5dfa0cf7ee..3217c78e864 100644
--- a/dlls/winegstreamer/wg_parser.c
+++ b/dlls/winegstreamer/wg_parser.c
@@ -2670,4 +2670,5 @@ const unixlib_entry_t __wine_unix_call_funcs[] =
X(wg_parser_stream_drain),
X(wg_transform_push_data),
+ X(wg_transform_read_data),
};
diff --git a/dlls/winegstreamer/wg_transform.c b/dlls/winegstreamer/wg_transform.c
index 2137c4c8821..1f8b35920b4 100644
--- a/dlls/winegstreamer/wg_transform.c
+++ b/dlls/winegstreamer/wg_transform.c
@@ -38,14 +38,24 @@
#include "unix_private.h"
+#include "wine/list.h"
+
GST_DEBUG_CATEGORY_EXTERN(wine);
#define GST_CAT_DEFAULT wine
+struct wg_transform_sample
+{
+ struct list entry;
+ GstSample *sample;
+};
+
struct wg_transform
{
GstElement *container;
GstPad *my_src, *my_sink;
GstPad *their_sink, *their_src;
+ pthread_mutex_t mutex;
+ struct list samples;
};
static GstCaps *wg_format_to_caps_xwma(const struct wg_encoded_format *format)
@@ -99,17 +109,29 @@ static GstCaps *wg_encoded_format_to_caps(const struct wg_encoded_format *format
static GstFlowReturn transform_sink_chain_cb(GstPad *pad, GstObject *parent, GstBuffer *buffer)
{
struct wg_transform *transform = gst_pad_get_element_private(pad);
+ struct wg_transform_sample *sample;
GST_INFO("transform %p, buffer %p.", transform, buffer);
- gst_buffer_unref(buffer);
+ if (!(sample = malloc(sizeof(*sample))))
+ GST_ERROR("Failed to allocate transform sample entry");
+ else
+ {
+ pthread_mutex_lock(&transform->mutex);
+ if (!(sample->sample = gst_sample_new(buffer, NULL, NULL, NULL)))
+ GST_ERROR("Failed to allocate transform sample");
+ list_add_tail(&transform->samples, &sample->entry);
+ pthread_mutex_unlock(&transform->mutex);
+ }
+ gst_buffer_unref(buffer);
return GST_FLOW_OK;
}
NTSTATUS wg_transform_destroy(void *args)
{
struct wg_transform *transform = args;
+ struct wg_transform_sample *sample, *next;
if (transform->container)
gst_element_set_state(transform->container, GST_STATE_NULL);
@@ -132,6 +154,13 @@ NTSTATUS wg_transform_destroy(void *args)
if (transform->my_src)
g_object_unref(transform->my_src);
+ LIST_FOR_EACH_ENTRY_SAFE(sample, next, &transform->samples, struct wg_transform_sample, entry)
+ {
+ gst_sample_unref(sample->sample);
+ list_remove(&sample->entry);
+ free(sample);
+ }
+
free(transform);
return S_OK;
}
@@ -224,6 +253,8 @@ NTSTATUS wg_transform_create(void *args)
if (!(transform = calloc(1, sizeof(*transform))))
return E_OUTOFMEMORY;
+ list_init(&transform->samples);
+
src_caps = wg_encoded_format_to_caps(&input_format);
assert(src_caps);
sink_caps = wg_format_to_caps(&output_format);
@@ -362,3 +393,46 @@ NTSTATUS wg_transform_push_data(void *args)
GST_INFO("Pushed %u bytes", params->size);
return S_OK;
}
+
+NTSTATUS wg_transform_read_data(void *args)
+{
+ struct wg_transform_read_data_params *params = args;
+ struct wg_transform *transform = params->transform;
+ struct wg_sample *read_sample = params->sample;
+ struct wg_transform_sample *transform_sample;
+ GstBuffer *buffer;
+ struct list *head;
+ GstMapInfo info;
+
+ pthread_mutex_lock(&transform->mutex);
+ if (!(head = list_head(&transform->samples)))
+ {
+ pthread_mutex_unlock(&transform->mutex);
+ return MF_E_TRANSFORM_NEED_MORE_INPUT;
+ }
+
+ transform_sample = LIST_ENTRY(head, struct wg_transform_sample, entry);
+ buffer = gst_sample_get_buffer(transform_sample->sample);
+
+ gst_buffer_map(buffer, &info, GST_MAP_READ);
+ if (read_sample->size > info.size)
+ read_sample->size = info.size;
+ memcpy(read_sample->data, info.data, read_sample->size);
+ gst_buffer_unmap(buffer, &info);
+
+ if (info.size > read_sample->size)
+ {
+ read_sample->flags |= WG_SAMPLE_FLAG_INCOMPLETE;
+ gst_buffer_resize(buffer, read_sample->size, -1);
+ }
+ else
+ {
+ gst_sample_unref(transform_sample->sample);
+ list_remove(&transform_sample->entry);
+ free(transform_sample);
+ }
+ pthread_mutex_unlock(&transform->mutex);
+
+ GST_INFO("Read %u bytes, flags %#x", read_sample->size, read_sample->flags);
+ return S_OK;
+}
diff --git a/dlls/winegstreamer/wma_decoder.c b/dlls/winegstreamer/wma_decoder.c
index c9472bde019..cac345be269 100644
--- a/dlls/winegstreamer/wma_decoder.c
+++ b/dlls/winegstreamer/wma_decoder.c
@@ -569,8 +569,63 @@ done:
static HRESULT WINAPI transform_ProcessOutput(IMFTransform *iface, DWORD flags, DWORD count,
MFT_OUTPUT_DATA_BUFFER *samples, DWORD *status)
{
- FIXME("iface %p, flags %#lx, count %lu, samples %p, status %p stub!\n", iface, flags, count, samples, status);
- return E_NOTIMPL;
+ struct wma_decoder *decoder = impl_from_IMFTransform(iface);
+ struct wg_sample wg_sample = {0};
+ IMFMediaBuffer *media_buffer;
+ MFT_OUTPUT_STREAM_INFO info;
+ DWORD buffer_size;
+ HRESULT hr;
+
+ TRACE("iface %p, flags %#lx, count %lu, samples %p, status %p.\n", iface, flags, count, samples, status);
+
+ if (count > 1)
+ {
+ FIXME("Not implemented count %lu\n", count);
+ return E_NOTIMPL;
+ }
+
+ if (FAILED(hr = IMFTransform_GetOutputStreamInfo(iface, 0, &info)))
+ return hr;
+
+ if (!decoder->wg_transform)
+ return MF_E_TRANSFORM_TYPE_NOT_SET;
+
+ *status = 0;
+ samples[0].dwStatus = 0;
+ if (!samples[0].pSample)
+ {
+ samples[0].dwStatus = MFT_OUTPUT_DATA_BUFFER_NO_SAMPLE;
+ return MF_E_TRANSFORM_NEED_MORE_INPUT;
+ }
+
+ if (FAILED(hr = IMFSample_ConvertToContiguousBuffer(samples[0].pSample, &media_buffer)))
+ return hr;
+
+ if (FAILED(hr = IMFMediaBuffer_Lock(media_buffer, &wg_sample.data, &buffer_size, NULL)))
+ goto done;
+ wg_sample.size = buffer_size;
+
+ if (wg_sample.size < info.cbSize)
+ hr = MF_E_BUFFERTOOSMALL;
+ else if (SUCCEEDED(hr = wg_transform_read_data(decoder->wg_transform, &wg_sample)))
+ {
+ if (wg_sample.flags & WG_SAMPLE_FLAG_INCOMPLETE)
+ samples[0].dwStatus |= MFT_OUTPUT_DATA_BUFFER_INCOMPLETE;
+ }
+ else
+ {
+ if (decoder->input_sample)
+ IMFSample_Release(decoder->input_sample);
+ decoder->input_sample = NULL;
+ wg_sample.size = 0;
+ }
+
+ IMFMediaBuffer_Unlock(media_buffer);
+
+done:
+ IMFMediaBuffer_SetCurrentLength(media_buffer, wg_sample.size);
+ IMFMediaBuffer_Release(media_buffer);
+ return hr;
}
static const IMFTransformVtbl transform_vtbl =
--
2.34.1

View File

@ -1,363 +0,0 @@
From e0fce42d02ca3c2975384f04729d7b67021fc8b0 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?R=C3=A9mi=20Bernon?= <rbernon@codeweavers.com>
Date: Tue, 18 Jan 2022 13:09:07 +0100
Subject: [PATCH 66/88] winegstreamer: Introduce new H264 decoder transform
stub.
As a remplacement for the previously added transform.
For: Call of Duty III, Mortal Kombat 11, Shadow Warrior 2,
Yakuza 4 Remastered, Hard Reset Redux.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=45988
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=47084
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=49715
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=52183
CW-Bug-Id: #16839
CW-Bug-Id: #18678
CW-Bug-Id: #19362
---
dlls/winegstreamer/Makefile.in | 1 +
dlls/winegstreamer/gst_private.h | 1 +
dlls/winegstreamer/h264_decoder.c | 279 ++++++++++++++++++++++++++++++
dlls/winegstreamer/mfplat.c | 7 +-
4 files changed, 282 insertions(+), 6 deletions(-)
create mode 100644 dlls/winegstreamer/h264_decoder.c
diff --git a/dlls/winegstreamer/Makefile.in b/dlls/winegstreamer/Makefile.in
index 294d3b199a5..c4f0f1cad2c 100644
--- a/dlls/winegstreamer/Makefile.in
+++ b/dlls/winegstreamer/Makefile.in
@@ -10,6 +10,7 @@ C_SRCS = \
audioconvert.c \
colorconvert.c \
decode_transform.c \
+ h264_decoder.c \
main.c \
media_source.c \
mfplat.c \
diff --git a/dlls/winegstreamer/gst_private.h b/dlls/winegstreamer/gst_private.h
index af30e944865..fa73fecb10d 100644
--- a/dlls/winegstreamer/gst_private.h
+++ b/dlls/winegstreamer/gst_private.h
@@ -128,6 +128,7 @@ void mf_media_type_to_wg_encoded_format(IMFMediaType *type, struct wg_encoded_fo
HRESULT winegstreamer_stream_handler_create(REFIID riid, void **obj);
+HRESULT h264_decoder_create(REFIID riid, void **ret);
HRESULT audio_converter_create(REFIID riid, void **ret);
HRESULT color_converter_create(REFIID riid, void **ret);
diff --git a/dlls/winegstreamer/h264_decoder.c b/dlls/winegstreamer/h264_decoder.c
new file mode 100644
index 00000000000..5db72c55151
--- /dev/null
+++ b/dlls/winegstreamer/h264_decoder.c
@@ -0,0 +1,279 @@
+/* H264 Decoder Transform
+ *
+ * Copyright 2022 Rémi Bernon for CodeWeavers
+ *
+ * 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 "wmcodecdsp.h"
+
+#include "wine/debug.h"
+#include "wine/heap.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(mfplat);
+
+struct h264_decoder
+{
+ IMFTransform IMFTransform_iface;
+ LONG refcount;
+};
+
+static struct h264_decoder *impl_from_IMFTransform(IMFTransform *iface)
+{
+ return CONTAINING_RECORD(iface, struct h264_decoder, IMFTransform_iface);
+}
+
+static HRESULT WINAPI h264_decoder_QueryInterface(IMFTransform *iface, REFIID iid, void **out)
+{
+ struct h264_decoder *decoder = impl_from_IMFTransform(iface);
+
+ TRACE("iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out);
+
+ if (IsEqualGUID(iid, &IID_IUnknown) || IsEqualGUID(iid, &IID_IMFTransform))
+ *out = &decoder->IMFTransform_iface;
+ else
+ {
+ *out = NULL;
+ WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid));
+ return E_NOINTERFACE;
+ }
+
+ IUnknown_AddRef((IUnknown *)*out);
+ return S_OK;
+}
+
+static ULONG WINAPI h264_decoder_AddRef(IMFTransform *iface)
+{
+ struct h264_decoder *decoder = impl_from_IMFTransform(iface);
+ ULONG refcount = InterlockedIncrement(&decoder->refcount);
+
+ TRACE("iface %p increasing refcount to %lu.\n", decoder, refcount);
+
+ return refcount;
+}
+
+static ULONG WINAPI h264_decoder_Release(IMFTransform *iface)
+{
+ struct h264_decoder *decoder = impl_from_IMFTransform(iface);
+ ULONG refcount = InterlockedDecrement(&decoder->refcount);
+
+ TRACE("iface %p decreasing refcount to %lu.\n", decoder, refcount);
+
+ if (!refcount)
+ free(decoder);
+
+ return refcount;
+}
+
+static HRESULT WINAPI h264_decoder_GetStreamLimits(IMFTransform *iface, DWORD *input_minimum, DWORD *input_maximum,
+ DWORD *output_minimum, DWORD *output_maximum)
+{
+ FIXME("iface %p, input_minimum %p, input_maximum %p, output_minimum %p, output_maximum %p stub!\n",
+ iface, input_minimum, input_maximum, output_minimum, output_maximum);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI h264_decoder_GetStreamCount(IMFTransform *iface, DWORD *inputs, DWORD *outputs)
+{
+ FIXME("iface %p, inputs %p, outputs %p stub!\n", iface, inputs, outputs);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI h264_decoder_GetStreamIDs(IMFTransform *iface, DWORD input_size, DWORD *inputs,
+ DWORD output_size, DWORD *outputs)
+{
+ FIXME("iface %p, input_size %lu, inputs %p, output_size %lu, outputs %p stub!\n",
+ iface, input_size, inputs, output_size, outputs);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI h264_decoder_GetInputStreamInfo(IMFTransform *iface, DWORD id, MFT_INPUT_STREAM_INFO *info)
+{
+ FIXME("iface %p, id %#lx, info %p stub!\n", iface, id, info);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI h264_decoder_GetOutputStreamInfo(IMFTransform *iface, DWORD id, MFT_OUTPUT_STREAM_INFO *info)
+{
+ FIXME("iface %p, id %#lx, info %p stub!\n", iface, id, info);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI h264_decoder_GetAttributes(IMFTransform *iface, IMFAttributes **attributes)
+{
+ FIXME("iface %p, attributes %p stub!\n", iface, attributes);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI h264_decoder_GetInputStreamAttributes(IMFTransform *iface, DWORD id,
+ IMFAttributes **attributes)
+{
+ FIXME("iface %p, id %#lx, attributes %p stub!\n", iface, id, attributes);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI h264_decoder_GetOutputStreamAttributes(IMFTransform *iface, DWORD id,
+ IMFAttributes **attributes)
+{
+ FIXME("iface %p, id %#lx, attributes %p stub!\n", iface, id, attributes);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI h264_decoder_DeleteInputStream(IMFTransform *iface, DWORD id)
+{
+ FIXME("iface %p, id %#lx stub!\n", iface, id);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI h264_decoder_AddInputStreams(IMFTransform *iface, DWORD streams, DWORD *ids)
+{
+ FIXME("iface %p, streams %lu, ids %p stub!\n", iface, streams, ids);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI h264_decoder_GetInputAvailableType(IMFTransform *iface, DWORD id, DWORD index,
+ IMFMediaType **type)
+{
+ FIXME("iface %p, id %#lx, index %#lx, type %p stub!\n", iface, id, index, type);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI h264_decoder_GetOutputAvailableType(IMFTransform *iface, DWORD id, DWORD index,
+ IMFMediaType **type)
+{
+ FIXME("iface %p, id %#lx, index %#lx, type %p stub!\n", iface, id, index, type);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI h264_decoder_SetInputType(IMFTransform *iface, DWORD id, IMFMediaType *type, DWORD flags)
+{
+ FIXME("iface %p, id %#lx, type %p, flags %#lx stub!\n", iface, id, type, flags);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI h264_decoder_SetOutputType(IMFTransform *iface, DWORD id, IMFMediaType *type, DWORD flags)
+{
+ FIXME("iface %p, id %#lx, type %p, flags %#lx stub!\n", iface, id, type, flags);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI h264_decoder_GetInputCurrentType(IMFTransform *iface, DWORD id, IMFMediaType **type)
+{
+ FIXME("iface %p, id %#lx, type %p stub!\n", iface, id, type);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI h264_decoder_GetOutputCurrentType(IMFTransform *iface, DWORD id, IMFMediaType **type)
+{
+ FIXME("iface %p, id %#lx, type %p stub!\n", iface, id, type);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI h264_decoder_GetInputStatus(IMFTransform *iface, DWORD id, DWORD *flags)
+{
+ FIXME("iface %p, id %#lx, flags %p stub!\n", iface, id, flags);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI h264_decoder_GetOutputStatus(IMFTransform *iface, DWORD *flags)
+{
+ FIXME("iface %p, flags %p stub!\n", iface, flags);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI h264_decoder_SetOutputBounds(IMFTransform *iface, LONGLONG lower, LONGLONG upper)
+{
+ FIXME("iface %p, lower %s, upper %s stub!\n", iface,
+ wine_dbgstr_longlong(lower), wine_dbgstr_longlong(upper));
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI h264_decoder_ProcessEvent(IMFTransform *iface, DWORD id, IMFMediaEvent *event)
+{
+ FIXME("iface %p, id %#lx, event %p stub!\n", iface, id, event);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI h264_decoder_ProcessMessage(IMFTransform *iface, MFT_MESSAGE_TYPE message, ULONG_PTR param)
+{
+ FIXME("iface %p, message %#x, param %p stub!\n", iface, message, (void *)param);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI h264_decoder_ProcessInput(IMFTransform *iface, DWORD id, IMFSample *sample, DWORD flags)
+{
+ FIXME("iface %p, id %#lx, sample %p, flags %#lx stub!\n", iface, id, sample, flags);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI h264_decoder_ProcessOutput(IMFTransform *iface, DWORD flags, DWORD count,
+ MFT_OUTPUT_DATA_BUFFER *samples, DWORD *status)
+{
+ FIXME("iface %p, flags %#lx, count %lu, samples %p, status %p stub!\n", iface, flags, count, samples, status);
+ return E_NOTIMPL;
+}
+
+static const IMFTransformVtbl h264_decoder_vtbl =
+{
+ h264_decoder_QueryInterface,
+ h264_decoder_AddRef,
+ h264_decoder_Release,
+ h264_decoder_GetStreamLimits,
+ h264_decoder_GetStreamCount,
+ h264_decoder_GetStreamIDs,
+ h264_decoder_GetInputStreamInfo,
+ h264_decoder_GetOutputStreamInfo,
+ h264_decoder_GetAttributes,
+ h264_decoder_GetInputStreamAttributes,
+ h264_decoder_GetOutputStreamAttributes,
+ h264_decoder_DeleteInputStream,
+ h264_decoder_AddInputStreams,
+ h264_decoder_GetInputAvailableType,
+ h264_decoder_GetOutputAvailableType,
+ h264_decoder_SetInputType,
+ h264_decoder_SetOutputType,
+ h264_decoder_GetInputCurrentType,
+ h264_decoder_GetOutputCurrentType,
+ h264_decoder_GetInputStatus,
+ h264_decoder_GetOutputStatus,
+ h264_decoder_SetOutputBounds,
+ h264_decoder_ProcessEvent,
+ h264_decoder_ProcessMessage,
+ h264_decoder_ProcessInput,
+ h264_decoder_ProcessOutput,
+};
+
+HRESULT h264_decoder_create(REFIID riid, void **ret)
+{
+ struct h264_decoder *decoder;
+
+ TRACE("riid %s, ret %p.\n", debugstr_guid(riid), ret);
+
+ if (!(decoder = calloc(1, sizeof(*decoder))))
+ return E_OUTOFMEMORY;
+
+ decoder->IMFTransform_iface.lpVtbl = &h264_decoder_vtbl;
+ decoder->refcount = 1;
+
+ *ret = &decoder->IMFTransform_iface;
+ TRACE("Created decoder %p\n", *ret);
+ return S_OK;
+}
diff --git a/dlls/winegstreamer/mfplat.c b/dlls/winegstreamer/mfplat.c
index 5633331359d..ca26c767125 100644
--- a/dlls/winegstreamer/mfplat.c
+++ b/dlls/winegstreamer/mfplat.c
@@ -400,11 +400,6 @@ 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;
@@ -549,7 +544,7 @@ mfts[] =
color_converter_supported_types,
},
{
- &CLSID_MSAACDecMFT,
+ &CLSID_MSH264DecoderMFT,
&MFT_CATEGORY_VIDEO_DECODER,
h264_decoderW,
MFT_ENUM_FLAG_SYNCMFT,
--
2.34.1

View File

@ -1,36 +0,0 @@
From ac5e4d49d48fb8b4f1070103c856f0b7363a7d03 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?R=C3=A9mi=20Bernon?= <rbernon@codeweavers.com>
Date: Tue, 18 Jan 2022 13:33:36 +0100
Subject: [PATCH 68/88] winegstreamer: Return S_OK from H264 decoder
ProcessMessage.
For: Call of Duty III, Mortal Kombat 11, Shadow Warrior 2,
Yakuza 4 Remastered, Hard Reset Redux.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=45988
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=47084
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=49715
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=52183
CW-Bug-Id: #16839
CW-Bug-Id: #18678
CW-Bug-Id: #19362
---
dlls/winegstreamer/h264_decoder.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/dlls/winegstreamer/h264_decoder.c b/dlls/winegstreamer/h264_decoder.c
index f46d6d77f8e..55f40ad7660 100644
--- a/dlls/winegstreamer/h264_decoder.c
+++ b/dlls/winegstreamer/h264_decoder.c
@@ -216,7 +216,7 @@ static HRESULT WINAPI h264_decoder_ProcessEvent(IMFTransform *iface, DWORD id, I
static HRESULT WINAPI h264_decoder_ProcessMessage(IMFTransform *iface, MFT_MESSAGE_TYPE message, ULONG_PTR param)
{
FIXME("iface %p, message %#x, param %p stub!\n", iface, message, (void *)param);
- return E_NOTIMPL;
+ return S_OK;
}
static HRESULT WINAPI h264_decoder_ProcessInput(IMFTransform *iface, DWORD id, IMFSample *sample, DWORD flags)
--
2.34.1

View File

@ -1,89 +0,0 @@
From 34491aae12bd533db2ceb8fdbfcbc0a1ccc54004 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?R=C3=A9mi=20Bernon?= <rbernon@codeweavers.com>
Date: Thu, 10 Feb 2022 09:54:51 +0100
Subject: [PATCH 69/88] winegstreamer: Implement H264 decoder SetInputType.
For: Call of Duty III, Mortal Kombat 11, Shadow Warrior 2,
Yakuza 4 Remastered, Hard Reset Redux.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=45988
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=47084
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=49715
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=52183
CW-Bug-Id: #16839
CW-Bug-Id: #18678
CW-Bug-Id: #19362
---
dlls/winegstreamer/h264_decoder.c | 37 +++++++++++++++++++++++++++++--
1 file changed, 35 insertions(+), 2 deletions(-)
diff --git a/dlls/winegstreamer/h264_decoder.c b/dlls/winegstreamer/h264_decoder.c
index 55f40ad7660..e0634bedcaa 100644
--- a/dlls/winegstreamer/h264_decoder.c
+++ b/dlls/winegstreamer/h264_decoder.c
@@ -30,10 +30,16 @@
WINE_DEFAULT_DEBUG_CHANNEL(mfplat);
+static const GUID *h264_decoder_input_types[] =
+{
+ &MFVideoFormat_H264,
+};
+
struct h264_decoder
{
IMFTransform IMFTransform_iface;
LONG refcount;
+ IMFMediaType *input_type;
};
static struct h264_decoder *impl_from_IMFTransform(IMFTransform *iface)
@@ -78,7 +84,11 @@ static ULONG WINAPI h264_decoder_Release(IMFTransform *iface)
TRACE("iface %p decreasing refcount to %lu.\n", decoder, refcount);
if (!refcount)
+ {
+ if (decoder->input_type)
+ IMFMediaType_Release(decoder->input_type);
free(decoder);
+ }
return refcount;
}
@@ -166,8 +176,31 @@ static HRESULT WINAPI h264_decoder_GetOutputAvailableType(IMFTransform *iface, D
static HRESULT WINAPI h264_decoder_SetInputType(IMFTransform *iface, DWORD id, IMFMediaType *type, DWORD flags)
{
- FIXME("iface %p, id %#lx, type %p, flags %#lx stub!\n", iface, id, type, flags);
- return E_NOTIMPL;
+ struct h264_decoder *decoder = impl_from_IMFTransform(iface);
+ GUID major, subtype;
+ HRESULT hr;
+ ULONG i;
+
+ TRACE("iface %p, id %#lx, type %p, flags %#lx.\n", iface, id, type, flags);
+
+ if (FAILED(hr = IMFMediaType_GetGUID(type, &MF_MT_MAJOR_TYPE, &major)) ||
+ FAILED(hr = IMFMediaType_GetGUID(type, &MF_MT_SUBTYPE, &subtype)))
+ return E_INVALIDARG;
+
+ if (!IsEqualGUID(&major, &MFMediaType_Video))
+ return MF_E_INVALIDMEDIATYPE;
+
+ for (i = 0; i < ARRAY_SIZE(h264_decoder_input_types); ++i)
+ if (IsEqualGUID(&subtype, h264_decoder_input_types[i]))
+ break;
+ if (i == ARRAY_SIZE(h264_decoder_input_types))
+ return MF_E_INVALIDMEDIATYPE;
+
+ if (decoder->input_type)
+ IMFMediaType_Release(decoder->input_type);
+ IMFMediaType_AddRef((decoder->input_type = type));
+
+ return S_OK;
}
static HRESULT WINAPI h264_decoder_SetOutputType(IMFTransform *iface, DWORD id, IMFMediaType *type, DWORD flags)
--
2.34.1

View File

@ -1,196 +0,0 @@
From 71e9a26475d40d5107b803cbc1c69dbff4a18b93 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?R=C3=A9mi=20Bernon?= <rbernon@codeweavers.com>
Date: Thu, 10 Feb 2022 09:55:30 +0100
Subject: [PATCH 70/88] winegstreamer: Implement H264 decoder
GetOutputAvailableType.
For: Call of Duty III, Mortal Kombat 11, Shadow Warrior 2,
Yakuza 4 Remastered, Hard Reset Redux.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=45988
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=47084
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=49715
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=52183
CW-Bug-Id: #16839
CW-Bug-Id: #18678
CW-Bug-Id: #19362
---
dlls/winegstreamer/h264_decoder.c | 141 +++++++++++++++++++++++++++++-
1 file changed, 138 insertions(+), 3 deletions(-)
diff --git a/dlls/winegstreamer/h264_decoder.c b/dlls/winegstreamer/h264_decoder.c
index e0634bedcaa..78bf317c36f 100644
--- a/dlls/winegstreamer/h264_decoder.c
+++ b/dlls/winegstreamer/h264_decoder.c
@@ -34,6 +34,14 @@ static const GUID *h264_decoder_input_types[] =
{
&MFVideoFormat_H264,
};
+static const GUID *h264_decoder_output_types[] =
+{
+ &MFVideoFormat_NV12,
+ &MFVideoFormat_YV12,
+ &MFVideoFormat_IYUV,
+ &MFVideoFormat_I420,
+ &MFVideoFormat_YUY2,
+};
struct h264_decoder
{
@@ -47,6 +55,103 @@ static struct h264_decoder *impl_from_IMFTransform(IMFTransform *iface)
return CONTAINING_RECORD(iface, struct h264_decoder, IMFTransform_iface);
}
+static HRESULT fill_output_media_type(IMFMediaType *media_type, IMFMediaType *default_type)
+{
+ UINT32 value, width, height;
+ UINT64 value64;
+ GUID subtype;
+ HRESULT hr;
+
+ if (FAILED(hr = IMFMediaType_GetGUID(media_type, &MF_MT_SUBTYPE, &subtype)))
+ return hr;
+
+ if (FAILED(hr = IMFMediaType_GetUINT64(media_type, &MF_MT_FRAME_SIZE, &value64)))
+ {
+ if (!default_type || FAILED(hr = IMFMediaType_GetUINT64(default_type, &MF_MT_FRAME_SIZE, &value64)))
+ value64 = (UINT64)1920 << 32 | 1080;
+ if (FAILED(hr = IMFMediaType_SetUINT64(media_type, &MF_MT_FRAME_SIZE, value64)))
+ return hr;
+ }
+ width = value64 >> 32;
+ height = value64;
+
+ if (FAILED(hr = IMFMediaType_GetItem(media_type, &MF_MT_FRAME_RATE, NULL)))
+ {
+ if (!default_type || FAILED(hr = IMFMediaType_GetUINT64(default_type, &MF_MT_FRAME_RATE, &value64)))
+ value64 = (UINT64)30000 << 32 | 1001;
+ if (FAILED(hr = IMFMediaType_SetUINT64(media_type, &MF_MT_FRAME_RATE, value64)))
+ return hr;
+ }
+
+ if (FAILED(hr = IMFMediaType_GetItem(media_type, &MF_MT_PIXEL_ASPECT_RATIO, NULL)))
+ {
+ if (!default_type || FAILED(hr = IMFMediaType_GetUINT64(default_type, &MF_MT_PIXEL_ASPECT_RATIO, &value64)))
+ value64 = (UINT64)1 << 32 | 1;
+ if (FAILED(hr = IMFMediaType_SetUINT64(media_type, &MF_MT_PIXEL_ASPECT_RATIO, value64)))
+ return hr;
+ }
+
+ if (FAILED(hr = IMFMediaType_GetItem(media_type, &MF_MT_SAMPLE_SIZE, NULL)))
+ {
+ if (!default_type || FAILED(hr = IMFMediaType_GetUINT32(default_type, &MF_MT_SAMPLE_SIZE, &value)))
+ {
+ if (IsEqualGUID(&subtype, &MFVideoFormat_YUY2))
+ value = width * height * 2;
+ else
+ value = width * height * 3 / 2;
+ }
+ if (FAILED(hr = IMFMediaType_SetUINT32(media_type, &MF_MT_SAMPLE_SIZE, value)))
+ return hr;
+ }
+
+ if (FAILED(hr = IMFMediaType_GetItem(media_type, &MF_MT_DEFAULT_STRIDE, NULL)))
+ {
+ if (!default_type || FAILED(hr = IMFMediaType_GetUINT32(default_type, &MF_MT_DEFAULT_STRIDE, &value)))
+ {
+ if (IsEqualGUID(&subtype, &MFVideoFormat_YUY2))
+ value = width * 2;
+ else
+ value = width;
+ }
+ if (FAILED(hr = IMFMediaType_SetUINT32(media_type, &MF_MT_DEFAULT_STRIDE, value)))
+ return hr;
+ }
+
+ if (FAILED(hr = IMFMediaType_GetItem(media_type, &MF_MT_INTERLACE_MODE, NULL)))
+ {
+ if (!default_type || FAILED(hr = IMFMediaType_GetUINT32(default_type, &MF_MT_INTERLACE_MODE, &value)))
+ value = MFVideoInterlace_MixedInterlaceOrProgressive;
+ if (FAILED(hr = IMFMediaType_SetUINT32(media_type, &MF_MT_INTERLACE_MODE, value)))
+ return hr;
+ }
+
+ if (FAILED(hr = IMFMediaType_GetItem(media_type, &MF_MT_ALL_SAMPLES_INDEPENDENT, NULL)))
+ {
+ if (!default_type || FAILED(hr = IMFMediaType_GetUINT32(default_type, &MF_MT_ALL_SAMPLES_INDEPENDENT, &value)))
+ value = 1;
+ if (FAILED(hr = IMFMediaType_SetUINT32(media_type, &MF_MT_ALL_SAMPLES_INDEPENDENT, value)))
+ return hr;
+ }
+
+ if (FAILED(hr = IMFMediaType_GetItem(media_type, &MF_MT_VIDEO_ROTATION, NULL)))
+ {
+ if (!default_type || FAILED(hr = IMFMediaType_GetUINT32(default_type, &MF_MT_VIDEO_ROTATION, &value)))
+ value = 0;
+ if (FAILED(hr = IMFMediaType_SetUINT32(media_type, &MF_MT_VIDEO_ROTATION, value)))
+ return hr;
+ }
+
+ if (FAILED(hr = IMFMediaType_GetItem(media_type, &MF_MT_FIXED_SIZE_SAMPLES, NULL)))
+ {
+ if (!default_type || FAILED(hr = IMFMediaType_GetUINT32(default_type, &MF_MT_FIXED_SIZE_SAMPLES, &value)))
+ value = 1;
+ if (FAILED(hr = IMFMediaType_SetUINT32(media_type, &MF_MT_FIXED_SIZE_SAMPLES, value)))
+ return hr;
+ }
+
+ return S_OK;
+}
+
static HRESULT WINAPI h264_decoder_QueryInterface(IMFTransform *iface, REFIID iid, void **out)
{
struct h264_decoder *decoder = impl_from_IMFTransform(iface);
@@ -170,8 +275,38 @@ static HRESULT WINAPI h264_decoder_GetInputAvailableType(IMFTransform *iface, DW
static HRESULT WINAPI h264_decoder_GetOutputAvailableType(IMFTransform *iface, DWORD id, DWORD index,
IMFMediaType **type)
{
- FIXME("iface %p, id %#lx, index %#lx, type %p stub!\n", iface, id, index, type);
- return E_NOTIMPL;
+ struct h264_decoder *decoder = impl_from_IMFTransform(iface);
+ IMFMediaType *media_type;
+ const GUID *output_type;
+ HRESULT hr;
+
+ TRACE("iface %p, id %#lx, index %#lx, type %p.\n", iface, id, index, type);
+
+ if (!decoder->input_type)
+ return MF_E_TRANSFORM_TYPE_NOT_SET;
+
+ *type = NULL;
+
+ if (index >= ARRAY_SIZE(h264_decoder_output_types))
+ return MF_E_NO_MORE_TYPES;
+ output_type = h264_decoder_output_types[index];
+
+ if (FAILED(hr = MFCreateMediaType(&media_type)))
+ return hr;
+
+ if (FAILED(hr = IMFMediaType_SetGUID(media_type, &MF_MT_MAJOR_TYPE, &MFMediaType_Video)))
+ goto done;
+ if (FAILED(hr = IMFMediaType_SetGUID(media_type, &MF_MT_SUBTYPE, output_type)))
+ goto done;
+
+ hr = fill_output_media_type(media_type, NULL);
+
+done:
+ if (SUCCEEDED(hr))
+ IMFMediaType_AddRef((*type = media_type));
+
+ IMFMediaType_Release(media_type);
+ return hr;
}
static HRESULT WINAPI h264_decoder_SetInputType(IMFTransform *iface, DWORD id, IMFMediaType *type, DWORD flags)
@@ -184,7 +319,7 @@ static HRESULT WINAPI h264_decoder_SetInputType(IMFTransform *iface, DWORD id, I
TRACE("iface %p, id %#lx, type %p, flags %#lx.\n", iface, id, type, flags);
if (FAILED(hr = IMFMediaType_GetGUID(type, &MF_MT_MAJOR_TYPE, &major)) ||
- FAILED(hr = IMFMediaType_GetGUID(type, &MF_MT_SUBTYPE, &subtype)))
+ FAILED(hr = IMFMediaType_GetGUID(type, &MF_MT_SUBTYPE, &subtype)))
return E_INVALIDARG;
if (!IsEqualGUID(&major, &MFMediaType_Video))
--
2.34.1

View File

@ -1,56 +0,0 @@
From 8b758c937a6e90f16488c0432601ecc98761de5e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?R=C3=A9mi=20Bernon?= <rbernon@codeweavers.com>
Date: Thu, 10 Feb 2022 09:55:46 +0100
Subject: [PATCH 71/88] winegstreamer: Implement H264 decoder
GetInputAvailableType.
Required by Shadow Warrior 2.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=45988
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=47084
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=49715
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=52183
CW-Bug-Id: #16839
CW-Bug-Id: #18678
CW-Bug-Id: #19362
---
dlls/winegstreamer/h264_decoder.c | 23 +++++++++++++++++++++--
1 file changed, 21 insertions(+), 2 deletions(-)
diff --git a/dlls/winegstreamer/h264_decoder.c b/dlls/winegstreamer/h264_decoder.c
index 78bf317c36f..7aca79e7a86 100644
--- a/dlls/winegstreamer/h264_decoder.c
+++ b/dlls/winegstreamer/h264_decoder.c
@@ -268,8 +268,27 @@ static HRESULT WINAPI h264_decoder_AddInputStreams(IMFTransform *iface, DWORD st
static HRESULT WINAPI h264_decoder_GetInputAvailableType(IMFTransform *iface, DWORD id, DWORD index,
IMFMediaType **type)
{
- FIXME("iface %p, id %#lx, index %#lx, type %p stub!\n", iface, id, index, type);
- return E_NOTIMPL;
+ IMFMediaType *media_type;
+ const GUID *subtype;
+ HRESULT hr;
+
+ TRACE("iface %p, id %#lx, index %#lx, type %p.\n", iface, id, index, type);
+
+ *type = NULL;
+
+ if (index >= ARRAY_SIZE(h264_decoder_input_types))
+ return MF_E_NO_MORE_TYPES;
+ subtype = h264_decoder_input_types[index];
+
+ if (FAILED(hr = MFCreateMediaType(&media_type)))
+ return hr;
+
+ if (SUCCEEDED(hr = IMFMediaType_SetGUID(media_type, &MF_MT_MAJOR_TYPE, &MFMediaType_Video)) &&
+ SUCCEEDED(hr = IMFMediaType_SetGUID(media_type, &MF_MT_SUBTYPE, subtype)))
+ IMFMediaType_AddRef((*type = media_type));
+
+ IMFMediaType_Release(media_type);
+ return hr;
}
static HRESULT WINAPI h264_decoder_GetOutputAvailableType(IMFTransform *iface, DWORD id, DWORD index,
--
2.34.1

View File

@ -1,93 +0,0 @@
From e1dfb79302e81c47131c820e7ee6182fc929ec22 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?R=C3=A9mi=20Bernon?= <rbernon@codeweavers.com>
Date: Thu, 10 Feb 2022 09:56:08 +0100
Subject: [PATCH 72/88] winegstreamer: Implement H264 decoder SetOutputType.
For: Call of Duty III, Mortal Kombat 11, Shadow Warrior 2,
Yakuza 4 Remastered, Hard Reset Redux.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=45988
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=47084
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=49715
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=52183
CW-Bug-Id: #16839
CW-Bug-Id: #18678
CW-Bug-Id: #19362
---
dlls/winegstreamer/h264_decoder.c | 39 +++++++++++++++++++++++++++++--
1 file changed, 37 insertions(+), 2 deletions(-)
diff --git a/dlls/winegstreamer/h264_decoder.c b/dlls/winegstreamer/h264_decoder.c
index 7aca79e7a86..2cfc1ac0d05 100644
--- a/dlls/winegstreamer/h264_decoder.c
+++ b/dlls/winegstreamer/h264_decoder.c
@@ -48,6 +48,7 @@ struct h264_decoder
IMFTransform IMFTransform_iface;
LONG refcount;
IMFMediaType *input_type;
+ IMFMediaType *output_type;
};
static struct h264_decoder *impl_from_IMFTransform(IMFTransform *iface)
@@ -192,6 +193,8 @@ static ULONG WINAPI h264_decoder_Release(IMFTransform *iface)
{
if (decoder->input_type)
IMFMediaType_Release(decoder->input_type);
+ if (decoder->output_type)
+ IMFMediaType_Release(decoder->output_type);
free(decoder);
}
@@ -350,6 +353,12 @@ static HRESULT WINAPI h264_decoder_SetInputType(IMFTransform *iface, DWORD id, I
if (i == ARRAY_SIZE(h264_decoder_input_types))
return MF_E_INVALIDMEDIATYPE;
+ if (decoder->output_type)
+ {
+ IMFMediaType_Release(decoder->output_type);
+ decoder->output_type = NULL;
+ }
+
if (decoder->input_type)
IMFMediaType_Release(decoder->input_type);
IMFMediaType_AddRef((decoder->input_type = type));
@@ -359,8 +368,34 @@ static HRESULT WINAPI h264_decoder_SetInputType(IMFTransform *iface, DWORD id, I
static HRESULT WINAPI h264_decoder_SetOutputType(IMFTransform *iface, DWORD id, IMFMediaType *type, DWORD flags)
{
- FIXME("iface %p, id %#lx, type %p, flags %#lx stub!\n", iface, id, type, flags);
- return E_NOTIMPL;
+ struct h264_decoder *decoder = impl_from_IMFTransform(iface);
+ GUID major, subtype;
+ HRESULT hr;
+ ULONG i;
+
+ TRACE("iface %p, id %#lx, type %p, flags %#lx.\n", iface, id, type, flags);
+
+ if (!decoder->input_type)
+ return MF_E_TRANSFORM_TYPE_NOT_SET;
+
+ if (FAILED(hr = IMFMediaType_GetGUID(type, &MF_MT_MAJOR_TYPE, &major)) ||
+ FAILED(hr = IMFMediaType_GetGUID(type, &MF_MT_SUBTYPE, &subtype)))
+ return hr;
+
+ if (!IsEqualGUID(&major, &MFMediaType_Video))
+ return MF_E_INVALIDMEDIATYPE;
+
+ for (i = 0; i < ARRAY_SIZE(h264_decoder_output_types); ++i)
+ if (IsEqualGUID(&subtype, h264_decoder_output_types[i]))
+ break;
+ if (i == ARRAY_SIZE(h264_decoder_output_types))
+ return MF_E_INVALIDMEDIATYPE;
+
+ if (decoder->output_type)
+ IMFMediaType_Release(decoder->output_type);
+ IMFMediaType_AddRef((decoder->output_type = type));
+
+ return S_OK;
}
static HRESULT WINAPI h264_decoder_GetInputCurrentType(IMFTransform *iface, DWORD id, IMFMediaType **type)
--
2.34.1

View File

@ -1,50 +0,0 @@
From e186fc28c685facf9bb0c0d1b1e5aee8c9352b30 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?R=C3=A9mi=20Bernon?= <rbernon@codeweavers.com>
Date: Thu, 10 Feb 2022 09:56:23 +0100
Subject: [PATCH 73/88] winegstreamer: Implement H264 decoder
GetInputStreamInfo.
For: Call of Duty III, Mortal Kombat 11, Shadow Warrior 2,
Yakuza 4 Remastered, Hard Reset Redux.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=45988
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=47084
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=49715
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=52183
CW-Bug-Id: #16839
CW-Bug-Id: #18678
CW-Bug-Id: #19362
---
dlls/winegstreamer/h264_decoder.c | 16 ++++++++++++++--
1 file changed, 14 insertions(+), 2 deletions(-)
diff --git a/dlls/winegstreamer/h264_decoder.c b/dlls/winegstreamer/h264_decoder.c
index 2cfc1ac0d05..1ccb5f39908 100644
--- a/dlls/winegstreamer/h264_decoder.c
+++ b/dlls/winegstreamer/h264_decoder.c
@@ -225,8 +225,20 @@ static HRESULT WINAPI h264_decoder_GetStreamIDs(IMFTransform *iface, DWORD input
static HRESULT WINAPI h264_decoder_GetInputStreamInfo(IMFTransform *iface, DWORD id, MFT_INPUT_STREAM_INFO *info)
{
- FIXME("iface %p, id %#lx, info %p stub!\n", iface, id, info);
- return E_NOTIMPL;
+ struct h264_decoder *decoder = impl_from_IMFTransform(iface);
+
+ TRACE("iface %p, id %#lx, info %p.\n", iface, id, info);
+
+ if (!decoder->input_type)
+ return MF_E_TRANSFORM_TYPE_NOT_SET;
+
+ info->hnsMaxLatency = 0;
+ info->dwFlags = MFT_INPUT_STREAM_WHOLE_SAMPLES | MFT_INPUT_STREAM_SINGLE_SAMPLE_PER_BUFFER | MFT_INPUT_STREAM_FIXED_SAMPLE_SIZE;
+ info->cbSize = 0x1000;
+ info->cbMaxLookahead = 0;
+ info->cbAlignment = 0;
+
+ return S_OK;
}
static HRESULT WINAPI h264_decoder_GetOutputStreamInfo(IMFTransform *iface, DWORD id, MFT_OUTPUT_STREAM_INFO *info)
--
2.34.1

View File

@ -1,55 +0,0 @@
From a0aa60794e90bd635983dfb7158ba19bdb4e3485 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?R=C3=A9mi=20Bernon?= <rbernon@codeweavers.com>
Date: Thu, 10 Feb 2022 09:56:35 +0100
Subject: [PATCH 74/88] winegstreamer: Implement H264 decoder
GetOutputStreamInfo.
For: Call of Duty III, Mortal Kombat 11, Shadow Warrior 2,
Yakuza 4 Remastered, Hard Reset Redux.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=45988
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=47084
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=49715
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=52183
CW-Bug-Id: #16839
CW-Bug-Id: #18678
CW-Bug-Id: #19362
---
dlls/winegstreamer/h264_decoder.c | 21 +++++++++++++++++++--
1 file changed, 19 insertions(+), 2 deletions(-)
diff --git a/dlls/winegstreamer/h264_decoder.c b/dlls/winegstreamer/h264_decoder.c
index 1ccb5f39908..eadb28cdaaa 100644
--- a/dlls/winegstreamer/h264_decoder.c
+++ b/dlls/winegstreamer/h264_decoder.c
@@ -243,8 +243,25 @@ static HRESULT WINAPI h264_decoder_GetInputStreamInfo(IMFTransform *iface, DWORD
static HRESULT WINAPI h264_decoder_GetOutputStreamInfo(IMFTransform *iface, DWORD id, MFT_OUTPUT_STREAM_INFO *info)
{
- FIXME("iface %p, id %#lx, info %p stub!\n", iface, id, info);
- return E_NOTIMPL;
+ struct h264_decoder *decoder = impl_from_IMFTransform(iface);
+ IMFMediaType *media_type;
+ UINT32 sample_size;
+ HRESULT hr;
+
+ TRACE("iface %p, id %#lx, info %p.\n", iface, id, info);
+
+ if (!decoder->input_type || !decoder->output_type)
+ return MF_E_TRANSFORM_TYPE_NOT_SET;
+
+ media_type = decoder->output_type;
+
+ info->dwFlags = MFT_OUTPUT_STREAM_WHOLE_SAMPLES | MFT_OUTPUT_STREAM_SINGLE_SAMPLE_PER_BUFFER | MFT_OUTPUT_STREAM_FIXED_SAMPLE_SIZE;
+ if (FAILED(hr = IMFMediaType_GetUINT32(media_type, &MF_MT_SAMPLE_SIZE, &sample_size)))
+ sample_size = 1920 * 1080 * 2;
+ info->cbSize = sample_size;
+ info->cbAlignment = 0;
+
+ return S_OK;
}
static HRESULT WINAPI h264_decoder_GetAttributes(IMFTransform *iface, IMFAttributes **attributes)
--
2.34.1

View File

@ -1,264 +0,0 @@
From b3ce2fcb76da45fbf1683cbd518172eae8d8d277 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?R=C3=A9mi=20Bernon?= <rbernon@codeweavers.com>
Date: Fri, 21 Jan 2022 14:33:39 +0100
Subject: [PATCH 75/88] winegstreamer: Add H264 encoded format support in
wg_transform.
For: Call of Duty III, Mortal Kombat 11, Shadow Warrior 2,
Yakuza 4 Remastered, Hard Reset Redux.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=45988
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=47084
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=49715
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=52183
CW-Bug-Id: #16839
CW-Bug-Id: #18678
CW-Bug-Id: #19362
---
dlls/winegstreamer/h264_decoder.c | 36 +++++++++++++++++-
dlls/winegstreamer/mfplat.c | 37 ++++++++++++++++++
dlls/winegstreamer/unixlib.h | 8 ++++
dlls/winegstreamer/wg_transform.c | 63 +++++++++++++++++++++++++++++++
4 files changed, 143 insertions(+), 1 deletion(-)
diff --git a/dlls/winegstreamer/h264_decoder.c b/dlls/winegstreamer/h264_decoder.c
index eadb28cdaaa..b7de097fc7d 100644
--- a/dlls/winegstreamer/h264_decoder.c
+++ b/dlls/winegstreamer/h264_decoder.c
@@ -49,6 +49,8 @@ struct h264_decoder
LONG refcount;
IMFMediaType *input_type;
IMFMediaType *output_type;
+
+ struct wg_transform *wg_transform;
};
static struct h264_decoder *impl_from_IMFTransform(IMFTransform *iface)
@@ -56,6 +58,30 @@ static struct h264_decoder *impl_from_IMFTransform(IMFTransform *iface)
return CONTAINING_RECORD(iface, struct h264_decoder, IMFTransform_iface);
}
+static HRESULT try_create_wg_transform(struct h264_decoder *decoder)
+{
+ struct wg_encoded_format input_format;
+ struct wg_format output_format;
+
+ if (decoder->wg_transform)
+ wg_transform_destroy(decoder->wg_transform);
+
+ mf_media_type_to_wg_encoded_format(decoder->input_type, &input_format);
+ if (input_format.encoded_type == WG_ENCODED_TYPE_UNKNOWN)
+ return MF_E_INVALIDMEDIATYPE;
+
+ mf_media_type_to_wg_format(decoder->output_type, &output_format);
+ if (output_format.major_type == WG_MAJOR_TYPE_UNKNOWN)
+ return MF_E_INVALIDMEDIATYPE;
+
+ decoder->wg_transform = wg_transform_create(&input_format, &output_format);
+ if (decoder->wg_transform)
+ return S_OK;
+
+ WARN("Failed to create H264 wg_transform.\n");
+ return E_FAIL;
+}
+
static HRESULT fill_output_media_type(IMFMediaType *media_type, IMFMediaType *default_type)
{
UINT32 value, width, height;
@@ -191,6 +217,8 @@ static ULONG WINAPI h264_decoder_Release(IMFTransform *iface)
if (!refcount)
{
+ if (decoder->wg_transform)
+ wg_transform_destroy(decoder->wg_transform);
if (decoder->input_type)
IMFMediaType_Release(decoder->input_type);
if (decoder->output_type)
@@ -424,7 +452,13 @@ static HRESULT WINAPI h264_decoder_SetOutputType(IMFTransform *iface, DWORD id,
IMFMediaType_Release(decoder->output_type);
IMFMediaType_AddRef((decoder->output_type = type));
- return S_OK;
+ if (FAILED(hr = try_create_wg_transform(decoder)))
+ {
+ IMFMediaType_Release(decoder->output_type);
+ decoder->output_type = NULL;
+ }
+
+ return hr;
}
static HRESULT WINAPI h264_decoder_GetInputCurrentType(IMFTransform *iface, DWORD id, IMFMediaType **type)
diff --git a/dlls/winegstreamer/mfplat.c b/dlls/winegstreamer/mfplat.c
index ca26c767125..f2cdd04070d 100644
--- a/dlls/winegstreamer/mfplat.c
+++ b/dlls/winegstreamer/mfplat.c
@@ -938,6 +938,36 @@ static void mf_media_type_to_wg_encoded_format_xwma(IMFMediaType *type, struct w
memcpy(format->u.xwma.codec_data, codec_data, codec_data_len);
}
+static void mf_media_type_to_wg_encoded_format_h264(IMFMediaType *type, struct wg_encoded_format *format)
+{
+ UINT64 frame_rate, frame_size;
+ UINT32 profile, level;
+
+ format->encoded_type = WG_ENCODED_TYPE_H264;
+ format->u.h264.width = 0;
+ format->u.h264.height = 0;
+ format->u.h264.fps_n = 1;
+ format->u.h264.fps_d = 1;
+
+ if (SUCCEEDED(IMFMediaType_GetUINT64(type, &MF_MT_FRAME_SIZE, &frame_size)))
+ {
+ format->u.h264.width = (UINT32)(frame_size >> 32);
+ format->u.h264.height = (UINT32)frame_size;
+ }
+
+ if (SUCCEEDED(IMFMediaType_GetUINT64(type, &MF_MT_FRAME_RATE, &frame_rate)) && (UINT32)frame_rate)
+ {
+ format->u.h264.fps_n = (UINT32)(frame_rate >> 32);
+ format->u.h264.fps_d = (UINT32)frame_rate;
+ }
+
+ if (SUCCEEDED(IMFMediaType_GetUINT32(type, &MF_MT_MPEG2_PROFILE, &profile)))
+ format->u.h264.profile = profile;
+
+ if (SUCCEEDED(IMFMediaType_GetUINT32(type, &MF_MT_MPEG2_LEVEL, &level)))
+ format->u.h264.level = level;
+}
+
void mf_media_type_to_wg_encoded_format(IMFMediaType *type, struct wg_encoded_format *format)
{
GUID major_type, subtype;
@@ -970,6 +1000,13 @@ void mf_media_type_to_wg_encoded_format(IMFMediaType *type, struct wg_encoded_fo
else
FIXME("Unimplemented audio subtype %s.\n", debugstr_guid(&subtype));
}
+ else if (IsEqualGUID(&major_type, &MFMediaType_Video))
+ {
+ if (IsEqualGUID(&subtype, &MFVideoFormat_H264))
+ mf_media_type_to_wg_encoded_format_h264(type, format);
+ else
+ FIXME("Unimplemented audio subtype %s.\n", debugstr_guid(&subtype));
+ }
else
{
FIXME("Unimplemented major type %s.\n", debugstr_guid(&major_type));
diff --git a/dlls/winegstreamer/unixlib.h b/dlls/winegstreamer/unixlib.h
index 0df245408ee..84564008ee2 100644
--- a/dlls/winegstreamer/unixlib.h
+++ b/dlls/winegstreamer/unixlib.h
@@ -132,6 +132,7 @@ struct wg_encoded_format
WG_ENCODED_TYPE_UNKNOWN,
WG_ENCODED_TYPE_WMA,
WG_ENCODED_TYPE_XMA,
+ WG_ENCODED_TYPE_H264,
} encoded_type;
union
@@ -147,6 +148,13 @@ struct wg_encoded_format
uint32_t codec_data_len;
unsigned char codec_data[64];
} xwma;
+ struct
+ {
+ int32_t width, height;
+ uint32_t fps_n, fps_d;
+ uint32_t profile;
+ uint32_t level;
+ } h264;
} u;
};
diff --git a/dlls/winegstreamer/wg_transform.c b/dlls/winegstreamer/wg_transform.c
index 256e77429a0..2956ddf753b 100644
--- a/dlls/winegstreamer/wg_transform.c
+++ b/dlls/winegstreamer/wg_transform.c
@@ -98,6 +98,64 @@ static GstCaps *wg_format_to_caps_xwma(const struct wg_encoded_format *format)
return caps;
}
+static GstCaps *wg_format_to_caps_h264(const struct wg_encoded_format *format)
+{
+ const char *profile, *level;
+ GstCaps *caps;
+
+ caps = gst_caps_new_empty_simple("video/x-h264");
+ gst_caps_set_simple(caps, "stream-format", G_TYPE_STRING, "byte-stream", NULL);
+ gst_caps_set_simple(caps, "alignment", G_TYPE_STRING, "au", NULL);
+
+ if (format->u.h264.width)
+ gst_caps_set_simple(caps, "width", G_TYPE_INT, format->u.h264.width, NULL);
+ if (format->u.h264.height)
+ gst_caps_set_simple(caps, "height", G_TYPE_INT, format->u.h264.height, NULL);
+ if (format->u.h264.fps_n || format->u.h264.fps_d)
+ gst_caps_set_simple(caps, "framerate", GST_TYPE_FRACTION, format->u.h264.fps_n, format->u.h264.fps_d, NULL);
+
+ switch (format->u.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:
+ GST_ERROR("Unrecognized H.264 profile attribute %u.", format->u.h264.profile);
+ /* fallthrough */
+ case 0: profile = NULL;
+ }
+ if (profile)
+ gst_caps_set_simple(caps, "profile", G_TYPE_STRING, profile, NULL);
+
+ switch (format->u.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:
+ GST_ERROR("Unrecognized H.264 level attribute %u.", format->u.h264.level);
+ /* fallthrough */
+ case 0: level = NULL;
+ }
+ if (level)
+ gst_caps_set_simple(caps, "level", G_TYPE_STRING, level, NULL);
+
+ return caps;
+}
+
static GstCaps *wg_encoded_format_to_caps(const struct wg_encoded_format *format)
{
switch (format->encoded_type)
@@ -107,6 +165,8 @@ static GstCaps *wg_encoded_format_to_caps(const struct wg_encoded_format *format
case WG_ENCODED_TYPE_WMA:
case WG_ENCODED_TYPE_XMA:
return wg_format_to_caps_xwma(format);
+ case WG_ENCODED_TYPE_H264:
+ return wg_format_to_caps_h264(format);
}
assert(0);
return NULL;
@@ -286,7 +346,10 @@ NTSTATUS wg_transform_create(void *args)
!transform_append_element(transform, element, &first, &last))
goto failed;
break;
+ case WG_MAJOR_TYPE_VIDEO:
+ break;
default:
+ assert(0);
break;
}
--
2.34.1

View File

@ -1,63 +0,0 @@
From ae960b62a8e83ea1f14ac04acd876c00c4ae0b7f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?R=C3=A9mi=20Bernon?= <rbernon@codeweavers.com>
Date: Thu, 10 Feb 2022 09:56:47 +0100
Subject: [PATCH 76/88] winegstreamer: Implement H264 decoder ProcessInput.
For: Call of Duty III, Mortal Kombat 11, Shadow Warrior 2,
Yakuza 4 Remastered, Hard Reset Redux.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=45988
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=47084
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=49715
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=52183
CW-Bug-Id: #16839
CW-Bug-Id: #18678
CW-Bug-Id: #19362
---
dlls/winegstreamer/h264_decoder.c | 30 ++++++++++++++++++++++++++++--
1 file changed, 28 insertions(+), 2 deletions(-)
diff --git a/dlls/winegstreamer/h264_decoder.c b/dlls/winegstreamer/h264_decoder.c
index b7de097fc7d..268262a0f18 100644
--- a/dlls/winegstreamer/h264_decoder.c
+++ b/dlls/winegstreamer/h264_decoder.c
@@ -506,8 +506,34 @@ static HRESULT WINAPI h264_decoder_ProcessMessage(IMFTransform *iface, MFT_MESSA
static HRESULT WINAPI h264_decoder_ProcessInput(IMFTransform *iface, DWORD id, IMFSample *sample, DWORD flags)
{
- FIXME("iface %p, id %#lx, sample %p, flags %#lx stub!\n", iface, id, sample, flags);
- return E_NOTIMPL;
+ struct h264_decoder *decoder = impl_from_IMFTransform(iface);
+ IMFMediaBuffer *media_buffer;
+ MFT_INPUT_STREAM_INFO info;
+ DWORD buffer_size;
+ BYTE *buffer;
+ HRESULT hr;
+
+ TRACE("iface %p, id %#lx, sample %p, flags %#lx.\n", iface, id, sample, flags);
+
+ if (FAILED(hr = IMFTransform_GetInputStreamInfo(iface, 0, &info)))
+ return hr;
+
+ if (!decoder->wg_transform)
+ return MF_E_TRANSFORM_TYPE_NOT_SET;
+
+ if (FAILED(hr = IMFSample_ConvertToContiguousBuffer(sample, &media_buffer)))
+ return hr;
+
+ if (FAILED(hr = IMFMediaBuffer_Lock(media_buffer, &buffer, NULL, &buffer_size)))
+ goto done;
+
+ hr = wg_transform_push_data(decoder->wg_transform, buffer, buffer_size);
+
+ IMFMediaBuffer_Unlock(media_buffer);
+
+done:
+ IMFMediaBuffer_Release(media_buffer);
+ return hr;
}
static HRESULT WINAPI h264_decoder_ProcessOutput(IMFTransform *iface, DWORD flags, DWORD count,
--
2.34.1

View File

@ -1,83 +0,0 @@
From 9509bc29d7a6d0514f2573007b2aa3399f4d2095 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?R=C3=A9mi=20Bernon?= <rbernon@codeweavers.com>
Date: Thu, 10 Feb 2022 09:57:10 +0100
Subject: [PATCH 77/88] winegstreamer: Implement H264 decoder ProcessOutput.
For: Call of Duty III, Mortal Kombat 11, Shadow Warrior 2,
Yakuza 4 Remastered, Hard Reset Redux.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=45988
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=47084
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=49715
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=52183
CW-Bug-Id: #16839
CW-Bug-Id: #18678
CW-Bug-Id: #19362
---
dlls/winegstreamer/h264_decoder.c | 50 +++++++++++++++++++++++++++++--
1 file changed, 48 insertions(+), 2 deletions(-)
diff --git a/dlls/winegstreamer/h264_decoder.c b/dlls/winegstreamer/h264_decoder.c
index 268262a0f18..44d55ae061f 100644
--- a/dlls/winegstreamer/h264_decoder.c
+++ b/dlls/winegstreamer/h264_decoder.c
@@ -539,8 +539,54 @@ done:
static HRESULT WINAPI h264_decoder_ProcessOutput(IMFTransform *iface, DWORD flags, DWORD count,
MFT_OUTPUT_DATA_BUFFER *samples, DWORD *status)
{
- FIXME("iface %p, flags %#lx, count %lu, samples %p, status %p stub!\n", iface, flags, count, samples, status);
- return E_NOTIMPL;
+ struct h264_decoder *decoder = impl_from_IMFTransform(iface);
+ struct wg_sample wg_sample = {0};
+ IMFMediaBuffer *media_buffer;
+ MFT_OUTPUT_STREAM_INFO info;
+ DWORD buffer_size;
+ HRESULT hr;
+
+ TRACE("iface %p, flags %#lx, count %lu, samples %p, status %p.\n", iface, flags, count, samples, status);
+
+ if (count > 1)
+ {
+ FIXME("Not implemented count %lu\n", count);
+ return E_NOTIMPL;
+ }
+
+ if (FAILED(hr = IMFTransform_GetOutputStreamInfo(iface, 0, &info)))
+ return hr;
+
+ if (!decoder->wg_transform)
+ return MF_E_TRANSFORM_TYPE_NOT_SET;
+
+ *status = 0;
+ samples[0].dwStatus = 0;
+ if (!samples[0].pSample)
+ {
+ samples[0].dwStatus = MFT_OUTPUT_DATA_BUFFER_NO_SAMPLE;
+ return MF_E_TRANSFORM_NEED_MORE_INPUT;
+ }
+
+ if (FAILED(hr = IMFSample_ConvertToContiguousBuffer(samples[0].pSample, &media_buffer)))
+ return hr;
+
+ if (FAILED(hr = IMFMediaBuffer_Lock(media_buffer, &wg_sample.data, &buffer_size, NULL)))
+ goto done;
+ wg_sample.size = buffer_size;
+
+ if (wg_sample.size < info.cbSize)
+ hr = MF_E_BUFFERTOOSMALL;
+ else if (SUCCEEDED(hr = wg_transform_read_data(decoder->wg_transform, &wg_sample)))
+ hr = IMFMediaBuffer_SetCurrentLength(media_buffer, wg_sample.size);
+
+ IMFMediaBuffer_Unlock(media_buffer);
+
+done:
+ if (FAILED(hr))
+ IMFMediaBuffer_SetCurrentLength(media_buffer, 0);
+ IMFMediaBuffer_Release(media_buffer);
+ return hr;
}
static const IMFTransformVtbl h264_decoder_vtbl =
--
2.34.1

View File

@ -1,87 +0,0 @@
From 1ddbede0757008fc9db91f03f0fbc1c671822b9b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?R=C3=A9mi=20Bernon?= <rbernon@codeweavers.com>
Date: Fri, 21 Jan 2022 14:34:12 +0100
Subject: [PATCH 78/88] winegstreamer: Add timestamps and duration to H264
decoded samples.
For: Call of Duty III, Mortal Kombat 11, Shadow Warrior 2,
Yakuza 4 Remastered, Hard Reset Redux.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=45988
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=47084
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=49715
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=52183
CW-Bug-Id: #16839
CW-Bug-Id: #18678
CW-Bug-Id: #19362
---
dlls/winegstreamer/h264_decoder.c | 6 ++++++
dlls/winegstreamer/unixlib.h | 4 ++++
dlls/winegstreamer/wg_transform.c | 11 +++++++++++
3 files changed, 21 insertions(+)
diff --git a/dlls/winegstreamer/h264_decoder.c b/dlls/winegstreamer/h264_decoder.c
index 44d55ae061f..69e747f1dc0 100644
--- a/dlls/winegstreamer/h264_decoder.c
+++ b/dlls/winegstreamer/h264_decoder.c
@@ -578,7 +578,13 @@ static HRESULT WINAPI h264_decoder_ProcessOutput(IMFTransform *iface, DWORD flag
if (wg_sample.size < info.cbSize)
hr = MF_E_BUFFERTOOSMALL;
else if (SUCCEEDED(hr = wg_transform_read_data(decoder->wg_transform, &wg_sample)))
+ {
+ if (wg_sample.flags & WG_SAMPLE_FLAG_HAS_PTS)
+ IMFSample_SetSampleTime(samples[0].pSample, wg_sample.pts);
+ if (wg_sample.flags & WG_SAMPLE_FLAG_HAS_DURATION)
+ IMFSample_SetSampleDuration(samples[0].pSample, wg_sample.duration);
hr = IMFMediaBuffer_SetCurrentLength(media_buffer, wg_sample.size);
+ }
IMFMediaBuffer_Unlock(media_buffer);
diff --git a/dlls/winegstreamer/unixlib.h b/dlls/winegstreamer/unixlib.h
index 84564008ee2..543e92e6c0d 100644
--- a/dlls/winegstreamer/unixlib.h
+++ b/dlls/winegstreamer/unixlib.h
@@ -329,6 +329,8 @@ struct wg_transform_push_data_params
enum wg_sample_flags
{
WG_SAMPLE_FLAG_INCOMPLETE = 1,
+ WG_SAMPLE_FLAG_HAS_PTS = 2,
+ WG_SAMPLE_FLAG_HAS_DURATION = 4,
};
struct wg_sample
@@ -336,6 +338,8 @@ struct wg_sample
UINT32 flags;
BYTE *data;
UINT32 size;
+ /* pts and duration are in 100-nanosecond units. */
+ ULONGLONG pts, duration;
};
struct wg_transform_read_data_params
diff --git a/dlls/winegstreamer/wg_transform.c b/dlls/winegstreamer/wg_transform.c
index 2956ddf753b..93e777ba39a 100644
--- a/dlls/winegstreamer/wg_transform.c
+++ b/dlls/winegstreamer/wg_transform.c
@@ -489,6 +489,17 @@ NTSTATUS wg_transform_read_data(void *args)
memcpy(read_sample->data, info.data, read_sample->size);
gst_buffer_unmap(buffer, &info);
+ if (buffer->pts != GST_CLOCK_TIME_NONE)
+ {
+ read_sample->flags |= WG_SAMPLE_FLAG_HAS_PTS;
+ read_sample->pts = buffer->pts / 100;
+ }
+ if (buffer->duration != GST_CLOCK_TIME_NONE)
+ {
+ read_sample->flags |= WG_SAMPLE_FLAG_HAS_DURATION;
+ read_sample->duration = buffer->duration / 100;
+ }
+
if (info.size > read_sample->size)
{
read_sample->flags |= WG_SAMPLE_FLAG_INCOMPLETE;
--
2.34.1

View File

@ -1,285 +0,0 @@
From af85dd52165d0c5755a34c7df87cbc631c92efcc Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?R=C3=A9mi=20Bernon?= <rbernon@codeweavers.com>
Date: Thu, 10 Feb 2022 09:57:36 +0100
Subject: [PATCH 79/88] winegstreamer: Support dynamic wg_transform video
format change.
For: Call of Duty III, Mortal Kombat 11, Shadow Warrior 2,
Yakuza 4 Remastered, Hard Reset Redux.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=45988
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=47084
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=49715
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=52183
CW-Bug-Id: #16839
CW-Bug-Id: #18678
CW-Bug-Id: #19362
---
dlls/winegstreamer/h264_decoder.c | 26 ++++++++++++-
dlls/winegstreamer/unix_private.h | 2 +
dlls/winegstreamer/unixlib.h | 1 +
dlls/winegstreamer/wg_parser.c | 4 +-
dlls/winegstreamer/wg_transform.c | 61 ++++++++++++++++++++++++++++++-
5 files changed, 89 insertions(+), 5 deletions(-)
diff --git a/dlls/winegstreamer/h264_decoder.c b/dlls/winegstreamer/h264_decoder.c
index 69e747f1dc0..219790128da 100644
--- a/dlls/winegstreamer/h264_decoder.c
+++ b/dlls/winegstreamer/h264_decoder.c
@@ -51,6 +51,7 @@ struct h264_decoder
IMFMediaType *output_type;
struct wg_transform *wg_transform;
+ struct wg_format wg_format;
};
static struct h264_decoder *impl_from_IMFTransform(IMFTransform *iface)
@@ -378,7 +379,7 @@ static HRESULT WINAPI h264_decoder_GetOutputAvailableType(IMFTransform *iface, D
if (FAILED(hr = IMFMediaType_SetGUID(media_type, &MF_MT_SUBTYPE, output_type)))
goto done;
- hr = fill_output_media_type(media_type, NULL);
+ hr = fill_output_media_type(media_type, decoder->output_type);
done:
if (SUCCEEDED(hr))
@@ -427,6 +428,7 @@ static HRESULT WINAPI h264_decoder_SetOutputType(IMFTransform *iface, DWORD id,
{
struct h264_decoder *decoder = impl_from_IMFTransform(iface);
GUID major, subtype;
+ BOOL identical;
HRESULT hr;
ULONG i;
@@ -449,7 +451,13 @@ static HRESULT WINAPI h264_decoder_SetOutputType(IMFTransform *iface, DWORD id,
return MF_E_INVALIDMEDIATYPE;
if (decoder->output_type)
+ {
+ if (SUCCEEDED(hr = IMFMediaType_Compare(decoder->output_type, (IMFAttributes *)type,
+ MF_ATTRIBUTES_MATCH_THEIR_ITEMS, &identical)) && identical)
+ return S_OK;
IMFMediaType_Release(decoder->output_type);
+ }
+
IMFMediaType_AddRef((decoder->output_type = type));
if (FAILED(hr = try_create_wg_transform(decoder)))
@@ -543,6 +551,7 @@ static HRESULT WINAPI h264_decoder_ProcessOutput(IMFTransform *iface, DWORD flag
struct wg_sample wg_sample = {0};
IMFMediaBuffer *media_buffer;
MFT_OUTPUT_STREAM_INFO info;
+ IMFMediaType *media_type;
DWORD buffer_size;
HRESULT hr;
@@ -575,6 +584,7 @@ static HRESULT WINAPI h264_decoder_ProcessOutput(IMFTransform *iface, DWORD flag
goto done;
wg_sample.size = buffer_size;
+ wg_sample.format = &decoder->wg_format;
if (wg_sample.size < info.cbSize)
hr = MF_E_BUFFERTOOSMALL;
else if (SUCCEEDED(hr = wg_transform_read_data(decoder->wg_transform, &wg_sample)))
@@ -585,6 +595,20 @@ static HRESULT WINAPI h264_decoder_ProcessOutput(IMFTransform *iface, DWORD flag
IMFSample_SetSampleDuration(samples[0].pSample, wg_sample.duration);
hr = IMFMediaBuffer_SetCurrentLength(media_buffer, wg_sample.size);
}
+ else if (hr == MF_E_TRANSFORM_STREAM_CHANGE)
+ {
+ media_type = mf_media_type_from_wg_format(&decoder->wg_format);
+ IMFMediaType_SetUINT32(media_type, &MF_MT_SAMPLE_SIZE, wg_sample.size);
+ IMFMediaType_DeleteItem(media_type, &MF_MT_FRAME_RATE);
+ IMFMediaType_DeleteItem(decoder->output_type, &MF_MT_DEFAULT_STRIDE);
+ fill_output_media_type(media_type, decoder->output_type);
+
+ IMFMediaType_Release(decoder->output_type);
+ decoder->output_type = media_type;
+
+ samples[0].dwStatus |= MFT_OUTPUT_DATA_BUFFER_FORMAT_CHANGE;
+ *status |= MFT_OUTPUT_DATA_BUFFER_FORMAT_CHANGE;
+ }
IMFMediaBuffer_Unlock(media_buffer);
diff --git a/dlls/winegstreamer/unix_private.h b/dlls/winegstreamer/unix_private.h
index 1b055436ba5..88566ab1db5 100644
--- a/dlls/winegstreamer/unix_private.h
+++ b/dlls/winegstreamer/unix_private.h
@@ -26,6 +26,8 @@
extern bool init_gstreamer(void) DECLSPEC_HIDDEN;
extern GstElement *create_element(const char *name, const char *plugin_set) DECLSPEC_HIDDEN;
extern GstCaps *wg_format_to_caps(const struct wg_format *format) DECLSPEC_HIDDEN;
+extern void wg_format_from_caps(struct wg_format *format, const GstCaps *caps) DECLSPEC_HIDDEN;
+extern bool wg_format_compare(const struct wg_format *a, const struct wg_format *b) DECLSPEC_HIDDEN;
extern NTSTATUS wg_transform_create(void *args) DECLSPEC_HIDDEN;
extern NTSTATUS wg_transform_destroy(void *args) DECLSPEC_HIDDEN;
diff --git a/dlls/winegstreamer/unixlib.h b/dlls/winegstreamer/unixlib.h
index 543e92e6c0d..1beeed8f1a2 100644
--- a/dlls/winegstreamer/unixlib.h
+++ b/dlls/winegstreamer/unixlib.h
@@ -340,6 +340,7 @@ struct wg_sample
UINT32 size;
/* pts and duration are in 100-nanosecond units. */
ULONGLONG pts, duration;
+ struct wg_format *format;
};
struct wg_transform_read_data_params
diff --git a/dlls/winegstreamer/wg_parser.c b/dlls/winegstreamer/wg_parser.c
index 3217c78e864..8e64735bd64 100644
--- a/dlls/winegstreamer/wg_parser.c
+++ b/dlls/winegstreamer/wg_parser.c
@@ -311,7 +311,7 @@ static void wg_format_from_caps_video_cinepak(struct wg_format *format, const Gs
format->u.video.fps_d = fps_d;
}
-static void wg_format_from_caps(struct wg_format *format, const GstCaps *caps)
+void wg_format_from_caps(struct wg_format *format, const GstCaps *caps)
{
const GstStructure *structure = gst_caps_get_structure(caps, 0);
const char *name = gst_structure_get_name(structure);
@@ -556,7 +556,7 @@ GstCaps *wg_format_to_caps(const struct wg_format *format)
return NULL;
}
-static bool wg_format_compare(const struct wg_format *a, const struct wg_format *b)
+bool wg_format_compare(const struct wg_format *a, const struct wg_format *b)
{
if (a->major_type != b->major_type)
return false;
diff --git a/dlls/winegstreamer/wg_transform.c b/dlls/winegstreamer/wg_transform.c
index 93e777ba39a..df37b4e8543 100644
--- a/dlls/winegstreamer/wg_transform.c
+++ b/dlls/winegstreamer/wg_transform.c
@@ -56,6 +56,7 @@ struct wg_transform
GstPad *their_sink, *their_src;
pthread_mutex_t mutex;
struct list samples;
+ GstCaps *sink_caps;
};
static GstCaps *wg_format_to_caps_xwma(const struct wg_encoded_format *format)
@@ -184,7 +185,7 @@ static GstFlowReturn transform_sink_chain_cb(GstPad *pad, GstObject *parent, Gst
else
{
pthread_mutex_lock(&transform->mutex);
- if (!(sample->sample = gst_sample_new(buffer, NULL, NULL, NULL)))
+ if (!(sample->sample = gst_sample_new(buffer, transform->sink_caps, NULL, NULL)))
GST_ERROR("Failed to allocate transform sample");
list_add_tail(&transform->samples, &sample->entry);
pthread_mutex_unlock(&transform->mutex);
@@ -194,6 +195,38 @@ static GstFlowReturn transform_sink_chain_cb(GstPad *pad, GstObject *parent, Gst
return GST_FLOW_OK;
}
+static gboolean transform_sink_event_cb(GstPad *pad, GstObject *parent, GstEvent *event)
+{
+ struct wg_transform *transform = gst_pad_get_element_private(pad);
+
+ GST_INFO("transform %p, type \"%s\".", transform, GST_EVENT_TYPE_NAME(event));
+
+ switch (event->type)
+ {
+ case GST_EVENT_CAPS:
+ {
+ GstCaps *caps;
+ gchar *str;
+
+ gst_event_parse_caps(event, &caps);
+ str = gst_caps_to_string(caps);
+ GST_WARNING("Got caps \"%s\".", str);
+ g_free(str);
+
+ pthread_mutex_lock(&transform->mutex);
+ gst_caps_unref(transform->sink_caps);
+ transform->sink_caps = gst_caps_ref(caps);
+ pthread_mutex_unlock(&transform->mutex);
+ break;
+ }
+ default:
+ GST_WARNING("Ignoring \"%s\" event.", GST_EVENT_TYPE_NAME(event));
+ }
+
+ gst_event_unref(event);
+ return TRUE;
+}
+
NTSTATUS wg_transform_destroy(void *args)
{
struct wg_transform *transform = args;
@@ -311,7 +344,7 @@ NTSTATUS wg_transform_create(void *args)
GstPadTemplate *template;
const gchar *media_type;
GstSegment *segment;
- int ret;
+ int i, ret;
if (!init_gstreamer())
return E_FAIL;
@@ -329,6 +362,7 @@ NTSTATUS wg_transform_create(void *args)
raw_caps = gst_caps_new_empty_simple(media_type);
assert(raw_caps);
+ transform->sink_caps = gst_caps_copy(sink_caps);
transform->container = gst_bin_new("wg_transform");
assert(transform->container);
@@ -347,6 +381,12 @@ NTSTATUS wg_transform_create(void *args)
goto failed;
break;
case WG_MAJOR_TYPE_VIDEO:
+ if (!(element = create_element("videoconvert", "base")) ||
+ !transform_append_element(transform, element, &first, &last))
+ goto failed;
+ for (i = 0; i < gst_caps_get_size(sink_caps); ++i)
+ gst_structure_remove_fields(gst_caps_get_structure(sink_caps, i),
+ "width", "height", NULL);
break;
default:
assert(0);
@@ -377,6 +417,7 @@ NTSTATUS wg_transform_create(void *args)
assert(transform->my_sink);
gst_pad_set_element_private(transform->my_sink, transform);
+ gst_pad_set_event_function(transform->my_sink, transform_sink_event_cb);
gst_pad_set_chain_function(transform->my_sink, transform_sink_chain_cb);
if ((ret = gst_pad_link(transform->my_src, transform->their_sink)) < 0)
@@ -469,9 +510,11 @@ NTSTATUS wg_transform_read_data(void *args)
struct wg_transform *transform = params->transform;
struct wg_sample *read_sample = params->sample;
struct wg_transform_sample *transform_sample;
+ struct wg_format buffer_format;
GstBuffer *buffer;
struct list *head;
GstMapInfo info;
+ GstCaps *caps;
pthread_mutex_lock(&transform->mutex);
if (!(head = list_head(&transform->samples)))
@@ -483,6 +526,20 @@ NTSTATUS wg_transform_read_data(void *args)
transform_sample = LIST_ENTRY(head, struct wg_transform_sample, entry);
buffer = gst_sample_get_buffer(transform_sample->sample);
+ if (read_sample->format)
+ {
+ if (!(caps = gst_sample_get_caps(transform_sample->sample)))
+ caps = transform->sink_caps;
+ wg_format_from_caps(&buffer_format, caps);
+ if (!wg_format_compare(read_sample->format, &buffer_format))
+ {
+ *read_sample->format = buffer_format;
+ read_sample->size = gst_buffer_get_size(buffer);
+ pthread_mutex_unlock(&transform->mutex);
+ return MF_E_TRANSFORM_STREAM_CHANGE;
+ }
+ }
+
gst_buffer_map(buffer, &info, GST_MAP_READ);
if (read_sample->size > info.size)
read_sample->size = info.size;
--
2.34.1

View File

@ -1,44 +0,0 @@
From e4378c0f59983416570621596b875ca91048bb7c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?R=C3=A9mi=20Bernon?= <rbernon@codeweavers.com>
Date: Fri, 21 Jan 2022 21:46:08 +0100
Subject: [PATCH 81/88] winegstreamer: Use an optional h264parse wg_transform
element.
Required for Mortal Kombat 11.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=45988
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=47084
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=49715
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=52183
CW-Bug-Id: #16839
CW-Bug-Id: #18678
CW-Bug-Id: #19362
---
dlls/winegstreamer/wg_transform.c | 11 +++++++++++
1 file changed, 11 insertions(+)
diff --git a/dlls/winegstreamer/wg_transform.c b/dlls/winegstreamer/wg_transform.c
index df37b4e8543..e3b7d8ed056 100644
--- a/dlls/winegstreamer/wg_transform.c
+++ b/dlls/winegstreamer/wg_transform.c
@@ -366,6 +366,17 @@ NTSTATUS wg_transform_create(void *args)
transform->container = gst_bin_new("wg_transform");
assert(transform->container);
+ switch (input_format.encoded_type)
+ {
+ case WG_ENCODED_TYPE_H264:
+ if ((element = create_element("h264parse", "base")) &&
+ !transform_append_element(transform, element, &first, &last))
+ goto failed;
+ break;
+ default:
+ break;
+ }
+
if (!(element = try_create_transform(src_caps, raw_caps)) ||
!transform_append_element(transform, element, &first, &last))
goto failed;
--
2.34.1