mirror of
https://gitlab.winehq.org/wine/wine-staging.git
synced 2024-11-21 16:46:54 -08:00
mfplat-streaming-support: Remove transform patches already implemented or superseded upstream.
This commit is contained in:
parent
34b3ffed35
commit
73351fd593
@ -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, ¶ms);
|
||||
}
|
||||
|
||||
-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, ¶ms))
|
||||
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
|
||||
|
@ -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, ¶ms);
|
||||
}
|
||||
|
||||
-struct wg_transform *wg_transform_create(void)
|
||||
-{
|
||||
- struct wg_transform_create_params params = {0};
|
||||
-
|
||||
- if (__wine_unix_call(unix_handle, unix_wg_transform_create, ¶ms))
|
||||
- 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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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, ¶ms);
|
||||
}
|
||||
|
||||
+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
|
||||
|
@ -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, ¶ms);
|
||||
}
|
||||
|
||||
+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, ¶ms);
|
||||
+}
|
||||
+
|
||||
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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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, ¶ms))
|
||||
+ 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
|
||||
|
@ -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
|
||||
|
@ -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, ¶ms))
|
||||
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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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, ¶ms);
|
||||
+}
|
||||
+
|
||||
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
|
||||
|
@ -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, ¶ms);
|
||||
}
|
||||
|
||||
+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, ¶ms);
|
||||
+}
|
||||
+
|
||||
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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user