mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-23 18:21:04 +00:00
[514/906] add GstGLMemory and allocator
implement custom GstMemory for GL textures currently map/unmap returns NULL although it might be favourable to upload/download/cache the image data
This commit is contained in:
parent
eb362969f1
commit
ffdc6d496e
4 changed files with 516 additions and 0 deletions
|
@ -10,6 +10,7 @@ EXTRA_DIST = \
|
|||
|
||||
libgstgl_@GST_API_VERSION@_la_SOURCES = \
|
||||
gstgldisplay.c \
|
||||
gstglmemory.c \
|
||||
gstglfilter.c \
|
||||
gstglmixer.c \
|
||||
gstglshader.c \
|
||||
|
@ -32,6 +33,7 @@ libgstgl_@GST_API_VERSION@includedir = $(includedir)/gstreamer-@GST_API_VERSION@
|
|||
libgstgl_@GST_API_VERSION@include_HEADERS = \
|
||||
gstglwindow.h \
|
||||
gstgldisplay.h \
|
||||
gstglmemory.h \
|
||||
gstgles2.h \
|
||||
gstglfilter.h \
|
||||
gstglmixer.h \
|
||||
|
|
320
gst-libs/gst/gl/gstglmemory.c
Normal file
320
gst-libs/gst/gl/gstglmemory.c
Normal file
|
@ -0,0 +1,320 @@
|
|||
/*
|
||||
* GStreamer
|
||||
* 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., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <gst/video/video.h>
|
||||
|
||||
#include "gstglmemory.h"
|
||||
|
||||
/*GST_DEBUG_CATEGORY_STATIC (GST_CAT_GL_MEMORY);
|
||||
#define GST_CAT_DEFUALT GST_CAT_GL_MEMORY
|
||||
GST_DEBUG_CATEGORY_STATIC (GST_CAT_MEMORY);*/
|
||||
|
||||
static GstAllocator *_gl_allocator;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
GstGLMemory *src;
|
||||
GLuint tex_id;
|
||||
} GstGLMemoryCopyParams;
|
||||
|
||||
static void
|
||||
_gl_mem_init (GstGLMemory * mem, GstAllocator * allocator, GstMemory * parent,
|
||||
GstGLDisplay * display, GstVideoFormat v_format, gsize width, gsize height)
|
||||
{
|
||||
gst_memory_init (GST_MEMORY_CAST (mem), GST_MEMORY_FLAG_NO_SHARE,
|
||||
allocator, parent, 0, 0, 0, 0);
|
||||
|
||||
mem->display = g_object_ref (display);
|
||||
mem->gl_format = GL_RGBA;
|
||||
mem->v_format = v_format;
|
||||
mem->width = width;
|
||||
mem->height = height;
|
||||
|
||||
GST_DEBUG ("new GL memory");
|
||||
}
|
||||
|
||||
static GstGLMemory *
|
||||
_gl_mem_new (GstAllocator * allocator, GstMemory * parent,
|
||||
GstGLDisplay * display, GstVideoFormat v_format, gsize width, gsize height)
|
||||
{
|
||||
GstGLMemory *mem;
|
||||
GLuint tex_id;
|
||||
|
||||
gst_gl_display_gen_texture (display, &tex_id, v_format, width, height);
|
||||
if (!tex_id) {
|
||||
GST_WARNING ("Could not create GL texture with display:%p", display);
|
||||
}
|
||||
|
||||
GST_TRACE ("created texture %u", tex_id);
|
||||
|
||||
mem = g_slice_alloc (sizeof (GstGLMemory));
|
||||
_gl_mem_init (mem, allocator, parent, display, v_format, width, height);
|
||||
|
||||
mem->tex_id = tex_id;
|
||||
|
||||
return mem;
|
||||
}
|
||||
|
||||
GstMemory *
|
||||
_gl_allocator_alloc_func (GstAllocator * allocator, gsize size,
|
||||
GstAllocationParams * params, gpointer user_data)
|
||||
{
|
||||
g_warning ("use gst_gl_memory_alloc () to allocate from this "
|
||||
"GstGLMemory allocator");
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
gpointer
|
||||
_gl_mem_map_func (GstGLMemory * gl_mem, gsize maxsize, GstMapFlags flags)
|
||||
{
|
||||
/* should we perform a {up,down}load? */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void
|
||||
_gl_mem_unmap_func (GstGLMemory * gl_mem)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
_gl_mem_free_func (GstGLMemory * gl_mem)
|
||||
{
|
||||
gst_gl_display_del_texture (gl_mem->display, &gl_mem->tex_id);
|
||||
|
||||
g_object_unref (gl_mem->display);
|
||||
|
||||
g_slice_free (GstGLMemory, gl_mem);
|
||||
}
|
||||
|
||||
void
|
||||
_gl_mem_copy_thread (GstGLDisplay * display, gpointer data)
|
||||
{
|
||||
GstGLMemoryCopyParams *copy_params;
|
||||
GstGLMemory *src;
|
||||
GLuint tex_id;
|
||||
GLuint rboId, fboId;
|
||||
GLenum status;
|
||||
gsize width, height;
|
||||
GLuint gl_format;
|
||||
GstVideoFormat v_format;
|
||||
|
||||
copy_params = (GstGLMemoryCopyParams *) data;
|
||||
src = copy_params->src;
|
||||
width = src->width;
|
||||
height = src->height;
|
||||
v_format = src->v_format;
|
||||
gl_format = src->gl_format;
|
||||
|
||||
if (!GLEW_EXT_framebuffer_object) {
|
||||
//turn off the pipeline because Frame buffer object is a not present
|
||||
gst_gl_display_set_error (display,
|
||||
"Context, EXT_framebuffer_object not supported");
|
||||
return;
|
||||
}
|
||||
|
||||
gst_gl_display_gen_texture_thread (src->display, &tex_id, v_format, width,
|
||||
height);
|
||||
if (!tex_id) {
|
||||
GST_WARNING ("Could not create GL texture with display:%p", src->display);
|
||||
}
|
||||
|
||||
GST_DEBUG ("created texture %i", tex_id);
|
||||
|
||||
/* create a framebuffer object */
|
||||
glGenFramebuffersEXT (1, &fboId);
|
||||
glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, fboId);
|
||||
|
||||
/* create a renderbuffer object */
|
||||
glGenRenderbuffersEXT (1, &rboId);
|
||||
glBindRenderbufferEXT (GL_RENDERBUFFER_EXT, rboId);
|
||||
|
||||
#ifndef OPENGL_ES2
|
||||
glRenderbufferStorageEXT (GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT, width,
|
||||
height);
|
||||
glRenderbufferStorageEXT (GL_RENDERBUFFER_EXT, GL_DEPTH24_STENCIL8_EXT,
|
||||
width, height);
|
||||
#else
|
||||
glRenderbufferStorageEXT (GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT16,
|
||||
width, height);
|
||||
#endif
|
||||
/* attach the renderbuffer to depth attachment point */
|
||||
glFramebufferRenderbufferEXT (GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT,
|
||||
GL_RENDERBUFFER_EXT, rboId);
|
||||
|
||||
#ifndef OPENGL_ES2
|
||||
glFramebufferRenderbufferEXT (GL_FRAMEBUFFER_EXT,
|
||||
GL_STENCIL_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, rboId);
|
||||
#endif
|
||||
|
||||
glFramebufferTexture2DEXT (GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
|
||||
GL_TEXTURE_RECTANGLE_ARB, src->tex_id, 0);
|
||||
|
||||
/* check FBO status */
|
||||
status = glCheckFramebufferStatusEXT (GL_FRAMEBUFFER_EXT);
|
||||
|
||||
if (status != GL_FRAMEBUFFER_COMPLETE) {
|
||||
switch (status) {
|
||||
case GL_FRAMEBUFFER_UNSUPPORTED_EXT:
|
||||
GST_ERROR ("GL_FRAMEBUFFER_UNSUPPORTED");
|
||||
break;
|
||||
|
||||
case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT:
|
||||
GST_ERROR ("GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT");
|
||||
break;
|
||||
|
||||
case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT:
|
||||
GST_ERROR ("GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT");
|
||||
break;
|
||||
|
||||
case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT:
|
||||
GST_ERROR ("GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS");
|
||||
break;
|
||||
|
||||
case GL_FRAMEBUFFER_UNDEFINED:
|
||||
GST_ERROR ("GL_FRAMEBUFFER_UNDEFINED");
|
||||
break;
|
||||
|
||||
default:
|
||||
GST_ERROR ("General FBO error");
|
||||
}
|
||||
goto fbo_error;
|
||||
}
|
||||
|
||||
/* copy tex */
|
||||
glBindTexture (GL_TEXTURE_RECTANGLE_ARB, tex_id);
|
||||
glCopyTexImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, gl_format, 0, 0,
|
||||
width, height, 0);
|
||||
glBindTexture (GL_TEXTURE_RECTANGLE_ARB, 0);
|
||||
|
||||
glBindFramebuffer (GL_FRAMEBUFFER_EXT, 0);
|
||||
|
||||
glDeleteRenderbuffers (1, &rboId);
|
||||
glDeleteFramebuffers (1, &fboId);
|
||||
|
||||
copy_params->tex_id = tex_id;
|
||||
|
||||
fbo_error:
|
||||
{
|
||||
glDeleteRenderbuffers (1, &rboId);
|
||||
glDeleteFramebuffers (1, &fboId);
|
||||
|
||||
copy_params->tex_id = 0;
|
||||
}
|
||||
}
|
||||
|
||||
GstMemory *
|
||||
_gl_mem_copy_func (GstGLMemory * src, gssize offset, gssize size)
|
||||
{
|
||||
GstGLMemory *dest;
|
||||
GstGLMemoryCopyParams copy_params;
|
||||
|
||||
copy_params = (GstGLMemoryCopyParams) {
|
||||
src, 0,};
|
||||
|
||||
gst_gl_display_thread_add (src->display, _gl_mem_copy_thread, ©_params);
|
||||
|
||||
dest = g_slice_alloc (sizeof (GstGLMemory));
|
||||
_gl_mem_init (dest, src->mem.allocator, NULL, src->display, src->v_format,
|
||||
src->width, src->height);
|
||||
|
||||
if (!copy_params.tex_id)
|
||||
GST_WARNING ("Could not copy GL Memory");
|
||||
|
||||
dest->tex_id = copy_params.tex_id;
|
||||
|
||||
return (GstMemory *) dest;
|
||||
}
|
||||
|
||||
GstGLMemory *
|
||||
gst_gl_memory_copy (GstGLMemory * src)
|
||||
{
|
||||
return (GstGLMemory *) _gl_mem_copy_func (src, 0, 0);
|
||||
}
|
||||
|
||||
GstMemory *
|
||||
_gl_mem_share_func (GstGLMemory * mem, gssize offset, gssize size)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
gboolean
|
||||
_gl_mem_is_span_func (GstGLMemory * mem1, GstGLMemory * mem2, gsize * offset)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
_gl_mem_destroy_notify (gpointer user_data)
|
||||
{
|
||||
GST_LOG ("GLTexture memory allocator freed");
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_gl_memory_alloc:
|
||||
* @display:a #GstGLDisplay
|
||||
* @format: the format for the texture
|
||||
* @width: width of the texture
|
||||
* @height: height of the texture
|
||||
*
|
||||
* Returns: a GstMemory object with a GL texture specified by @format, @width and @height
|
||||
* from @display
|
||||
*/
|
||||
GstMemory *
|
||||
gst_gl_memory_alloc (GstGLDisplay * display, GstVideoFormat format,
|
||||
gsize width, gsize height)
|
||||
{
|
||||
return (GstMemory *) _gl_mem_new (_gl_allocator, NULL, display, format, width,
|
||||
height);
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_gl_memory_init:
|
||||
*
|
||||
* Initializes the GL Memory allocator. It is safe to call this function multiple times
|
||||
*
|
||||
* Returns: a #GstAllocator
|
||||
*/
|
||||
void
|
||||
gst_gl_memory_init (void)
|
||||
{
|
||||
static volatile gsize _init = 0;
|
||||
static const GstMemoryInfo mem_info = {
|
||||
GST_GL_MEMORY_ALLOCATOR,
|
||||
(GstAllocatorAllocFunction) _gl_allocator_alloc_func,
|
||||
(GstMemoryMapFunction) _gl_mem_map_func,
|
||||
(GstMemoryUnmapFunction) _gl_mem_unmap_func,
|
||||
(GstMemoryFreeFunction) _gl_mem_free_func,
|
||||
(GstMemoryCopyFunction) _gl_mem_copy_func,
|
||||
(GstMemoryShareFunction) _gl_mem_share_func,
|
||||
(GstMemoryIsSpanFunction) _gl_mem_is_span_func,
|
||||
};
|
||||
|
||||
if (g_once_init_enter (&_init)) {
|
||||
_gl_allocator = gst_allocator_new (&mem_info, NULL, _gl_mem_destroy_notify);
|
||||
gst_allocator_register (GST_GL_MEMORY_ALLOCATOR,
|
||||
gst_allocator_ref (_gl_allocator));
|
||||
g_once_init_leave (&_init, 1);
|
||||
}
|
||||
}
|
69
gst-libs/gst/gl/gstglmemory.h
Normal file
69
gst-libs/gst/gl/gstglmemory.h
Normal file
|
@ -0,0 +1,69 @@
|
|||
/*
|
||||
* GStreamer
|
||||
* 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., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef _GST_GL_MEMORY_H_
|
||||
#define _GST_GL_MEMORY_H_
|
||||
|
||||
#include <gst/gst.h>
|
||||
#include <gst/gstmemory.h>
|
||||
|
||||
#include "gstgldisplay.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GST_TYPE_GL_MEMORY (gst_gl_memory_get_type())
|
||||
GType gst_gl_memory_get_type(void);
|
||||
|
||||
typedef struct _GstGLMemoryInitParams GstGLMemoryInitParams;
|
||||
typedef struct _GstGLMemory GstGLMemory;
|
||||
|
||||
/**
|
||||
* GstGLMemory:
|
||||
* @mem: the parent object
|
||||
* @display: the #GstGLDisplay to use
|
||||
* @tex_id: the texture id
|
||||
* @gl_format: the format of the texture
|
||||
* @width: width of the texture
|
||||
* @height: height of the texture
|
||||
*
|
||||
* Represents information about a GL texture
|
||||
*/
|
||||
struct _GstGLMemory
|
||||
{
|
||||
GstMemory mem;
|
||||
|
||||
GstGLDisplay *display;
|
||||
GLuint tex_id;
|
||||
GstVideoFormat v_format;
|
||||
GLenum gl_format;
|
||||
GLuint width;
|
||||
GLuint height;
|
||||
};
|
||||
|
||||
#define GST_GL_MEMORY_ALLOCATOR "GLMemory"
|
||||
|
||||
void gst_gl_memory_init (void);
|
||||
|
||||
GstMemory * gst_gl_memory_alloc (GstGLDisplay * display, GstVideoFormat format,
|
||||
gsize width, gsize height);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* _GST_GL_MEMORY_H_ */
|
125
tests/check/libs/gstglmemory.c
Normal file
125
tests/check/libs/gstglmemory.c
Normal file
|
@ -0,0 +1,125 @@
|
|||
/* 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., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include "config.h"
|
||||
#endif
|
||||
|
||||
#include <gst/check/gstcheck.h>
|
||||
|
||||
#include <gst/gl/gstglmemory.h>
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
static GstGLDisplay *display;
|
||||
|
||||
void
|
||||
setup (void)
|
||||
{
|
||||
display = gst_gl_display_new ();
|
||||
gst_gl_display_create_context (display, 0);
|
||||
gst_gl_memory_init ();
|
||||
}
|
||||
|
||||
void
|
||||
teardown (void)
|
||||
{
|
||||
g_object_unref (display);
|
||||
}
|
||||
|
||||
GST_START_TEST (test_basic)
|
||||
{
|
||||
GstMemory *mem, *mem2;
|
||||
GstGLMemory *gl_mem, *gl_mem2;
|
||||
GstAllocator *gl_allocator;
|
||||
GstVideoInfo vinfo;
|
||||
gint i;
|
||||
static GstVideoFormat formats[15] = {
|
||||
GST_VIDEO_FORMAT_RGBx, GST_VIDEO_FORMAT_BGRx, GST_VIDEO_FORMAT_xRGB,
|
||||
GST_VIDEO_FORMAT_xBGR, GST_VIDEO_FORMAT_RGBA, GST_VIDEO_FORMAT_BGRA,
|
||||
GST_VIDEO_FORMAT_ARGB, GST_VIDEO_FORMAT_ABGR, GST_VIDEO_FORMAT_RGB,
|
||||
GST_VIDEO_FORMAT_BGR, GST_VIDEO_FORMAT_YUY2, GST_VIDEO_FORMAT_UYVY,
|
||||
GST_VIDEO_FORMAT_I420, GST_VIDEO_FORMAT_YV12, GST_VIDEO_FORMAT_AYUV,
|
||||
};
|
||||
|
||||
for (i = 0; i < G_N_ELEMENTS (formats); i++) {
|
||||
gsize width = 320, height = 240;
|
||||
|
||||
gst_video_info_set_format (&vinfo, formats[i], width, height);
|
||||
gl_allocator = gst_allocator_find (GST_GL_MEMORY_ALLOCATOR);
|
||||
fail_if (gl_allocator == NULL);
|
||||
|
||||
/* test allocator creation */
|
||||
ASSERT_WARNING (mem = gst_allocator_alloc (gl_allocator, 0, NULL););
|
||||
mem = gst_gl_memory_alloc (display, formats[i], width, height);
|
||||
fail_if (mem == NULL);
|
||||
gl_mem = (GstGLMemory *) mem;
|
||||
|
||||
/* test init params */
|
||||
fail_if (gl_mem->width != width);
|
||||
fail_if (gl_mem->height != height);
|
||||
fail_if (gl_mem->v_format != formats[i]);
|
||||
fail_if (gl_mem->display != display);
|
||||
fail_if (gl_mem->tex_id == 0);
|
||||
|
||||
/* copy the memory */
|
||||
mem2 = gst_memory_copy (mem, 0, -1);
|
||||
fail_if (mem == NULL);
|
||||
gl_mem2 = (GstGLMemory *) mem2;
|
||||
|
||||
/* test params */
|
||||
fail_if (gl_mem->tex_id == gl_mem2->tex_id);
|
||||
fail_if (gl_mem->width != gl_mem->width);
|
||||
fail_if (gl_mem->height != gl_mem->height);
|
||||
fail_if (gl_mem->v_format != gl_mem->v_format);
|
||||
fail_if (gl_mem->gl_format != gl_mem->gl_format);
|
||||
fail_if (gl_mem->display != gl_mem->display);
|
||||
fail_if (gl_mem->tex_id == 0);
|
||||
|
||||
if (display->error_message)
|
||||
printf ("%s\n", display->error_message);
|
||||
fail_if (display->error_message != NULL);
|
||||
|
||||
gst_memory_unref (mem);
|
||||
gst_memory_unref (mem2);
|
||||
|
||||
gst_allocator_unref (gl_allocator);
|
||||
}
|
||||
}
|
||||
|
||||
GST_END_TEST;
|
||||
|
||||
|
||||
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_basic);
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
GST_CHECK_MAIN (gst_gl_memory);
|
Loading…
Reference in a new issue