[108/906] git-svn-id: svn://svn.wobow.com/GStreamer_playground/gst-plugins-gl@540 93df14bb-0f41-7a43-8087-d3e2a2f0e464

This commit is contained in:
Julien Isorce 2008-06-21 21:38:42 +00:00 committed by Tim-Philipp Müller
parent 18177e6c46
commit 49e944778e
6 changed files with 217 additions and 272 deletions

View file

@ -30,8 +30,7 @@ static void
gst_gl_buffer_finalize (GstGLBuffer* buffer)
{
//wait clear textures end, blocking call
gst_gl_display_clearTexture (buffer->display, buffer->texture,
buffer->texture_u, buffer->texture_v);
gst_gl_display_clearTexture (buffer->display, buffer->texture);
g_object_unref (buffer->display);
@ -43,15 +42,10 @@ static void
gst_gl_buffer_init (GstGLBuffer* buffer, gpointer g_class)
{
buffer->display = NULL;
buffer->video_format = 0;
buffer->width = 0;
buffer->height = 0;
buffer->texture = 0;
buffer->texture_u = 0;
buffer->texture_v = 0;
buffer->widthGL = 0;
buffer->heightGL = 0;
buffer->textureGL = 0;
}
static void
@ -92,57 +86,43 @@ gst_gl_buffer_get_type (void)
GstGLBuffer*
gst_gl_buffer_new_from_video_format (GstGLDisplay* display,
GstVideoFormat video_format, gint context_width, gint context_height,
gint widthGL, gint heightGL,
gint width, gint height)
gst_gl_buffer_new (GstGLDisplay* display,
gint gl_width, gint gl_height)
{
GstGLBuffer *buffer;
GstGLBuffer* gl_buffer = (GstGLBuffer *) gst_mini_object_new (GST_TYPE_GL_BUFFER);
//g_return_val_if_fail (video_format != GST_VIDEO_FORMAT_UNKNOWN, NULL);
g_return_val_if_fail (display != NULL, NULL);
g_return_val_if_fail (width > 0, NULL);
g_return_val_if_fail (height > 0, NULL);
gl_buffer->display = g_object_ref (display);
gl_buffer->width = gl_width;
gl_buffer->height = gl_height;
buffer = (GstGLBuffer *) gst_mini_object_new (GST_TYPE_GL_BUFFER);
//it does not depends on the video format because gl buffer has always one texture.
//the one attached to the upload FBO
GST_BUFFER_SIZE (gl_buffer) = gst_gl_buffer_get_size (gl_width, gl_height);
buffer->display = g_object_ref (display);
buffer->width = width;
buffer->height = height;
buffer->video_format = video_format;
buffer->widthGL = widthGL;
buffer->heightGL = heightGL;
GST_BUFFER_SIZE (buffer) = gst_gl_buffer_format_get_size (video_format, context_width, context_height);
//blocking call, request a texture and attach it to the upload FBO
gst_gl_display_prepare_texture (gl_buffer->display, &gl_buffer->texture) ;
//blocking call, init texture
if (video_format != GST_VIDEO_FORMAT_UNKNOWN)
gst_gl_display_textureRequested (buffer->display, buffer->video_format,
buffer->width, buffer->height,
&buffer->texture, &buffer->texture_u, &buffer->texture_v) ;
return buffer;
return gl_buffer;
}
int
gst_gl_buffer_format_get_size (GstVideoFormat format, int width, int height)
gint
gst_gl_buffer_get_size (gint width, gint height)
{
/* this is not strictly true, but it's used for compatibility with
* queue and BaseTransform */
return width * height * 4;
//this is not strictly true, but it's used for compatibility with
//queue and BaseTransform
return width * height * 4;
}
gboolean
gst_gl_buffer_format_parse_caps (GstCaps * caps, GstVideoFormat * format,
gint* width, gint* height)
gst_gl_buffer_parse_caps (GstCaps* caps, gint* width, gint* height)
{
GstStructure *structure;
gboolean ret;
GstStructure* structure = gst_caps_get_structure (caps, 0);
gboolean ret = gst_structure_has_name (structure, "video/x-raw-gl");
structure = gst_caps_get_structure (caps, 0);
if (!gst_structure_has_name (structure, "video/x-raw-gl"))
return FALSE;
if (!ret)
return ret;
ret = gst_structure_get_int (structure, "width", width);
ret &= gst_structure_get_int (structure, "height", height);

View file

@ -33,24 +33,19 @@ typedef struct _GstGLBuffer GstGLBuffer;
#define GST_IS_GL_BUFFER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_GL_BUFFER))
#define GST_GL_BUFFER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_GL_BUFFER, GstGLBuffer))
//A gl buffer has only one texture.
//Note that when a gl buffer is created by the upload filter,
//the colorspace conversion is made using a FBO.
//And so the texture attached to this FBO is the one managed by the gl buffer.
struct _GstGLBuffer {
GstBuffer buffer;
GstGLDisplay *display;
GstVideoFormat video_format;
gint width;
gint height;
GLuint texture;
GLuint texture_u;
GLuint texture_v;
gint widthGL;
gint heightGL;
GLuint textureGL;
};
GType gst_gl_buffer_get_type (void);
@ -58,13 +53,9 @@ GType gst_gl_buffer_get_type (void);
#define gst_gl_buffer_ref(x) ((GstGLBuffer *)(gst_buffer_ref((GstBuffer *)(x))))
#define gst_gl_buffer_unref(x) (gst_buffer_unref((GstBuffer *)(x)))
GstGLBuffer* gst_gl_buffer_new_from_video_format (GstGLDisplay* display, GstVideoFormat format,
gint context_width, gint context_height,
gint widthGL, gint heightGL,
gint width, gint height);
gint gst_gl_buffer_format_get_size (GstVideoFormat format, gint width, gint height);
gboolean gst_gl_buffer_format_parse_caps (GstCaps* caps, GstVideoFormat* format,
gint* width, gint* height);
GstGLBuffer* gst_gl_buffer_new (GstGLDisplay* display, gint gl_width, gint gl_height);
gint gst_gl_buffer_get_size (gint width, gint height);
gboolean gst_gl_buffer_parse_caps (GstCaps* caps, gint* width, gint* height);
#define GST_GL_VIDEO_CAPS \

View file

@ -57,6 +57,8 @@ void gst_gl_display_fill_texture (GstGLDisplay* display);
void gst_gl_display_draw_texture (GstGLDisplay* display);
void gst_gl_display_draw_graphic (GstGLDisplay* display);
void gst_gl_display_fill_video (GstGLDisplay* display);
void gst_gl_display_gen_texture (GstGLDisplay* display, guint* pTexture);
void gst_gl_display_del_texture (GstGLDisplay* display, guint* pTexture);
GLhandleARB gst_gl_display_loadGLSLprogram (gchar* textFProgram);
void checkFramebufferStatus(void);
GST_BOILERPLATE (GstGLDisplay, gst_gl_display, GObject, G_TYPE_OBJECT);
@ -123,7 +125,6 @@ gst_gl_display_init (GstGLDisplay *display, GstGLDisplayClass *klass)
display->requestedFBO = 0;
display->requestedDepthBuffer = 0;
display->requestedTextureFBO = 0;
display->requestedTextureFBOWidth = 0;
display->requestedTextureFBOHeight = 0;
display->usedFBO = 0;
@ -140,37 +141,22 @@ gst_gl_display_init (GstGLDisplay *display, GstGLDisplayClass *klass)
display->inputTexture = 0;
display->rejectedFBO = 0;
display->rejectedDepthBuffer = 0;
display->rejectedTextureFBO = 0;
display->displayedTexture = 0;
display->displayedTextureWidth = 0;
display->displayedTextureHeight = 0;
display->requestedTexture = 0;
display->requestedTexture_u = 0;
display->requestedTexture_v = 0;
display->requestedVideo_format = 0;
display->requestedTextureWidth = 0;
display->requestedTextureHeight = 0;
display->candidateTexture = 0;
display->candidateTexture_u = 0;
display->candidateTexture_v = 0;
display->candidateVideo_format = 0;
display->candidateTextureWidth = 0;
display->candidateTextureHeight = 0;
display->candidateData = NULL;
display->preparedTexture = 0;
display->currentTexture = 0;
display->currentTexture_u = 0;
display->currentTexture_v = 0;
display->currentVideo_format = 0;
display->currentTextureWidth = 0;
display->currentTextureHeight = 0;
display->currentVideo_format = 0;
display->currentData = NULL;
display->textureTrash = 0;
display->textureTrash_u = 0;
display->textureTrash_v = 0;
display->videoFBO = 0;
display->videoDepthBuffer = 0;
@ -497,10 +483,10 @@ gst_gl_display_glutCreateWindow (GstGLDisplay *display)
{
//OpenGL > 2.1.0 and Glew > 1.5.0
GString* opengl_version = g_string_truncate (g_string_new ((gchar*) glGetString (GL_VERSION)), 3);
gint opengl_version_major = 0.;
gint opengl_version_major = 0;
gint opengl_version_minor = 0;
GString* glew_version = g_string_truncate (g_string_new ((gchar*) glewGetString (GLEW_VERSION)), 3);
gint glew_version_major = 0.;
gint glew_version_major = 0;
gint glew_version_minor = 0;
sscanf(opengl_version->str, "%d.%d", &opengl_version_major, &opengl_version_minor);
@ -525,6 +511,9 @@ gst_gl_display_glutCreateWindow (GstGLDisplay *display)
if (GLEW_EXT_framebuffer_object)
{
//a texture must be attached to the FBO
guint fake_texture = 0;
GST_DEBUG ("Context %d, EXT_framebuffer_object supported: yes", glutWinId);
//-- init intput frame buffer object (video -> GL)
@ -540,29 +529,29 @@ gst_gl_display_glutCreateWindow (GstGLDisplay *display)
display->textureFBOWidth, display->textureFBOHeight);
//setup a texture to render to
glGenTextures (1, &display->textureFBO);
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, display->textureFBO);
glGenTextures (1, &fake_texture);
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, fake_texture);
glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA8,
display->textureFBOWidth, display->textureFBOHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
//attach the texture to the FBO to renderer to
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
GL_TEXTURE_RECTANGLE_ARB, display->textureFBO, 0);
GL_TEXTURE_RECTANGLE_ARB, fake_texture, 0);
//attach the depth render buffer to the FBO
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT,
GL_RENDERBUFFER_EXT, display->depthBuffer);
checkFramebufferStatus();
g_assert (glCheckFramebufferStatusEXT (GL_FRAMEBUFFER_EXT) ==
GL_FRAMEBUFFER_COMPLETE_EXT);
//unbind the FBO
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
glDeleteTextures (1, &fake_texture);
}
else
{
@ -621,7 +610,6 @@ gst_gl_display_glutGenerateOutputVideoFBO (GstGLDisplay *display)
{
glutSetWindow (display->glutWinId);
if (GLEW_EXT_framebuffer_object)
{
GST_DEBUG ("Context %d, EXT_framebuffer_object supported: yes", display->glutWinId);
@ -657,6 +645,8 @@ gst_gl_display_glutGenerateOutputVideoFBO (GstGLDisplay *display)
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT,
GL_RENDERBUFFER_EXT, display->graphicDepthBuffer);
checkFramebufferStatus();
g_assert (glCheckFramebufferStatusEXT (GL_FRAMEBUFFER_EXT) ==
GL_FRAMEBUFFER_COMPLETE_EXT);
@ -772,7 +762,9 @@ gst_gl_display_glutGenerateOutputVideoFBO (GstGLDisplay *display)
static void
gst_gl_display_glutGenerateFBO (GstGLDisplay *display)
{
//a texture must be attached to the FBO
guint fake_texture = 0;
glutSetWindow (display->glutWinId);
//-- generate frame buffer object
@ -788,18 +780,14 @@ gst_gl_display_glutGenerateFBO (GstGLDisplay *display)
display->requestedTextureFBOWidth, display->requestedTextureFBOHeight);
//setup a texture to render to
glGenTextures (1, &display->requestedTextureFBO);
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, display->requestedTextureFBO);
glGenTextures (1, &fake_texture);
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, fake_texture);
glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA8,
display->requestedTextureFBOWidth, display->requestedTextureFBOHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
//attach the texture to the FBO to renderer to
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
GL_TEXTURE_RECTANGLE_ARB, display->requestedTextureFBO, 0);
GL_TEXTURE_RECTANGLE_ARB, fake_texture, 0);
//attach the depth render buffer to the FBO
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT,
@ -811,6 +799,8 @@ gst_gl_display_glutGenerateFBO (GstGLDisplay *display)
//unbind the FBO
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
glDeleteTextures (1, &fake_texture);
g_cond_signal (display->cond_generateFBO);
}
@ -824,6 +814,19 @@ gst_gl_display_glutUseFBO (GstGLDisplay *display)
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, display->usedFBO);
//setup a texture to render to
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, display->usedTextureFBO);
glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA8,
display->usedTextureFBOWidth, display->usedTextureFBOHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
//attach the texture to the FBO to renderer to
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
GL_TEXTURE_RECTANGLE_ARB, display->usedTextureFBO, 0);
glPushAttrib(GL_VIEWPORT_BIT);
glMatrixMode(GL_PROJECTION);
@ -872,12 +875,24 @@ gst_gl_display_glutUseFBO2 (GstGLDisplay *display)
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, display->usedFBO);
//setup a texture to render to
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, display->usedTextureFBO);
glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA8,
display->usedTextureFBOWidth, display->usedTextureFBOHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
//attach the texture to the FBO to renderer to
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
GL_TEXTURE_RECTANGLE_ARB, display->usedTextureFBO, 0);
glPushAttrib(GL_VIEWPORT_BIT);
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
//gluPerspective(45, (gfloat)display->usedTextureFBOWidth/(gfloat)display->usedTextureFBOHeight, 0.1, 100);
gluOrtho2D(0.0, display->usedTextureFBOWidth, 0.0, display->usedTextureFBOHeight);
glMatrixMode(GL_MODELVIEW);
@ -919,10 +934,8 @@ gst_gl_display_glutDestroyFBO (GstGLDisplay* display)
glDeleteFramebuffersEXT (1, &display->rejectedFBO);
glDeleteRenderbuffersEXT(1, &display->rejectedDepthBuffer);
glDeleteTextures (1, &display->rejectedTextureFBO);
display->rejectedFBO = 0;
display->rejectedDepthBuffer = 0;
display->rejectedTextureFBO = 0;
g_cond_signal (display->cond_destroyFBO);
}
@ -970,7 +983,6 @@ gst_gl_display_glutDestroyWindow (GstGLDisplay *display)
glDeleteFramebuffersEXT (1, &display->fbo);
glDeleteRenderbuffersEXT(1, &display->depthBuffer);
glDeleteTextures (1, &display->textureFBO);
glDeleteFramebuffersEXT (1, &display->graphicFBO);
glDeleteRenderbuffersEXT(1, &display->graphicDepthBuffer);
@ -986,15 +998,8 @@ gst_gl_display_glutDestroyWindow (GstGLDisplay *display)
while (g_queue_get_length (display->texturePool))
{
GstGLDisplayTex* tex = g_queue_pop_head (display->texturePool);
//delete textures
glDeleteTextures (1, &tex->texture);
if (tex->texture_u) {
glDeleteTextures (1, &tex->texture_u);
}
if (tex->texture_v) {
glDeleteTextures (1, &tex->texture_v);
}
g_free (tex);
}
g_hash_table_remove (gst_gl_display_map, GINT_TO_POINTER (display->glutWinId));
@ -1036,7 +1041,8 @@ static void
gst_gl_display_glutPrepareTexture (GstGLDisplay * display)
{
glutSetWindow (display->glutWinId);
gst_gl_display_make_texture (display);
//setup a texture to render to (this one will be in a gl buffer)
gst_gl_display_gen_texture (display, &display->preparedTexture);
g_cond_signal (display->cond_make);
}
@ -1046,6 +1052,7 @@ static void
gst_gl_display_glutUpdateTexture (GstGLDisplay * display)
{
glutSetWindow (display->glutWinId);
gst_gl_display_make_texture (display);
gst_gl_display_fill_texture (display);
gst_gl_display_draw_texture (display);
g_cond_signal (display->cond_fill);
@ -1054,25 +1061,10 @@ gst_gl_display_glutUpdateTexture (GstGLDisplay * display)
/* Called by the idle function */
static void
gst_gl_display_glutCleanTexture (GstGLDisplay * display)
gst_gl_display_glutCleanTexture (GstGLDisplay* display)
{
GstGLDisplayTex* tex = NULL;
glutSetWindow (display->glutWinId);
//contructuct a texture pool element
tex = g_new0 (GstGLDisplayTex, 1);
tex->texture = display->textureTrash;
tex->texture_u = display->textureTrash_u;
tex->texture_v = display->textureTrash_v;
display->textureTrash = 0;
display->textureTrash_u = 0;
display->textureTrash_v = 0;
//add tex to the pool, it makes texture allocation reusable
g_queue_push_tail (display->texturePool, tex);
gst_gl_display_del_texture (display, &display->textureTrash);
g_cond_signal (display->cond_clear);
}
@ -1348,55 +1340,40 @@ gst_gl_display_resizeWindow (GstGLDisplay* display, gint width, gint height)
/* Called by gstglbuffer */
void
gst_gl_display_textureRequested (GstGLDisplay* display, GstVideoFormat video_format,
gint width, gint height, guint* texture,
guint* texture_u, guint* texture_v)
gst_gl_display_prepare_texture (GstGLDisplay* display, guint* pTexture)
{
gst_gl_display_lock (display);
display->requestedVideo_format = video_format;
display->requestedTextureWidth = width;
display->requestedTextureHeight = height;
gst_gl_display_postMessage (GST_GL_DISPLAY_ACTION_PREPARE, display);
g_cond_wait (display->cond_make, display->mutex);
*texture = display->requestedTexture;
*texture_u = display->requestedTexture_u;
*texture_v = display->requestedTexture_v;
*pTexture = display->preparedTexture;
gst_gl_display_unlock (display);
}
/* Called by gst_gl elements */
void
gst_gl_display_textureChanged (GstGLDisplay* display, GstVideoFormat video_format,
GLuint texture, GLuint texture_u, GLuint texture_v,
gint width, gint height, gpointer data, GLuint* outputTexture)
gst_gl_display_do_upload (GstGLDisplay* display, GstVideoFormat video_format,
gint video_width, gint video_height, gpointer data,
guint gl_width, guint gl_height, guint pTexture)
{
gst_gl_display_lock (display);
display->candidateTexture = texture;
display->candidateTexture_u = texture_u;
display->candidateTexture_v = texture_v;
display->candidateVideo_format = video_format;
display->candidateTextureWidth = width;
display->candidateTextureHeight = height;
display->candidateData = data;
display->currentTextureWidth = video_width;
display->currentTextureHeight = video_height;
display->currentVideo_format = video_format;
display->currentData = data;
display->textureFBO = pTexture;
gst_gl_display_postMessage (GST_GL_DISPLAY_ACTION_CHANGE, display);
g_cond_wait (display->cond_fill, display->mutex);
//Here texture width and height are always the same than the fbo
if (outputTexture)
*outputTexture = display->textureFBO;
gst_gl_display_unlock (display);
}
/* Called by gstglbuffer */
void
gst_gl_display_clearTexture (GstGLDisplay* display, guint texture,
guint texture_u, guint texture_v)
gst_gl_display_clearTexture (GstGLDisplay* display, guint texture)
{
gst_gl_display_lock (display);
display->textureTrash = texture;
display->textureTrash_u = texture_u;
display->textureTrash_v = texture_v;
gst_gl_display_postMessage (GST_GL_DISPLAY_ACTION_CLEAR, display);
g_cond_wait (display->cond_clear, display->mutex);
gst_gl_display_unlock (display);
@ -1446,7 +1423,7 @@ gst_gl_display_postRedisplay (GstGLDisplay* display, GLuint texture, gint width
/* Called by gst_gl elements */
void
gst_gl_display_requestFBO (GstGLDisplay* display, gint width, gint height,
guint* fbo, guint* depthbuffer, guint* texture)
guint* fbo, guint* depthbuffer)
{
gst_gl_display_lock (display);
display->requestedTextureFBOWidth = width;
@ -1455,7 +1432,6 @@ gst_gl_display_requestFBO (GstGLDisplay* display, gint width, gint height,
g_cond_wait (display->cond_generateFBO, display->mutex);
*fbo = display->requestedFBO;
*depthbuffer = display->requestedDepthBuffer;
*texture = display->requestedTextureFBO;
gst_gl_display_unlock (display);
}
@ -1497,6 +1473,8 @@ gst_gl_display_useFBO2 (GstGLDisplay* display, gint textureFBOWidth, gint textur
display->usedTextureFBOWidth = textureFBOWidth;
display->usedTextureFBOHeight = textureFBOheight;
display->glsceneFBO_cb2 = cb2;
display->p1 = p1;
display->p2 = p2;
gst_gl_display_postMessage (GST_GL_DISPLAY_ACTION_USEFBO2, display);
g_cond_wait (display->cond_useFBO2, display->mutex);
gst_gl_display_unlock (display);
@ -1506,12 +1484,11 @@ gst_gl_display_useFBO2 (GstGLDisplay* display, gint textureFBOWidth, gint textur
/* Called by gst_gl elements */
void
gst_gl_display_rejectFBO (GstGLDisplay* display, guint fbo,
guint depthbuffer, guint texture)
guint depthbuffer)
{
gst_gl_display_lock (display);
display->rejectedFBO = fbo;
display->rejectedDepthBuffer = depthbuffer;
display->rejectedTextureFBO = texture;
gst_gl_display_postMessage (GST_GL_DISPLAY_ACTION_DELFBO, display);
g_cond_wait (display->cond_destroyFBO, display->mutex);
gst_gl_display_unlock (display);
@ -1718,23 +1695,17 @@ void gst_gl_display_onClose (void)
}
/* called by gst_gl_display_glutPrepareTexture (in the glut thread) */
void gst_gl_display_make_texture (GstGLDisplay * display)
/* called by gst_gl_display_glutUpdateTexture (in the glut thread) */
void gst_gl_display_make_texture (GstGLDisplay* display)
{
GstGLDisplayTex* tex = NULL;
gint width = display->currentTextureWidth;
gint height = display->currentTextureHeight;
gst_gl_display_gen_texture (display, &display->currentTexture);
//check if there is a tex available in the pool
if (g_queue_get_length (display->texturePool))
tex = g_queue_pop_head (display->texturePool);
//one tex is available
if (tex)
display->requestedTexture = tex->texture;
else
glGenTextures (1, &display->requestedTexture);
glBindTexture (GL_TEXTURE_RECTANGLE_ARB, display->requestedTexture);
switch (display->requestedVideo_format) {
glBindTexture (GL_TEXTURE_RECTANGLE_ARB, display->currentTexture);
switch (display->currentVideo_format)
{
case GST_VIDEO_FORMAT_RGBx:
case GST_VIDEO_FORMAT_BGRx:
case GST_VIDEO_FORMAT_xRGB:
@ -1745,82 +1716,68 @@ void gst_gl_display_make_texture (GstGLDisplay * display)
case GST_VIDEO_FORMAT_ABGR:
case GST_VIDEO_FORMAT_AYUV:
glTexImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA,
display->requestedTextureWidth, display->requestedTextureHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
break;
case GST_VIDEO_FORMAT_RGB:
case GST_VIDEO_FORMAT_BGR:
glTexImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGB,
display->requestedTextureWidth, display->requestedTextureHeight, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
break;
case GST_VIDEO_FORMAT_YUY2:
case GST_VIDEO_FORMAT_UYVY:
glTexImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, GL_LUMINANCE_ALPHA,
display->requestedTextureWidth, display->requestedTextureHeight,
width, height,
0, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, NULL);
//one tex is available
if (tex)
display->requestedTexture_u = tex->texture_u;
else
glGenTextures (1, &display->requestedTexture_u);
gst_gl_display_gen_texture (display, &display->currentTexture_u);
glBindTexture (GL_TEXTURE_RECTANGLE_ARB, display->requestedTexture_u);
glBindTexture (GL_TEXTURE_RECTANGLE_ARB, display->currentTexture_u);
glTexImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA8,
display->requestedTextureWidth, display->requestedTextureHeight,
width, height,
0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL);
break;
case GST_VIDEO_FORMAT_I420:
case GST_VIDEO_FORMAT_YV12:
glTexImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, GL_LUMINANCE,
display->requestedTextureWidth, display->requestedTextureHeight,
width, height,
0, GL_LUMINANCE, GL_UNSIGNED_BYTE, NULL);
//one tex is available
if (tex)
display->requestedTexture_u = tex->texture_u;
else
glGenTextures (1, &display->requestedTexture_u);
gst_gl_display_gen_texture (display, &display->currentTexture_u);
glBindTexture (GL_TEXTURE_RECTANGLE_ARB, display->requestedTexture_u);
glBindTexture (GL_TEXTURE_RECTANGLE_ARB, display->currentTexture_u);
glTexImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, GL_LUMINANCE,
GST_ROUND_UP_2 (display->requestedTextureWidth) / 2,
GST_ROUND_UP_2 (display->requestedTextureHeight) / 2,
GST_ROUND_UP_2 (width) / 2,
GST_ROUND_UP_2 (height) / 2,
0, GL_LUMINANCE, GL_UNSIGNED_BYTE, NULL);
//one tex is available
if (tex)
display->requestedTexture_v = tex->texture_v;
else
glGenTextures (1, &display->requestedTexture_v);
gst_gl_display_gen_texture (display, &display->currentTexture_v);
glBindTexture (GL_TEXTURE_RECTANGLE_ARB, display->requestedTexture_v);
glBindTexture (GL_TEXTURE_RECTANGLE_ARB, display->currentTexture_v);
glTexImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, GL_LUMINANCE,
GST_ROUND_UP_2 (display->requestedTextureWidth) / 2,
GST_ROUND_UP_2 (display->requestedTextureHeight) / 2,
GST_ROUND_UP_2 (width) / 2,
GST_ROUND_UP_2 (height) / 2,
0, GL_LUMINANCE, GL_UNSIGNED_BYTE, NULL);
break;
default:
g_assert_not_reached ();
}
if (tex)
g_free (tex);
}
/* called by gst_gl_display_glutUpdateTexture (in the glut thread) */
void
gst_gl_display_fill_texture (GstGLDisplay * display)
{
GstVideoFormat video_format = display->candidateVideo_format;
gint width = display->candidateTextureWidth;
gint height = display->candidateTextureHeight;
gpointer data = display->candidateData;
gint width = display->currentTextureWidth;
gint height = display->currentTextureHeight;
GstVideoFormat video_format = display->currentVideo_format;
gpointer data = display->currentData;
glBindTexture (GL_TEXTURE_RECTANGLE_ARB, display->candidateTexture);
glBindTexture (GL_TEXTURE_RECTANGLE_ARB, display->currentTexture);
switch (video_format) {
case GST_VIDEO_FORMAT_RGBx:
@ -1845,7 +1802,7 @@ gst_gl_display_fill_texture (GstGLDisplay * display)
glTexSubImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, 0, 0, width, height,
GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, data);
glBindTexture (GL_TEXTURE_RECTANGLE_ARB, display->candidateTexture_u);
glBindTexture (GL_TEXTURE_RECTANGLE_ARB, display->currentTexture_u);
glTexSubImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, 0, 0,
GST_ROUND_UP_2 (width) / 2, height,
GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, data);
@ -1873,14 +1830,14 @@ gst_gl_display_fill_texture (GstGLDisplay * display)
glTexSubImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, 0, 0, width, height,
GL_LUMINANCE, GL_UNSIGNED_BYTE, data);
glBindTexture (GL_TEXTURE_RECTANGLE_ARB, display->candidateTexture_u);
glBindTexture (GL_TEXTURE_RECTANGLE_ARB, display->currentTexture_u);
glTexSubImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, 0, 0,
GST_ROUND_UP_2 (width) / 2, GST_ROUND_UP_2 (height) / 2,
GL_LUMINANCE, GL_UNSIGNED_BYTE,
(guint8 *) data +
gst_video_format_get_component_offset (video_format, offsetU, width, height));
glBindTexture (GL_TEXTURE_RECTANGLE_ARB, display->candidateTexture_v);
glBindTexture (GL_TEXTURE_RECTANGLE_ARB, display->currentTexture_v);
glTexSubImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, 0, 0,
GST_ROUND_UP_2 (width) / 2, GST_ROUND_UP_2 (height) / 2,
GL_LUMINANCE, GL_UNSIGNED_BYTE,
@ -1891,15 +1848,6 @@ gst_gl_display_fill_texture (GstGLDisplay * display)
default:
g_assert_not_reached ();
}
//candidate textures can now be used
display->currentTexture = display->candidateTexture;
display->currentTexture_u = display->candidateTexture_u;
display->currentTexture_v = display->candidateTexture_v;
display->currentVideo_format = display->candidateVideo_format;
display->currentTextureWidth = display->candidateTextureWidth;
display->currentTextureHeight = display->candidateTextureHeight;
}
@ -1909,6 +1857,18 @@ gst_gl_display_draw_texture (GstGLDisplay* display)
{
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, display->fbo);
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, display->textureFBO);
glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA8,
display->textureFBOWidth, display->textureFBOHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
//attach the texture to the FBO to renderer to
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
GL_TEXTURE_RECTANGLE_ARB, display->textureFBO, 0);
glPushAttrib(GL_VIEWPORT_BIT);
glMatrixMode(GL_PROJECTION);
@ -2079,6 +2039,12 @@ gst_gl_display_draw_texture (GstGLDisplay* display)
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
checkFramebufferStatus();
gst_gl_display_del_texture (display, &display->currentTexture);
if (display->currentTexture_u)
gst_gl_display_del_texture (display, &display->currentTexture_u);
if (display->currentTexture_v)
gst_gl_display_del_texture (display, &display->currentTexture_v);
}
@ -2381,6 +2347,42 @@ gst_gl_display_fill_video (GstGLDisplay* display)
}
/* Generate a texture if no one is available in the pool */
void
gst_gl_display_gen_texture (GstGLDisplay* display, guint* pTexture)
{
//check if there is a texture available in the pool
GstGLDisplayTex* tex = g_queue_pop_head (display->texturePool);
if (tex)
{
*pTexture = tex->texture;
g_free (tex);
}
//otherwise one more texture is generated
//note that this new texture is added in the pool
//only after being used
else
glGenTextures (1, pTexture);
}
/* Delete a texture, actually the texture is just added to the pool */
void
gst_gl_display_del_texture (GstGLDisplay* display, guint* pTexture)
{
//Each existing texture is destroyed only when the pool is destroyed
//The pool of textures is deleted in the GstGLDisplay destructor
//contruct a texture pool element
GstGLDisplayTex* tex = g_new0 (GstGLDisplayTex, 1);
tex->texture = *pTexture;
*pTexture = 0;
//add tex to the pool, it makes texture allocation reusable
g_queue_push_tail (display->texturePool, tex);
}
/* called by gst_gl_display_glutCreateWindow (in the glut thread) */
GLhandleARB
gst_gl_display_loadGLSLprogram (gchar* textFProgram)
@ -2427,10 +2429,10 @@ checkFramebufferStatus(void)
break;
case GL_FRAMEBUFFER_UNSUPPORTED_EXT:
GST_DEBUG("GL_FRAMEBUFFER_UNSUPPORTED_EXT");
g_print ("GL_FRAMEBUFFER_UNSUPPORTED_EXT\n");
break;
default:
GST_DEBUG("General FBO error");
g_print ("General FBO error\n");
}
}

View file

@ -74,8 +74,6 @@ typedef struct _GstGLDisplayMsg {
//Texture pool elements
typedef struct _GstGLDisplayTex {
GLuint texture;
GLuint texture_u;
GLuint texture_v;
} GstGLDisplayTex;
@ -133,9 +131,9 @@ struct _GstGLDisplay {
//filter frame buffer object (GL -> GL)
GLuint requestedFBO;
GLuint requestedDepthBuffer;
GLuint requestedTextureFBO;
GLuint requestedTextureFBOWidth;
GLuint requestedTextureFBOHeight;
GLuint usedFBO;
GLuint usedDepthBuffer;
GLuint usedTextureFBO;
@ -150,38 +148,23 @@ struct _GstGLDisplay {
GLuint inputTexture;
GLuint rejectedFBO;
GLuint rejectedDepthBuffer;
GLuint rejectedTextureFBO;
//displayed texture
GLuint displayedTexture;
GLuint displayedTextureWidth;
GLuint displayedTextureHeight;
GLuint requestedTexture;
GLuint requestedTexture_u;
GLuint requestedTexture_v;
GstVideoFormat requestedVideo_format;
GLuint requestedTextureWidth;
GLuint requestedTextureHeight;
GLuint candidateTexture;
GLuint candidateTexture_u;
GLuint candidateTexture_v;
GstVideoFormat candidateVideo_format;
GLuint candidateTextureWidth;
GLuint candidateTextureHeight;
gpointer candidateData;
GLuint preparedTexture;
GLuint currentTexture;
GLuint currentTexture_u;
GLuint currentTexture_v;
GstVideoFormat currentVideo_format;
GLuint currentTextureWidth;
GLuint currentTextureHeight;
GstVideoFormat currentVideo_format;
gpointer currentData;
GLuint textureTrash;
GLuint textureTrash_u;
GLuint textureTrash_v;
//output frame buffer object (GL -> video)
GLuint videoFBO;
@ -257,20 +240,17 @@ void gst_gl_display_setClientReshapeCallback (GstGLDisplay* display, CRCB cb);
void gst_gl_display_setClientDrawCallback (GstGLDisplay* display, CDCB cb);
void gst_gl_display_setVisibleWindow (GstGLDisplay* display, gboolean visible);
void gst_gl_display_resizeWindow (GstGLDisplay* display, gint width, gint height);
void gst_gl_display_textureRequested (GstGLDisplay* display, GstVideoFormat format,
gint width, gint height, guint* texture,
guint* texture_u, guint* texture_v);
void gst_gl_display_textureChanged (GstGLDisplay* display, GstVideoFormat video_format,
GLuint texture, GLuint texture_u, GLuint texture_v,
gint width, gint height, gpointer data, GLuint* outputTexture);
void gst_gl_display_clearTexture (GstGLDisplay* display, guint texture,
guint texture_u, guint texture_v);
void gst_gl_display_prepare_texture (GstGLDisplay* display, guint* pTexture);
void gst_gl_display_do_upload (GstGLDisplay* display, GstVideoFormat video_format,
gint video_width, gint video_height, gpointer data,
guint gl_width, guint gl_height, guint pTexture);
void gst_gl_display_clearTexture (GstGLDisplay* display, guint texture);
void gst_gl_display_videoChanged (GstGLDisplay* display, GstVideoFormat video_format,
gint width, gint height, GLuint recordedTexture, gpointer data);
gboolean gst_gl_display_postRedisplay (GstGLDisplay* display, GLuint texture, gint width, gint height);
void gst_gl_display_requestFBO (GstGLDisplay* display, gint width, gint height,
guint* fbo, guint* depthbuffer, guint* texture);
guint* fbo, guint* depthbuffer);
void gst_gl_display_useFBO (GstGLDisplay* display, gint textureFBOWidth, gint textureFBOheight,
guint fbo, guint depthbuffer, guint textureFBO, GLCB cb,
guint inputTextureWidth, guint inputTextureHeight, guint inputTexture,
@ -279,7 +259,7 @@ void gst_gl_display_useFBO2 (GstGLDisplay* display, gint textureFBOWidth, gint t
guint fbo, guint depthbuffer, guint textureFBO, GLCB2 cb,
gpointer* p1, gpointer* p2);
void gst_gl_display_rejectFBO (GstGLDisplay* display, guint fbo,
guint depthbuffer, guint texture);
guint depthbuffer);
void gst_gl_display_initDonwloadFBO (GstGLDisplay* display, gint width, gint height);
void gst_gl_display_initShader (GstGLDisplay* display, gchar* textShader, GLhandleARB* handleShader);
void gst_gl_display_destroyShader (GstGLDisplay* display, GLhandleARB shader);

View file

@ -157,16 +157,14 @@ gst_gl_filter_reset (GstGLFilter* filter)
{
//blocking call, delete the FBO
gst_gl_display_rejectFBO (filter->display, filter->fbo,
filter->depthbuffer, filter->texture);
filter->depthbuffer);
g_object_unref (filter->display);
filter->display = NULL;
}
filter->video_format = GST_VIDEO_FORMAT_UNKNOWN;
filter->width = 0;
filter->height = 0;
filter->fbo = 0;
filter->depthbuffer = 0;
filter->texture = 0;
}
static gboolean
@ -221,14 +219,13 @@ static gboolean
gst_gl_filter_get_unit_size (GstBaseTransform* trans, GstCaps* caps,
guint* size)
{
gboolean ret;
GstVideoFormat video_format;
gint width;
gint height;
gboolean ret = FALSE;
gint width = 0;
gint height = 0;
ret = gst_gl_buffer_format_parse_caps (caps, &video_format, &width, &height);
ret = gst_gl_buffer_parse_caps (caps, &width, &height);
if (ret)
*size = gst_gl_buffer_format_get_size (video_format, width, height);
*size = gst_gl_buffer_get_size (width, height);
return TRUE;
}
@ -251,17 +248,14 @@ gst_gl_filter_prepare_output_buffer (GstBaseTransform* trans,
//blocking call, generate a FBO
gst_gl_display_requestFBO (filter->display, filter->width, filter->height,
&filter->fbo, &filter->depthbuffer, &filter->texture);
&filter->fbo, &filter->depthbuffer);
if (filter_class->onInitFBO)
filter_class->onInitFBO (filter);
}
gl_outbuf = gst_gl_buffer_new_from_video_format (filter->display,
filter->video_format,
filter->width, filter->height,
filter->width, filter->height,
gl_inbuf->width, gl_inbuf->height);
gl_outbuf = gst_gl_buffer_new (filter->display,
filter->width, filter->height);
*buf = GST_BUFFER (gl_outbuf);
gst_buffer_set_caps (*buf, caps);
@ -277,8 +271,7 @@ gst_gl_filter_set_caps (GstBaseTransform* bt, GstCaps* incaps,
gboolean ret = FALSE;
GstGLFilterClass* filter_class = GST_GL_FILTER_GET_CLASS (filter);
ret = gst_gl_buffer_format_parse_caps (outcaps, &filter->video_format,
&filter->width, &filter->height);
ret = gst_gl_buffer_parse_caps (outcaps, &filter->width, &filter->height);
if (filter_class->set_caps)
filter_class->set_caps (filter, incaps, outcaps);

View file

@ -54,12 +54,11 @@ struct _GstGLFilter
GstPad *sinkpad;
GstGLDisplay *display;
GstVideoFormat video_format;
gint width;
gint height;
guint fbo;
guint depthbuffer;
guint texture;
};
struct _GstGLFilterClass