gstreamer/tests/check/libs/gstglmemory.c
Marijn Suijten abb026ec6a gl,video: Make ptrs to VideoInfo and (GL)AllocationParams immutable
These parameters are incorrectly regarded as mutable in G-IR making them
"incompatible" with languages that are explicit about mutability like
Rust. In order to clean up the code and expected API there, update the
signatures here, right at the source (instead of overriding them in
Gir.toml and hoping for the best).

Part-of: <https://gitlab.freedesktop.org/gstreamer/gst-plugins-base/-/merge_requests/1005>
2021-01-14 11:53:10 +00:00

536 lines
16 KiB
C

/* GStreamer
*
* unit test for state changes on all elements
*
* Copyright (C) <2012> Matthew Waters <ystreet00@gmail.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 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
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library 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.
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <gst/check/gstcheck.h>
#include <gst/gl/gl.h>
#include <stdio.h>
static GstGLDisplay *display;
static GstGLContext *context;
static void
setup (void)
{
display = gst_gl_display_new ();
context = gst_gl_context_new (display);
gst_gl_context_create (context, 0, NULL);
gst_gl_memory_init_once ();
}
static void
teardown (void)
{
gst_object_unref (display);
gst_object_unref (context);
}
/* one red rgba pixel */
static guint8 rgba_pixel[] = {
0xff, 0x00, 0x00, 0xff,
};
static const struct
{
GstVideoFormat format;
guint width;
guint height;
guint plane;
guint8 *data;
gsize size;
} formats[] = {
{
GST_VIDEO_FORMAT_RGBA, 1, 1, 0, rgba_pixel, 4}, {
GST_VIDEO_FORMAT_RGB, 1, 1, 0, rgba_pixel, 3}, {
GST_VIDEO_FORMAT_YUY2, 1, 1, 0, rgba_pixel, 1}, {
GST_VIDEO_FORMAT_I420, 1, 1, 0, rgba_pixel, 1},};
GST_START_TEST (test_allocator_alloc)
{
GstAllocator *gl_allocator;
GstMemory *mem;
gl_allocator = gst_allocator_find (GST_GL_MEMORY_ALLOCATOR_NAME);
ASSERT_WARNING (mem = gst_allocator_alloc (gl_allocator, 0, NULL));
fail_unless (mem == NULL);
gst_object_unref (gl_allocator);
}
GST_END_TEST;
GST_START_TEST (test_allocator_pbo_alloc)
{
GstAllocator *gl_allocator;
GstMemory *mem;
gl_allocator = gst_allocator_find (GST_GL_MEMORY_PBO_ALLOCATOR_NAME);
ASSERT_WARNING (mem = gst_allocator_alloc (gl_allocator, 0, NULL));
fail_unless (mem == NULL);
gst_object_unref (gl_allocator);
}
GST_END_TEST;
static GstMemory *
create_memory (const gchar * allocator_name, const GstVideoInfo * v_info,
guint plane)
{
GstAllocator *gl_allocator;
GstGLBaseMemoryAllocator *base_mem_alloc;
GstGLVideoAllocationParams *params;
GstGLMemory *gl_mem;
GstMemory *mem;
GST_DEBUG ("creating from %s texture for format %s, %ux%u plane %u",
allocator_name, GST_VIDEO_INFO_NAME (v_info),
GST_VIDEO_INFO_WIDTH (v_info), GST_VIDEO_INFO_HEIGHT (v_info), plane);
gl_allocator = gst_allocator_find (allocator_name);
fail_if (gl_allocator == NULL);
base_mem_alloc = GST_GL_BASE_MEMORY_ALLOCATOR (gl_allocator);
params = gst_gl_video_allocation_params_new (context, NULL, v_info, plane,
NULL, GST_GL_TEXTURE_TARGET_2D, GST_GL_RGBA);
/* texture creation */
mem = (GstMemory *) gst_gl_base_memory_alloc (base_mem_alloc,
(GstGLAllocationParams *) params);
gl_mem = (GstGLMemory *) mem;
fail_unless (!GST_MEMORY_FLAG_IS_SET (mem,
GST_GL_BASE_MEMORY_TRANSFER_NEED_UPLOAD));
fail_unless (!GST_MEMORY_FLAG_IS_SET (mem,
GST_GL_BASE_MEMORY_TRANSFER_NEED_DOWNLOAD));
fail_unless_equals_int (TRUE, gst_video_info_is_equal (v_info,
&gl_mem->info));
fail_unless_equals_int (plane, gl_mem->plane);
fail_if (gl_mem->mem.context != context);
fail_if (gl_mem->tex_id == 0);
gst_gl_allocation_params_free ((GstGLAllocationParams *) params);
gst_object_unref (gl_allocator);
return mem;
}
GST_START_TEST (test_allocator_create)
{
int i;
for (i = 0; i < G_N_ELEMENTS (formats); i++) {
GstVideoInfo v_info;
GstMemory *mem;
gst_video_info_set_format (&v_info, formats[i].format, formats[i].width,
formats[i].height);
mem = create_memory (GST_GL_MEMORY_ALLOCATOR_NAME, &v_info,
formats[i].plane);
gst_memory_unref (mem);
mem = create_memory (GST_GL_MEMORY_PBO_ALLOCATOR_NAME, &v_info,
formats[i].plane);
gst_memory_unref (mem);
}
}
GST_END_TEST;
GST_START_TEST (test_memory_copy)
{
int i;
for (i = 0; i < G_N_ELEMENTS (formats); i++) {
GstVideoInfo v_info;
GstMemory *mem, *mem2;
GstGLMemory *gl_mem, *gl_mem2;
gst_video_info_set_format (&v_info, formats[i].format, formats[i].width,
formats[i].height);
mem = create_memory (GST_GL_MEMORY_PBO_ALLOCATOR_NAME, &v_info,
formats[i].plane);
gl_mem = (GstGLMemory *) mem;
mem2 = gst_memory_copy (mem, 0, -1);
gl_mem2 = (GstGLMemory *) mem;
fail_unless (gl_mem->mem.context == context);
fail_unless_equals_int (gl_mem->tex_id, gl_mem2->tex_id);
fail_unless_equals_int (gl_mem->tex_target, gl_mem2->tex_target);
fail_unless_equals_int (gl_mem->tex_format, gl_mem2->tex_format);
fail_unless_equals_int (TRUE, gst_video_info_is_equal (&gl_mem2->info,
&gl_mem->info));
fail_unless_equals_int (gl_mem->plane, gl_mem2->plane);
gst_memory_unref (mem);
gst_memory_unref (mem2);
}
}
GST_END_TEST;
static GstMemory *
wrap_raw_data (const gchar * allocator_name, const GstVideoInfo * v_info,
guint plane, guint8 * data)
{
GstAllocator *gl_allocator;
GstGLBaseMemoryAllocator *base_mem_alloc;
GstGLVideoAllocationParams *params;
GstMemory *mem;
GstGLMemory *gl_mem;
GstGLFormat gl_format;
GST_DEBUG ("wrapping from %s data pointer %p for format %s, %ux%u plane %u",
allocator_name, data, GST_VIDEO_INFO_NAME (v_info),
GST_VIDEO_INFO_WIDTH (v_info), GST_VIDEO_INFO_HEIGHT (v_info), plane);
gl_allocator = gst_allocator_find (allocator_name);
fail_if (gl_allocator == NULL);
base_mem_alloc = GST_GL_BASE_MEMORY_ALLOCATOR (gl_allocator);
gl_format = gst_gl_format_from_video_info (context, v_info, plane);
params = gst_gl_video_allocation_params_new_wrapped_data (context, NULL,
v_info, plane, NULL, GST_GL_TEXTURE_TARGET_2D,
gl_format, data, NULL, NULL);
mem =
(GstMemory *) gst_gl_base_memory_alloc (base_mem_alloc,
(GstGLAllocationParams *) params);
gl_mem = (GstGLMemory *) mem;
fail_if (mem == NULL);
fail_unless (GST_MEMORY_FLAG_IS_SET (mem,
GST_GL_BASE_MEMORY_TRANSFER_NEED_UPLOAD));
fail_unless (!GST_MEMORY_FLAG_IS_SET (mem,
GST_GL_BASE_MEMORY_TRANSFER_NEED_DOWNLOAD));
fail_unless_equals_int (TRUE, gst_video_info_is_equal (v_info,
&gl_mem->info));
fail_unless_equals_int (gl_mem->plane, plane);
gst_gl_allocation_params_free ((GstGLAllocationParams *) params);
gst_object_unref (gl_allocator);
return mem;
}
GST_START_TEST (test_wrap_raw)
{
int i;
for (i = 0; i < G_N_ELEMENTS (formats); i++) {
GstVideoInfo v_info;
GstMemory *mem;
GstGLMemory *gl_mem;
GstMapInfo map_info;
gst_video_info_set_format (&v_info, formats[i].format, formats[i].width,
formats[i].height);
mem = wrap_raw_data (GST_GL_MEMORY_PBO_ALLOCATOR_NAME, &v_info,
formats[i].plane, formats[i].data);
gl_mem = (GstGLMemory *) mem;
fail_unless (gl_mem->mem.context == context);
fail_unless (gst_memory_map (mem, &map_info, GST_MAP_READ));
fail_unless (memcmp (map_info.data, formats[i].data, formats[i].size) == 0);
gst_memory_unmap (mem, &map_info);
gst_memory_unref (mem);
}
}
GST_END_TEST;
static GstMemory *
wrap_gl_memory (GstGLMemory * gl_mem)
{
GstGLBaseMemoryAllocator *base_mem_alloc;
GstGLVideoAllocationParams *params;
GstMemory *mem, *mem2;
GstGLMemory *gl_mem2;
mem = (GstMemory *) gl_mem;
base_mem_alloc = GST_GL_BASE_MEMORY_ALLOCATOR (mem->allocator);
GST_DEBUG ("wrapping from %s %" GST_PTR_FORMAT " for format %s, %ux%u "
"plane %u", mem->allocator->mem_type, gl_mem,
GST_VIDEO_INFO_NAME (&gl_mem->info), GST_VIDEO_INFO_WIDTH (&gl_mem->info),
GST_VIDEO_INFO_HEIGHT (&gl_mem->info), gl_mem->plane);
params = gst_gl_video_allocation_params_new_wrapped_texture (context, NULL,
&gl_mem->info, gl_mem->plane, NULL, gl_mem->tex_target,
gl_mem->tex_format, gl_mem->tex_id, NULL, NULL);
mem2 =
(GstMemory *) gst_gl_base_memory_alloc (base_mem_alloc,
(GstGLAllocationParams *) params);
gl_mem2 = (GstGLMemory *) mem2;
fail_if (mem == NULL);
fail_unless (!GST_MEMORY_FLAG_IS_SET (mem2,
GST_GL_BASE_MEMORY_TRANSFER_NEED_UPLOAD));
fail_unless (GST_MEMORY_FLAG_IS_SET (mem2,
GST_GL_BASE_MEMORY_TRANSFER_NEED_DOWNLOAD));
fail_unless (gl_mem->mem.context == context);
fail_unless_equals_int (gl_mem->tex_id, gl_mem2->tex_id);
fail_unless_equals_int (gl_mem->tex_target, gl_mem2->tex_target);
fail_unless_equals_int (gl_mem->tex_format, gl_mem2->tex_format);
fail_unless_equals_int (TRUE, gst_video_info_is_equal (&gl_mem2->info,
&gl_mem->info));
fail_unless_equals_int (gl_mem->plane, gl_mem2->plane);
gst_gl_allocation_params_free ((GstGLAllocationParams *) params);
return mem2;
}
GST_START_TEST (test_wrap_gl_memory)
{
int i;
for (i = 0; i < G_N_ELEMENTS (formats); i++) {
GstVideoInfo v_info;
GstMemory *mem, *mem2;
GstGLMemory *gl_mem;
gst_video_info_set_format (&v_info, formats[i].format, formats[i].width,
formats[i].height);
mem = create_memory (GST_GL_MEMORY_PBO_ALLOCATOR_NAME, &v_info,
formats[i].plane);
gl_mem = (GstGLMemory *) mem;
mem2 = wrap_gl_memory (gl_mem);
gst_memory_unref (mem);
gst_memory_unref (mem2);
}
}
GST_END_TEST;
GST_START_TEST (test_wrap_data_copy_into)
{
int i;
/* FIXME: in GLES2 only supported with RGBA */
for (i = 0; i < 1 /*G_N_ELEMENTS (formats) */ ; i++) {
GstVideoInfo v_info;
GstMemory *mem, *mem2;
GstGLMemory *gl_mem, *gl_mem2;
GstMapInfo map_info;
gst_video_info_set_format (&v_info, formats[i].format, formats[i].width,
formats[i].height);
/* wrap some data */
mem = wrap_raw_data (GST_GL_MEMORY_PBO_ALLOCATOR_NAME, &v_info,
formats[i].plane, formats[i].data);
gl_mem = (GstGLMemory *) mem;
mem2 = create_memory (GST_GL_MEMORY_PBO_ALLOCATOR_NAME, &v_info,
formats[i].plane);
gl_mem2 = (GstGLMemory *) mem2;
fail_unless (gst_memory_map (mem, &map_info, GST_MAP_READ | GST_MAP_GL));
/* copy wrapped data into another texture */
fail_unless (gst_gl_memory_copy_into (gl_mem,
gl_mem2->tex_id, GST_GL_TEXTURE_TARGET_2D, gl_mem2->tex_format,
formats[i].width, formats[i].height));
GST_MINI_OBJECT_FLAG_SET (mem2, GST_GL_BASE_MEMORY_TRANSFER_NEED_DOWNLOAD);
fail_unless (!GST_MEMORY_FLAG_IS_SET (mem,
GST_GL_BASE_MEMORY_TRANSFER_NEED_UPLOAD));
fail_unless (!GST_MEMORY_FLAG_IS_SET (mem,
GST_GL_BASE_MEMORY_TRANSFER_NEED_DOWNLOAD));
fail_unless (!GST_MEMORY_FLAG_IS_SET (mem2,
GST_GL_BASE_MEMORY_TRANSFER_NEED_UPLOAD));
fail_unless (GST_MEMORY_FLAG_IS_SET (mem2,
GST_GL_BASE_MEMORY_TRANSFER_NEED_DOWNLOAD));
gst_memory_unmap (mem, &map_info);
/* check copied texture is the same as the wrapped data */
fail_unless (gst_memory_map (mem2, &map_info, GST_MAP_READ));
fail_unless (memcmp (map_info.data, formats[i].data, formats[i].size) == 0);
gst_memory_unmap (mem2, &map_info);
gst_memory_unref (mem);
gst_memory_unref (mem2);
}
}
GST_END_TEST;
GST_START_TEST (test_transfer_state)
{
GstVideoInfo v_info;
GstMapInfo map_info;
GstMemory *mem;
gst_video_info_set_format (&v_info, GST_VIDEO_FORMAT_RGBA, 1, 1);
mem = create_memory (GST_GL_MEMORY_PBO_ALLOCATOR_NAME, &v_info, 0);
/* initial state is no transfer needed */
fail_unless (!GST_MEMORY_FLAG_IS_SET (mem,
GST_GL_BASE_MEMORY_TRANSFER_NEED_UPLOAD));
fail_unless (!GST_MEMORY_FLAG_IS_SET (mem,
GST_GL_BASE_MEMORY_TRANSFER_NEED_DOWNLOAD));
GST_DEBUG ("read-only map");
gst_memory_map (mem, &map_info, GST_MAP_READ);
gst_memory_unmap (mem, &map_info);
/* read map does not change transfer state */
fail_unless (!GST_MEMORY_FLAG_IS_SET (mem,
GST_GL_BASE_MEMORY_TRANSFER_NEED_UPLOAD));
fail_unless (!GST_MEMORY_FLAG_IS_SET (mem,
GST_GL_BASE_MEMORY_TRANSFER_NEED_DOWNLOAD));
GST_DEBUG ("read/GL-only map");
gst_memory_map (mem, &map_info, GST_MAP_READ | GST_MAP_GL);
gst_memory_unmap (mem, &map_info);
/* read | GL map does not change transfer state */
fail_unless (!GST_MEMORY_FLAG_IS_SET (mem,
GST_GL_BASE_MEMORY_TRANSFER_NEED_UPLOAD));
fail_unless (!GST_MEMORY_FLAG_IS_SET (mem,
GST_GL_BASE_MEMORY_TRANSFER_NEED_DOWNLOAD));
GST_DEBUG ("write-only map");
gst_memory_map (mem, &map_info, GST_MAP_WRITE);
gst_memory_unmap (mem, &map_info);
/* write map causes need-upload */
fail_unless (GST_MEMORY_FLAG_IS_SET (mem,
GST_GL_BASE_MEMORY_TRANSFER_NEED_UPLOAD));
fail_unless (!GST_MEMORY_FLAG_IS_SET (mem,
GST_GL_BASE_MEMORY_TRANSFER_NEED_DOWNLOAD));
GST_DEBUG ("write/GL-only map");
gst_memory_map (mem, &map_info, GST_MAP_WRITE | GST_MAP_GL);
gst_memory_unmap (mem, &map_info);
/* write | GL map from need-upload causes only need-download */
fail_unless (!GST_MEMORY_FLAG_IS_SET (mem,
GST_GL_BASE_MEMORY_TRANSFER_NEED_UPLOAD));
fail_unless (GST_MEMORY_FLAG_IS_SET (mem,
GST_GL_BASE_MEMORY_TRANSFER_NEED_DOWNLOAD));
gst_memory_unref (mem);
}
GST_END_TEST;
GST_START_TEST (test_separate_upload_transfer)
{
GstVideoInfo v_info;
GstMemory *mem;
GstMapInfo info;
gst_video_info_set_format (&v_info, GST_VIDEO_FORMAT_RGBA, 1, 1);
mem =
wrap_raw_data (GST_GL_MEMORY_PBO_ALLOCATOR_NAME, &v_info, 0, rgba_pixel);
gst_gl_memory_pbo_upload_transfer ((GstGLMemoryPBO *) mem);
fail_unless (!GST_MEMORY_FLAG_IS_SET (mem,
GST_GL_BASE_MEMORY_TRANSFER_NEED_DOWNLOAD));
/* complete the upload */
fail_unless (gst_memory_map (mem, &info, GST_MAP_READ | GST_MAP_GL));
gst_memory_unmap (mem, &info);
/* force a download */
fail_unless (gst_memory_map (mem, &info, GST_MAP_WRITE | GST_MAP_GL));
gst_memory_unmap (mem, &info);
/* check the downloaded data is the same */
fail_unless (gst_memory_map (mem, &info, GST_MAP_READ));
fail_unless (memcmp (info.data, rgba_pixel, G_N_ELEMENTS (rgba_pixel)) == 0,
"0x%02x%02x%02x%02x != 0x%02x%02x%02x%02x", (guint8) info.data[0],
(guint8) info.data[1], (guint8) info.data[2],
(guint8) info.data[3], (guint8) rgba_pixel[0], (guint8) rgba_pixel[1],
(guint8) rgba_pixel[2], (guint8) rgba_pixel[3]);
gst_memory_unmap (mem, &info);
gst_memory_unref (mem);
}
GST_END_TEST;
GST_START_TEST (test_separate_download_transfer)
{
GstVideoInfo v_info;
GstMemory *mem;
GstMapInfo info;
gst_video_info_set_format (&v_info, GST_VIDEO_FORMAT_RGBA, 1, 1);
mem =
wrap_raw_data (GST_GL_MEMORY_PBO_ALLOCATOR_NAME, &v_info, 0, rgba_pixel);
/* complete the upload */
fail_unless (gst_memory_map (mem, &info, GST_MAP_READ | GST_MAP_GL));
gst_memory_unmap (mem, &info);
/* force a download */
fail_unless (gst_memory_map (mem, &info, GST_MAP_WRITE | GST_MAP_GL));
gst_memory_unmap (mem, &info);
gst_gl_memory_pbo_download_transfer ((GstGLMemoryPBO *) mem);
/* check the downloaded data is the same */
fail_unless (gst_memory_map (mem, &info, GST_MAP_READ));
fail_unless (memcmp (info.data, rgba_pixel, G_N_ELEMENTS (rgba_pixel)) == 0,
"0x%02x%02x%02x%02x != 0x%02x%02x%02x%02x", (guint8) info.data[0],
(guint8) info.data[1], (guint8) info.data[2],
(guint8) info.data[3], (guint8) rgba_pixel[0], (guint8) rgba_pixel[1],
(guint8) rgba_pixel[2], (guint8) rgba_pixel[3]);
gst_memory_unmap (mem, &info);
gst_memory_unref (mem);
}
GST_END_TEST;
static Suite *
gst_gl_memory_suite (void)
{
Suite *s = suite_create ("GstGLMemory");
TCase *tc_chain = tcase_create ("general");
suite_add_tcase (s, tc_chain);
tcase_add_checked_fixture (tc_chain, setup, teardown);
tcase_add_test (tc_chain, test_allocator_alloc);
tcase_add_test (tc_chain, test_allocator_pbo_alloc);
tcase_add_test (tc_chain, test_allocator_create);
tcase_add_test (tc_chain, test_memory_copy);
tcase_add_test (tc_chain, test_wrap_raw);
tcase_add_test (tc_chain, test_wrap_gl_memory);
tcase_add_test (tc_chain, test_wrap_data_copy_into);
tcase_add_test (tc_chain, test_transfer_state);
tcase_add_test (tc_chain, test_separate_upload_transfer);
tcase_add_test (tc_chain, test_separate_download_transfer);
return s;
}
GST_CHECK_MAIN (gst_gl_memory);