From: Rémi Bernon rbernon@codeweavers.com
--- MAINTAINERS | 1 + dlls/winegstreamer/Makefile.in | 1 + dlls/winegstreamer/gst_private.h | 3 + dlls/winegstreamer/main.c | 25 ++++++++ dlls/winegstreamer/media_source.c | 15 ++++- dlls/winegstreamer/unix_private.h | 5 ++ dlls/winegstreamer/unixlib.h | 9 +++ dlls/winegstreamer/wg_parser.c | 6 ++ dlls/winegstreamer/wg_source.c | 94 +++++++++++++++++++++++++++++++ 9 files changed, 158 insertions(+), 1 deletion(-) create mode 100644 dlls/winegstreamer/wg_source.c
diff --git a/MAINTAINERS b/MAINTAINERS index 29fa77c0404..64c696ddc09 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -217,6 +217,7 @@ F: dlls/winegstreamer/mfplat.c F: dlls/winegstreamer/resampler.c F: dlls/winegstreamer/video_decoder.c F: dlls/winegstreamer/video_processor.c +F: dlls/winegstreamer/wg_source.c F: dlls/winegstreamer/wg_sample.c F: dlls/winegstreamer/wg_transform.c F: dlls/winegstreamer/wma_decoder.c diff --git a/dlls/winegstreamer/Makefile.in b/dlls/winegstreamer/Makefile.in index 63ca3f61fdf..40ff4515281 100644 --- a/dlls/winegstreamer/Makefile.in +++ b/dlls/winegstreamer/Makefile.in @@ -27,6 +27,7 @@ SOURCES = \ wg_muxer.c \ wg_parser.c \ wg_sample.c \ + wg_source.c \ wg_transform.c \ winegstreamer_classes.idl \ wm_reader.c \ diff --git a/dlls/winegstreamer/gst_private.h b/dlls/winegstreamer/gst_private.h index 0f7d945ba37..6380b8fb7ff 100644 --- a/dlls/winegstreamer/gst_private.h +++ b/dlls/winegstreamer/gst_private.h @@ -104,6 +104,9 @@ char *wg_parser_stream_get_tag(wg_parser_stream_t stream, enum wg_parser_tag tag void wg_parser_stream_seek(wg_parser_stream_t stream, double rate, uint64_t start_pos, uint64_t stop_pos, DWORD start_flags, DWORD stop_flags);
+HRESULT wg_source_create(wg_source_t *out); +void wg_source_destroy(wg_source_t source); + HRESULT wg_transform_create_mf(IMFMediaType *input_type, IMFMediaType *output_type, const struct wg_transform_attrs *attrs, wg_transform_t *transform); HRESULT wg_transform_create_quartz(const AM_MEDIA_TYPE *input_format, const AM_MEDIA_TYPE *output_format, diff --git a/dlls/winegstreamer/main.c b/dlls/winegstreamer/main.c index 2d144a6f71f..92a44be0c96 100644 --- a/dlls/winegstreamer/main.c +++ b/dlls/winegstreamer/main.c @@ -435,6 +435,31 @@ void wg_parser_stream_seek(wg_parser_stream_t stream, double rate, WINE_UNIX_CALL(unix_wg_parser_stream_seek, ¶ms); }
+HRESULT wg_source_create(wg_source_t *out) +{ + struct wg_source_create_params params = {0}; + NTSTATUS status; + + TRACE("out %p\n", out); + + if ((status = WINE_UNIX_CALL(unix_wg_source_create, ¶ms))) + WARN("wg_source_create returned status %#lx\n", status); + else + { + TRACE("Returning source %#I64x.\n", params.source); + *out = params.source; + } + + return HRESULT_FROM_NT(status); +} + +void wg_source_destroy(wg_source_t source) +{ + TRACE("source %#I64x.\n", source); + + WINE_UNIX_CALL(unix_wg_source_destroy, &source); +} + HRESULT wg_transform_create_mf(IMFMediaType *input_type, IMFMediaType *output_type, const struct wg_transform_attrs *attrs, wg_transform_t *transform) { diff --git a/dlls/winegstreamer/media_source.c b/dlls/winegstreamer/media_source.c index 030d0c1b9a2..0de82d76db9 100644 --- a/dlls/winegstreamer/media_source.c +++ b/dlls/winegstreamer/media_source.c @@ -36,6 +36,8 @@ struct object_context IMFByteStream *stream; UINT64 file_size; WCHAR *url; + + wg_source_t wg_source; };
static struct object_context *impl_from_IUnknown(IUnknown *iface) @@ -78,6 +80,8 @@ static ULONG WINAPI object_context_Release(IUnknown *iface)
if (!refcount) { + if (context->wg_source) + wg_source_destroy(context->wg_source); IMFAsyncResult_Release(context->result); IMFByteStream_Release(context->stream); free(context->url); @@ -182,6 +186,7 @@ struct media_source
CRITICAL_SECTION cs;
+ wg_source_t wg_source; UINT64 file_size; wg_parser_t wg_parser; UINT64 duration; @@ -1364,6 +1369,7 @@ static ULONG WINAPI media_source_Release(IMFMediaSource *iface) IMFMediaSource_Shutdown(iface); IMFMediaEventQueue_Release(source->event_queue); IMFByteStream_Release(source->byte_stream); + wg_source_destroy(source->wg_source); wg_parser_destroy(source->wg_parser); source->cs.DebugInfo->Spare[0] = 0; DeleteCriticalSection(&source->cs); @@ -1642,6 +1648,9 @@ static HRESULT media_source_create(struct object_context *context, IMFMediaSourc InitializeCriticalSectionEx(&object->cs, 0, RTL_CRITICAL_SECTION_FLAG_FORCE_DEBUG_INFO); object->cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": cs");
+ object->wg_source = context->wg_source; + context->wg_source = 0; + if (FAILED(hr = MFCreateEventQueue(&object->event_queue))) goto fail;
@@ -1721,6 +1730,8 @@ fail: WaitForSingleObject(object->read_thread, INFINITE); CloseHandle(object->read_thread); } + if (object->wg_source) + wg_source_destroy(object->wg_source); if (object->wg_parser) wg_parser_destroy(object->wg_parser); if (object->async_commands_queue) @@ -2003,7 +2014,9 @@ static HRESULT WINAPI stream_handler_callback_Invoke(IMFAsyncCallback *iface, IM if (!state || !(context = impl_from_IUnknown(state))) return E_INVALIDARG;
- if (FAILED(hr = media_source_create(context, (IMFMediaSource **)&object))) + if (FAILED(hr = wg_source_create(&context->wg_source))) + WARN("Failed to create wg_source, hr %#lx\n", hr); + else if (FAILED(hr = media_source_create(context, (IMFMediaSource **)&object))) WARN("Failed to create media source, hr %#lx\n", hr); else { diff --git a/dlls/winegstreamer/unix_private.h b/dlls/winegstreamer/unix_private.h index b2cc036c914..52412a283ab 100644 --- a/dlls/winegstreamer/unix_private.h +++ b/dlls/winegstreamer/unix_private.h @@ -68,6 +68,11 @@ extern NTSTATUS wg_transform_drain(void *args); extern NTSTATUS wg_transform_flush(void *args); extern NTSTATUS wg_transform_notify_qos(void *args);
+/* wg_source.c */ + +extern NTSTATUS wg_source_create(void *args); +extern NTSTATUS wg_source_destroy(void *args); + /* wg_media_type.c */
static inline BOOL is_mf_video_area_empty(const MFVideoArea *area) diff --git a/dlls/winegstreamer/unixlib.h b/dlls/winegstreamer/unixlib.h index 19270bd731b..0a98aadd1ab 100644 --- a/dlls/winegstreamer/unixlib.h +++ b/dlls/winegstreamer/unixlib.h @@ -205,6 +205,7 @@ C_ASSERT(sizeof(struct wg_parser_buffer) == 32);
typedef UINT64 wg_parser_t; typedef UINT64 wg_parser_stream_t; +typedef UINT64 wg_source_t; typedef UINT64 wg_transform_t; typedef UINT64 wg_muxer_t;
@@ -329,6 +330,11 @@ struct wg_parser_stream_seek_params DWORD start_flags, stop_flags; };
+struct wg_source_create_params +{ + wg_source_t source; +}; + struct wg_transform_attrs { UINT32 output_plane_align; @@ -444,6 +450,9 @@ enum unix_funcs unix_wg_parser_stream_get_tag, unix_wg_parser_stream_seek,
+ unix_wg_source_create, + unix_wg_source_destroy, + unix_wg_transform_create, unix_wg_transform_destroy, unix_wg_transform_get_output_type, diff --git a/dlls/winegstreamer/wg_parser.c b/dlls/winegstreamer/wg_parser.c index 710cfe6a0a5..51753b1f429 100644 --- a/dlls/winegstreamer/wg_parser.c +++ b/dlls/winegstreamer/wg_parser.c @@ -1887,6 +1887,9 @@ const unixlib_entry_t __wine_unix_call_funcs[] = X(wg_parser_stream_get_tag), X(wg_parser_stream_seek),
+ X(wg_source_create), + X(wg_source_destroy), + X(wg_transform_create), X(wg_transform_destroy), X(wg_transform_get_output_type), @@ -2284,6 +2287,9 @@ const unixlib_entry_t __wine_unix_call_wow64_funcs[] = X64(wg_parser_stream_get_tag), X(wg_parser_stream_seek),
+ X(wg_source_create), + X(wg_source_destroy), + X64(wg_transform_create), X(wg_transform_destroy), X64(wg_transform_get_output_type), diff --git a/dlls/winegstreamer/wg_source.c b/dlls/winegstreamer/wg_source.c new file mode 100644 index 00000000000..52a54196ea9 --- /dev/null +++ b/dlls/winegstreamer/wg_source.c @@ -0,0 +1,94 @@ +/* + * Copyright 2023 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 <gst/base/base.h> +#include <gst/tag/tag.h> + +#include "ntstatus.h" +#define WIN32_NO_STATUS +#include "winternl.h" +#include "mferror.h" + +#include "unix_private.h" + +struct wg_source +{ + GstElement *container; +}; + +static struct wg_source *get_source(wg_source_t source) +{ + return (struct wg_source *)(ULONG_PTR)source; +} + +NTSTATUS wg_source_create(void *args) +{ + struct wg_source_create_params *params = args; + struct wg_source *source; + + if (!(source = calloc(1, sizeof(*source)))) + return STATUS_UNSUCCESSFUL; + + if (!(source->container = gst_bin_new("wg_source"))) + goto error; + + gst_element_set_state(source->container, GST_STATE_PAUSED); + if (!gst_element_get_state(source->container, NULL, NULL, -1)) + goto error; + + params->source = (wg_source_t)(ULONG_PTR)source; + GST_INFO("Created winegstreamer source %p.", source); + return STATUS_SUCCESS; + +error: + if (source->container) + { + gst_element_set_state(source->container, GST_STATE_NULL); + gst_object_unref(source->container); + } + free(source); + + GST_ERROR("Failed to create winegstreamer source."); + return STATUS_UNSUCCESSFUL; +} + +NTSTATUS wg_source_destroy(void *args) +{ + struct wg_source *source = get_source(*(wg_source_t *)args); + + GST_TRACE("source %p", source); + + gst_element_set_state(source->container, GST_STATE_NULL); + gst_object_unref(source->container); + free(source); + + return STATUS_SUCCESS; +}