[PATCH v2 3/5] winegstreamer: Introduce a new custom memory allocator.
Rémi Bernon
wine at gitlab.winehq.org
Wed Jun 8 04:09:37 CDT 2022
From: Rémi Bernon <rbernon at codeweavers.com>
Signed-off-by: Rémi Bernon <rbernon at codeweavers.com>
---
dlls/winegstreamer/Makefile.in | 1 +
dlls/winegstreamer/unix_private.h | 3 +
dlls/winegstreamer/wg_allocator.c | 162 ++++++++++++++++++++++++++++++
dlls/winegstreamer/wg_transform.c | 12 ++-
4 files changed, 176 insertions(+), 2 deletions(-)
create mode 100644 dlls/winegstreamer/wg_allocator.c
diff --git a/dlls/winegstreamer/Makefile.in b/dlls/winegstreamer/Makefile.in
index e4c2636d02d..50f4dc861d4 100644
--- a/dlls/winegstreamer/Makefile.in
+++ b/dlls/winegstreamer/Makefile.in
@@ -14,6 +14,7 @@ C_SRCS = \
mfplat.c \
quartz_parser.c \
quartz_transform.c \
+ wg_allocator.c \
wg_format.c \
wg_parser.c \
wg_transform.c \
diff --git a/dlls/winegstreamer/unix_private.h b/dlls/winegstreamer/unix_private.h
index 7bce8263aaf..16615ef0833 100644
--- a/dlls/winegstreamer/unix_private.h
+++ b/dlls/winegstreamer/unix_private.h
@@ -37,4 +37,7 @@ 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;
+extern GstAllocator *wg_allocator_create(void) DECLSPEC_HIDDEN;
+extern void wg_allocator_destroy(GstAllocator *allocator) DECLSPEC_HIDDEN;
+
#endif /* __WINE_WINEGSTREAMER_UNIX_PRIVATE_H */
diff --git a/dlls/winegstreamer/wg_allocator.c b/dlls/winegstreamer/wg_allocator.c
new file mode 100644
index 00000000000..90dada288ae
--- /dev/null
+++ b/dlls/winegstreamer/wg_allocator.c
@@ -0,0 +1,162 @@
+/*
+ * GStreamer memory allocator
+ *
+ * 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 <gst/gst.h>
+#include <gst/video/video.h>
+#include <gst/audio/audio.h>
+
+#include "unix_private.h"
+
+GST_DEBUG_CATEGORY_EXTERN(wine);
+#define GST_CAT_DEFAULT wine
+
+typedef struct
+{
+ GstMemory parent;
+
+ GstMemory *unix_memory;
+ GstMapInfo unix_map_info;
+} WgMemory;
+
+typedef struct
+{
+ GstAllocator parent;
+} WgAllocator;
+
+typedef struct
+{
+ GstAllocatorClass parent_class;
+} WgAllocatorClass;
+
+G_DEFINE_TYPE(WgAllocator, wg_allocator, GST_TYPE_ALLOCATOR);
+
+static gpointer wg_allocator_map(GstMemory *gst_memory, GstMapInfo *info, gsize maxsize)
+{
+ WgMemory *memory = (WgMemory *)gst_memory;
+
+ if (gst_memory->parent)
+ return wg_allocator_map(gst_memory->parent, info, maxsize);
+
+ GST_LOG("memory %p, info %p, maxsize %#zx", memory, info, maxsize);
+
+ info->data = memory->unix_map_info.data;
+
+ GST_INFO("Mapped memory %p to %p", memory, info->data);
+ return info->data;
+}
+
+static void wg_allocator_unmap(GstMemory *gst_memory, GstMapInfo *info)
+{
+ WgMemory *memory = (WgMemory *)gst_memory;
+
+ if (gst_memory->parent)
+ return wg_allocator_unmap(gst_memory->parent, info);
+
+ GST_LOG("memory %p, info %p", memory, info);
+}
+
+static void wg_allocator_init(WgAllocator *allocator)
+{
+ GST_LOG("allocator %p", allocator);
+
+ allocator->parent.mem_type = "Wine";
+
+ allocator->parent.mem_map_full = wg_allocator_map;
+ allocator->parent.mem_unmap_full = wg_allocator_unmap;
+
+ GST_OBJECT_FLAG_SET(allocator, GST_ALLOCATOR_FLAG_CUSTOM_ALLOC);
+}
+
+static void wg_allocator_finalize(GObject *object)
+{
+ WgAllocator *allocator = (WgAllocator *)object;
+
+ GST_LOG("allocator %p", allocator);
+
+ G_OBJECT_CLASS(wg_allocator_parent_class)->finalize(object);
+}
+
+static GstMemory *wg_allocator_alloc(GstAllocator *gst_allocator, gsize size,
+ GstAllocationParams *params)
+{
+ WgAllocator *allocator = (WgAllocator *)gst_allocator;
+ WgMemory *memory;
+
+ GST_LOG("allocator %p, size %#zx, params %p", allocator, size, params);
+
+ memory = g_slice_new0(WgMemory);
+ gst_memory_init(GST_MEMORY_CAST(memory), 0, GST_ALLOCATOR_CAST(allocator),
+ NULL, size, 0, 0, size);
+ memory->unix_memory = gst_allocator_alloc(NULL, size, params);
+ gst_memory_map(memory->unix_memory, &memory->unix_map_info, GST_MAP_WRITE);
+
+ GST_INFO("Allocated memory %p, unix_memory %p, data %p", memory, memory->unix_memory,
+ memory->unix_map_info.data);
+ return (GstMemory *)memory;
+}
+
+static void wg_allocator_free(GstAllocator *gst_allocator, GstMemory *gst_memory)
+{
+ WgAllocator *allocator = (WgAllocator *)gst_allocator;
+ WgMemory *memory = (WgMemory *)gst_memory;
+
+ GST_LOG("allocator %p, memory %p", allocator, memory);
+
+ gst_memory_unmap(memory->unix_memory, &memory->unix_map_info);
+ gst_memory_unref(memory->unix_memory);
+ g_slice_free(WgMemory, memory);
+}
+
+static void wg_allocator_class_init(WgAllocatorClass *klass)
+{
+ GstAllocatorClass *parent_class = (GstAllocatorClass *)klass;
+ GObjectClass *root_class = (GObjectClass *)klass;
+
+ GST_LOG("klass %p", klass);
+
+ parent_class->alloc = wg_allocator_alloc;
+ parent_class->free = wg_allocator_free;
+ root_class->finalize = wg_allocator_finalize;
+}
+
+GstAllocator *wg_allocator_create(void)
+{
+ return g_object_new(wg_allocator_get_type(), NULL);
+}
+
+void wg_allocator_destroy(GstAllocator *gst_allocator)
+{
+ WgAllocator *allocator = (WgAllocator *)gst_allocator;
+
+ GST_LOG("allocator %p", allocator);
+
+ g_object_unref(allocator);
+
+ GST_INFO("Destroyed buffer allocator %p", allocator);
+}
diff --git a/dlls/winegstreamer/wg_transform.c b/dlls/winegstreamer/wg_transform.c
index fb852b4cf3d..c87536e5fbb 100644
--- a/dlls/winegstreamer/wg_transform.c
+++ b/dlls/winegstreamer/wg_transform.c
@@ -47,6 +47,7 @@ GST_DEBUG_CATEGORY_EXTERN(wine);
struct wg_transform
{
GstElement *container;
+ GstAllocator *allocator;
GstPad *my_src, *my_sink;
GstPad *their_sink, *their_src;
GstSegment segment;
@@ -152,6 +153,7 @@ static gboolean transform_sink_query_cb(GstPad *pad, GstObject *parent, GstQuery
gst_buffer_pool_config_set_params(config, caps,
info.size, 0, 0);
+ gst_buffer_pool_config_set_allocator(config, transform->allocator, NULL);
if (!gst_buffer_pool_set_config(pool, config))
GST_ERROR("Failed to set pool %p config.", pool);
}
@@ -161,9 +163,10 @@ static gboolean transform_sink_query_cb(GstPad *pad, GstObject *parent, GstQuery
GST_ERROR("Pool %p failed to activate.", pool);
gst_query_add_allocation_pool(query, pool, info.size, 0, 0);
+ gst_query_add_allocation_param(query, transform->allocator, NULL);
- GST_INFO("Proposing pool %p, buffer size %#zx, for query %p.",
- pool, info.size, query);
+ GST_INFO("Proposing pool %p, buffer size %#zx, allocator %p, for query %p.",
+ pool, info.size, transform->allocator, query);
g_object_unref(pool);
return true;
@@ -221,6 +224,7 @@ NTSTATUS wg_transform_destroy(void *args)
while ((sample = gst_atomic_queue_pop(transform->output_queue)))
gst_sample_unref(sample);
+ wg_allocator_destroy(transform->allocator);
g_object_unref(transform->their_sink);
g_object_unref(transform->their_src);
g_object_unref(transform->container);
@@ -325,6 +329,8 @@ NTSTATUS wg_transform_create(void *args)
goto out;
if (!(transform->output_queue = gst_atomic_queue_new(8)))
goto out;
+ if (!(transform->allocator = wg_allocator_create()))
+ goto out;
transform->input_max_length = 1;
transform->output_plane_align = 0;
@@ -481,6 +487,8 @@ out:
gst_object_unref(transform->my_src);
if (src_caps)
gst_caps_unref(src_caps);
+ if (transform->allocator)
+ wg_allocator_destroy(transform->allocator);
if (transform->output_queue)
gst_atomic_queue_unref(transform->output_queue);
if (transform->input)
--
GitLab
https://gitlab.winehq.org/wine/wine/-/merge_requests/197
More information about the wine-devel
mailing list