[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