Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=51931 Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=52391 Signed-off-by: Rémi Bernon rbernon@codeweavers.com ---
v2: Move the format helpers to a dedicated source, use a separate major format in the wg_format struct for WMA format.
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 c53e914e246..52295418f0f 100644 --- a/dlls/winegstreamer/Makefile.in +++ b/dlls/winegstreamer/Makefile.in @@ -13,6 +13,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 222bce3b2c7..df82b229143 100644 --- a/dlls/winegstreamer/gst_private.h +++ b/dlls/winegstreamer/gst_private.h @@ -96,6 +96,9 @@ uint64_t wg_parser_stream_get_duration(struct wg_parser_stream *stream) DECLSPEC 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) DECLSPEC_HIDDEN;
+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) DECLSPEC_HIDDEN; diff --git a/dlls/winegstreamer/main.c b/dlls/winegstreamer/main.c index 260dd208e2f..f23fa3abcdf 100644 --- a/dlls/winegstreamer/main.c +++ b/dlls/winegstreamer/main.c @@ -254,6 +254,20 @@ 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 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 82bb534b938..c8b98da3a64 100644 --- a/dlls/winegstreamer/unixlib.h +++ b/dlls/winegstreamer/unixlib.h @@ -217,6 +217,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, @@ -245,6 +250,9 @@ 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 013566b25e9..ac8c5a2b95c 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); @@ -1963,6 +1963,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[] = @@ -1973,11 +1983,10 @@ 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 (pthread_once(&once, init_gstreamer_once)) + if (!init_gstreamer()) return E_FAIL;
if (!(parser = calloc(1, sizeof(*parser)))) @@ -2044,4 +2053,7 @@ 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 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 78316059052..3b051230a9e 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: