From: Rémi Bernon rbernon@codeweavers.com
Signed-off-by: Rémi Bernon rbernon@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 9a5c16afe74..16c73bcbcd6 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; @@ -153,6 +154,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); } @@ -162,9 +164,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; @@ -222,6 +225,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); @@ -326,6 +330,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;
@@ -482,6 +488,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)