diff --git a/gst-libs/gst/gl/gstglbuffer.c b/gst-libs/gst/gl/gstglbuffer.c index 4fbdbd4e33..2932e24f20 100644 --- a/gst-libs/gst/gl/gstglbuffer.c +++ b/gst-libs/gst/gl/gstglbuffer.c @@ -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); diff --git a/gst-libs/gst/gl/gstglbuffer.h b/gst-libs/gst/gl/gstglbuffer.h index 1c18f4c2bb..9f30800560 100644 --- a/gst-libs/gst/gl/gstglbuffer.h +++ b/gst-libs/gst/gl/gstglbuffer.h @@ -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 \ diff --git a/gst-libs/gst/gl/gstgldisplay.c b/gst-libs/gst/gl/gstgldisplay.c index a7a26fc9c5..ab23083362 100644 --- a/gst-libs/gst/gl/gstgldisplay.c +++ b/gst-libs/gst/gl/gstgldisplay.c @@ -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"); } } diff --git a/gst-libs/gst/gl/gstgldisplay.h b/gst-libs/gst/gl/gstgldisplay.h index db8d7865f4..ba3eaed965 100644 --- a/gst-libs/gst/gl/gstgldisplay.h +++ b/gst-libs/gst/gl/gstgldisplay.h @@ -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); diff --git a/gst-libs/gst/gl/gstglfilter.c b/gst-libs/gst/gl/gstglfilter.c index a007c6c619..f371c385a3 100644 --- a/gst-libs/gst/gl/gstglfilter.c +++ b/gst-libs/gst/gl/gstglfilter.c @@ -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); diff --git a/gst-libs/gst/gl/gstglfilter.h b/gst-libs/gst/gl/gstglfilter.h index bd3d99dd15..ba23081136 100644 --- a/gst-libs/gst/gl/gstglfilter.h +++ b/gst-libs/gst/gl/gstglfilter.h @@ -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 diff --git a/gst/gl/gstglcolorscale.c b/gst/gl/gstglcolorscale.c index a7b8ae7820..3b7d803282 100644 --- a/gst/gl/gstglcolorscale.c +++ b/gst/gl/gstglcolorscale.c @@ -104,9 +104,9 @@ gst_gl_colorscale_base_init (gpointer klass) } static void -gst_gl_colorscale_class_init (GstGLColorscaleClass * klass) +gst_gl_colorscale_class_init (GstGLColorscaleClass* klass) { - GObjectClass *gobject_class; + GObjectClass* gobject_class; gobject_class = (GObjectClass *) klass; gobject_class->set_property = gst_gl_colorscale_set_property; @@ -123,7 +123,7 @@ gst_gl_colorscale_class_init (GstGLColorscaleClass * klass) } static void -gst_gl_colorscale_init (GstGLColorscale* colorscale, GstGLColorscaleClass * klass) +gst_gl_colorscale_init (GstGLColorscale* colorscale, GstGLColorscaleClass* klass) { gst_gl_colorscale_reset (colorscale); } @@ -370,15 +370,15 @@ gst_gl_colorscale_set_caps (GstBaseTransform* bt, GstCaps* incaps, { GstGLColorscale* colorscale = GST_GL_COLORSCALE (bt); gboolean ret = FALSE; - static gint glcontext_y = 0; + static gint y_pos = 0; GST_DEBUG ("called with %" GST_PTR_FORMAT, incaps); - ret = gst_video_format_parse_caps (outcaps, &colorscale->outVideo_format, - &colorscale->outWidth, &colorscale->outHeight); + ret = gst_video_format_parse_caps (outcaps, &colorscale->output_video_format, + &colorscale->output_video_width, &colorscale->output_video_height); - ret |= gst_video_format_parse_caps (incaps, &colorscale->inVideo_format, - &colorscale->inWidth, &colorscale->inHeight); + ret |= gst_video_format_parse_caps (incaps, &colorscale->input_video_format, + &colorscale->input_video_width, &colorscale->input_video_height); if (!ret) { @@ -390,12 +390,13 @@ gst_gl_colorscale_set_caps (GstBaseTransform* bt, GstCaps* incaps, //init unvisible opengl context gst_gl_display_initGLContext (colorscale->display, - 50, glcontext_y++ * (colorscale->inHeight+50) + 50, - colorscale->inWidth, colorscale->inHeight, - colorscale->inWidth, colorscale->inHeight, 0, FALSE); + 50, y_pos++ * (colorscale->output_video_height+50) + 50, + colorscale->output_video_width, colorscale->output_video_height, + colorscale->output_video_width, colorscale->output_video_height, 0, FALSE); //blocking call - gst_gl_display_initDonwloadFBO (colorscale->display, colorscale->outWidth, colorscale->outHeight); + gst_gl_display_initDonwloadFBO (colorscale->display, + colorscale->output_video_width, colorscale->output_video_height); return ret; } @@ -412,11 +413,9 @@ gst_gl_colorscale_get_unit_size (GstBaseTransform* trans, GstCaps* caps, structure = gst_caps_get_structure (caps, 0); if (gst_structure_has_name (structure, "video/x-raw-gl")) { - GstVideoFormat video_format; - - 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); } else { @@ -437,26 +436,26 @@ gst_gl_colorscale_transform (GstBaseTransform* trans, GstBuffer* inbuf, GstGLColorscale* colorscale = GST_GL_COLORSCALE (trans); //blocking call - GstGLBuffer* gl_tembuf = gst_gl_buffer_new_from_video_format (colorscale->display, - colorscale->inVideo_format, - colorscale->outWidth, colorscale->outHeight, - colorscale->inWidth, colorscale->inHeight, - colorscale->inWidth, colorscale->inHeight); + GstGLBuffer* gl_temp_buffer = gst_gl_buffer_new (colorscale->display, + colorscale->output_video_width, colorscale->output_video_height); GST_DEBUG ("input size %p size %d", GST_BUFFER_DATA (inbuf), GST_BUFFER_SIZE (inbuf)); //blocking call - gst_gl_display_textureChanged(colorscale->display, colorscale->inVideo_format, - gl_tembuf->texture, gl_tembuf->texture_u, gl_tembuf->texture_v, - gl_tembuf->width, gl_tembuf->height, GST_BUFFER_DATA (inbuf), &gl_tembuf->textureGL); + gst_gl_display_do_upload (colorscale->display, colorscale->input_video_format, + colorscale->input_video_width, colorscale->input_video_height, GST_BUFFER_DATA (inbuf), + gl_temp_buffer->width, gl_temp_buffer->height, gl_temp_buffer->texture); GST_DEBUG ("output size %p size %d", GST_BUFFER_DATA (outbuf), GST_BUFFER_SIZE (outbuf)); //blocking call - gst_gl_display_videoChanged(colorscale->display, colorscale->outVideo_format, - gl_tembuf->width, gl_tembuf->height, gl_tembuf->textureGL, GST_BUFFER_DATA (outbuf)); + gst_gl_display_videoChanged(colorscale->display, colorscale->output_video_format, + gl_temp_buffer->width, gl_temp_buffer->height, gl_temp_buffer->texture, + GST_BUFFER_DATA (outbuf)); + + gst_buffer_unref (gl_temp_buffer); return GST_FLOW_OK; } diff --git a/gst/gl/gstglcolorscale.h b/gst/gl/gstglcolorscale.h index 48abc98f25..7699d22091 100644 --- a/gst/gl/gstglcolorscale.h +++ b/gst/gl/gstglcolorscale.h @@ -48,12 +48,14 @@ struct _GstGLColorscale GstPad *sinkpad; GstGLDisplay *display; - GstVideoFormat inVideo_format; - gint inWidth; - gint inHeight; - GstVideoFormat outVideo_format; - gint outWidth; - gint outHeight; + + GstVideoFormat input_video_format; + gint input_video_width; + gint input_video_height; + + GstVideoFormat output_video_format; + gint output_video_width; + gint output_video_height; }; struct _GstGLColorscaleClass diff --git a/gst/gl/gstgldownload.c b/gst/gl/gstgldownload.c index ffd4f2f56a..cfaee3e8d9 100644 --- a/gst/gl/gstgldownload.c +++ b/gst/gl/gstgldownload.c @@ -270,11 +270,9 @@ gst_gl_download_get_unit_size (GstBaseTransform* trans, GstCaps* caps, structure = gst_caps_get_structure (caps, 0); if (gst_structure_has_name (structure, "video/x-raw-gl")) { - GstVideoFormat video_format; - - 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); } else { @@ -309,7 +307,7 @@ gst_gl_download_transform (GstBaseTransform* trans, GstBuffer* inbuf, //blocking call gst_gl_display_videoChanged(download->display, download->video_format, - gl_inbuf->width, gl_inbuf->height, gl_inbuf->textureGL, GST_BUFFER_DATA (outbuf)); + gl_inbuf->width, gl_inbuf->height, gl_inbuf->texture, GST_BUFFER_DATA (outbuf)); return GST_FLOW_OK; } diff --git a/gst/gl/gstglfilterapp.c b/gst/gl/gstglfilterapp.c index 77517f0ab9..a5bfd781bf 100644 --- a/gst/gl/gstglfilterapp.c +++ b/gst/gl/gstglfilterapp.c @@ -56,6 +56,7 @@ static gboolean gst_gl_filter_app_set_caps (GstGLFilter* filter, static void gst_gl_filter_app_setClientCallbacks (GstGLFilter* filter); static gboolean gst_gl_filter_app_filter (GstGLFilter* filter, GstGLBuffer* inbuf, GstGLBuffer* outbuf); +static void gst_gl_filter_app_callback (guint width, guint height, guint texture, GLhandleARB shader); static void @@ -164,14 +165,39 @@ gst_gl_filter_app_filter (GstGLFilter* filter, GstGLBuffer* inbuf, { //GstGLFilterApp* app_filter = GST_GL_FILTER_APP(filter); - outbuf->width = inbuf->width; - outbuf->height = inbuf->height; - outbuf->texture = inbuf->texture; - outbuf->texture_u = inbuf->texture_u; - outbuf->texture_v = inbuf->texture_v; - outbuf->widthGL = inbuf->widthGL; - outbuf->heightGL = inbuf->heightGL; - outbuf->textureGL = inbuf->textureGL; + //blocking call, use a FBO + gst_gl_display_useFBO (filter->display, filter->width, filter->height, + filter->fbo, filter->depthbuffer, outbuf->texture, gst_gl_filter_app_callback, + inbuf->width, inbuf->height, inbuf->texture, 0); return TRUE; } + +//opengl scene, params: input texture (not the output filter->texture) +static void +gst_gl_filter_app_callback (guint width, guint height, guint texture, GLhandleARB shader) +{ + glEnable (GL_TEXTURE_RECTANGLE_ARB); + glBindTexture (GL_TEXTURE_RECTANGLE_ARB, texture); + 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); + glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); + + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + glMatrixMode (GL_PROJECTION); + glLoadIdentity (); + + glBegin (GL_QUADS); + glTexCoord2i (0, 0); + glVertex2f (-1.0f, -1.0f); + glTexCoord2i (width, 0); + glVertex2f (1.0f, -1.0f); + glTexCoord2i (width, height); + glVertex2f (1.0f, 1.0f); + glTexCoord2i (0, height); + glVertex2f (-1.0f, 1.0f); + glEnd (); +} diff --git a/gst/gl/gstglfiltercube.c b/gst/gl/gstglfiltercube.c index 5b74cc9178..1832696baf 100644 --- a/gst/gl/gstglfiltercube.c +++ b/gst/gl/gstglfiltercube.c @@ -114,17 +114,10 @@ gst_gl_filter_cube_filter (GstGLFilter* filter, GstGLBuffer* inbuf, { //GstGLFilterCube* cube_filter = GST_GL_FILTER_CUBE(filter); - //blocking call, generate a FBO + //blocking call, use a FBO gst_gl_display_useFBO (filter->display, filter->width, filter->height, - filter->fbo, filter->depthbuffer, filter->texture, gst_gl_filter_cube_callback, - inbuf->width, inbuf->height, inbuf->textureGL, 0); - - outbuf->width = inbuf->width; - outbuf->height = inbuf->height; - outbuf->texture = inbuf->texture; - outbuf->texture_u = inbuf->texture_u; - outbuf->texture_v = inbuf->texture_v; - outbuf->textureGL = filter->texture; + filter->fbo, filter->depthbuffer, outbuf->texture, gst_gl_filter_cube_callback, + inbuf->width, inbuf->height, inbuf->texture, 0); return TRUE; } diff --git a/gst/gl/gstglfilteredge.c b/gst/gl/gstglfilteredge.c index 55084c9792..21b7067705 100644 --- a/gst/gl/gstglfilteredge.c +++ b/gst/gl/gstglfilteredge.c @@ -170,15 +170,8 @@ gst_gl_filter_edge_filter (GstGLFilter* filter, GstGLBuffer* inbuf, //blocking call, generate a FBO gst_gl_display_useFBO (filter->display, filter->width, filter->height, - filter->fbo, filter->depthbuffer, filter->texture, gst_gl_filter_edge_callback, - inbuf->width, inbuf->height, inbuf->textureGL, edge_filter->handleShader); - - outbuf->width = inbuf->width; - outbuf->height = inbuf->height; - outbuf->texture = inbuf->texture; - outbuf->texture_u = inbuf->texture_u; - outbuf->texture_v = inbuf->texture_v; - outbuf->textureGL = filter->texture; + filter->fbo, filter->depthbuffer, outbuf->texture, gst_gl_filter_edge_callback, + inbuf->width, inbuf->height, inbuf->texture, edge_filter->handleShader); return TRUE; } @@ -214,7 +207,6 @@ gst_gl_filter_edge_callback (guint width, guint height, guint texture, GLhandleA glTexCoord2i (width, height); glVertex2f (1.0f, 1.0f); glTexCoord2i (0, height); - glVertex2f (-1.0f, 1.0f); - + glVertex2f (-1.0f, 1.0f); glEnd (); } diff --git a/gst/gl/gstglimagesink.c b/gst/gl/gstglimagesink.c index 5c58dd74ba..1a5957f0c5 100644 --- a/gst/gl/gstglimagesink.c +++ b/gst/gl/gstglimagesink.c @@ -444,15 +444,13 @@ gst_glimage_sink_render (GstBaseSink* bsink, GstBuffer* buf) } //blocking call - gl_buffer = gst_gl_buffer_new_from_video_format (glimage_sink->display, - glimage_sink->format, glimage_sink->width, glimage_sink->height, - glimage_sink->width, glimage_sink->height, + gl_buffer = gst_gl_buffer_new (glimage_sink->display, glimage_sink->width, glimage_sink->height); //blocking call - gst_gl_display_textureChanged(glimage_sink->display, glimage_sink->format, - gl_buffer->texture, gl_buffer->texture_u, gl_buffer->texture_v, - gl_buffer->width, gl_buffer->height, GST_BUFFER_DATA (buf), &gl_buffer->textureGL); + gst_gl_display_do_upload(glimage_sink->display, glimage_sink->format, + glimage_sink->width, glimage_sink->height, GST_BUFFER_DATA (buf), + gl_buffer->width, gl_buffer->height, gl_buffer->texture); //gl_buffer is created in this block, so the gl buffer is already referenced } @@ -469,7 +467,7 @@ gst_glimage_sink_render (GstBaseSink* bsink, GstBuffer* buf) //redisplay opengl scene isAlive = gst_gl_display_postRedisplay (glimage_sink->display, - gl_buffer->textureGL, gl_buffer->widthGL, gl_buffer->heightGL); + gl_buffer->texture, gl_buffer->width, gl_buffer->height); if (isAlive) return GST_FLOW_OK; diff --git a/gst/gl/gstgltestsrc.c b/gst/gl/gstgltestsrc.c index f5b22457d1..3a7fea8122 100644 --- a/gst/gl/gstgltestsrc.c +++ b/gst/gl/gstgltestsrc.c @@ -369,7 +369,7 @@ gst_gl_test_src_setcaps (GstBaseSrc* bsrc, GstCaps* caps) gltestsrc->width, gltestsrc->height, 0, FALSE); gst_gl_display_requestFBO (gltestsrc->display, gltestsrc->width, gltestsrc->height, - &gltestsrc->fbo, &gltestsrc->depthbuffer, &gltestsrc->texture); + &gltestsrc->fbo, &gltestsrc->depthbuffer); } return res; } @@ -543,10 +543,7 @@ gst_gl_test_src_create (GstPushSrc* psrc, GstBuffer** buffer) GST_LOG_OBJECT (src, "creating buffer %dx%d image for frame %d", src->width, src->height, (gint) src->n_frames); - outbuf = gst_gl_buffer_new_from_video_format (src->display, - GST_VIDEO_FORMAT_UNKNOWN, - src->width, src->height, - src->width, src->height, + outbuf = gst_gl_buffer_new (src->display, src->width, src->height); gst_buffer_set_caps (GST_BUFFER (outbuf), @@ -562,9 +559,8 @@ gst_gl_test_src_create (GstPushSrc* psrc, GstBuffer** buffer) //blocking call, generate a FBO gst_gl_display_useFBO2 (src->display, src->width, src->height, - src->fbo, src->depthbuffer, src->texture, (GLCB2)src->make_image, + src->fbo, src->depthbuffer, outbuf->texture, (GLCB2)src->make_image, (gpointer*)src, (gpointer*)outbuf); - outbuf->textureGL = src->texture; GST_BUFFER_TIMESTAMP (GST_BUFFER (outbuf)) = src->timestamp_offset + src->running_time; @@ -631,7 +627,7 @@ gst_gl_test_src_stop (GstBaseSrc* basesrc) { //blocking call, delete the FBO gst_gl_display_rejectFBO (src->display, src->fbo, - src->depthbuffer, src->texture); + src->depthbuffer); g_object_unref (src->display); src->display = NULL; } diff --git a/gst/gl/gstgltestsrc.h b/gst/gl/gstgltestsrc.h index 776a488159..9f7dbf220f 100644 --- a/gst/gl/gstgltestsrc.h +++ b/gst/gl/gstgltestsrc.h @@ -98,7 +98,6 @@ struct _GstGLTestSrc { guint fbo; guint depthbuffer; - guint texture; /* private */ GstGLDisplay *display; diff --git a/gst/gl/gstglupload.c b/gst/gl/gstglupload.c index 835c66ea9f..f50e7ab85a 100644 --- a/gst/gl/gstglupload.c +++ b/gst/gl/gstglupload.c @@ -377,54 +377,53 @@ gst_gl_upload_set_caps (GstBaseTransform* bt, GstCaps* incaps, GstGLUpload* upload = GST_GL_UPLOAD (bt); gboolean ret = FALSE; GstVideoFormat video_format = GST_VIDEO_FORMAT_UNKNOWN; - static gint glcontext_y = 0; + static gint y_pos = 0; GST_DEBUG ("called with %" GST_PTR_FORMAT, incaps); ret = gst_video_format_parse_caps (outcaps, &video_format, - &upload->outWidth, &upload->outHeight); + &upload->gl_width, &upload->gl_height); ret |= gst_video_format_parse_caps (incaps, &upload->video_format, - &upload->inWidth, &upload->inHeight); + &upload->video_width, &upload->video_height); if (!ret) { - GST_DEBUG ("bad caps"); - return FALSE; + GST_DEBUG ("caps connot be parsed"); + return FALSE; } + //we have video and gl size, we can now init OpenGL stuffs upload->display = gst_gl_display_new (); //init unvisible opengl context gst_gl_display_initGLContext (upload->display, - 50, glcontext_y++ * (upload->inHeight+50) + 50, - upload->inWidth, upload->inHeight, - upload->inWidth, upload->inHeight, 0, FALSE); + 50, y_pos++ * (upload->gl_height+50) + 50, + upload->gl_width, upload->gl_height, + upload->gl_width, upload->gl_height, 0, FALSE); return ret; } static gboolean gst_gl_upload_get_unit_size (GstBaseTransform* trans, GstCaps* caps, - guint* size) + guint* size) { - gboolean ret; - GstStructure *structure; - gint width; - gint height; + gboolean ret = FALSE; + GstStructure* structure = NULL; + gint width = 0; + gint height = 0; structure = gst_caps_get_structure (caps, 0); if (gst_structure_has_name (structure, "video/x-raw-gl")) { - GstVideoFormat video_format; - - 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); } else { - GstVideoFormat video_format; + GstVideoFormat video_format = GST_VIDEO_FORMAT_UNKNOWN; ret = gst_video_format_parse_caps (caps, &video_format, &width, &height); if (ret) @@ -438,17 +437,12 @@ static GstFlowReturn gst_gl_upload_prepare_output_buffer (GstBaseTransform* trans, GstBuffer* input, gint size, GstCaps* caps, GstBuffer** buf) { - GstGLUpload* upload; - GstGLBuffer* gl_outbuf; + GstGLUpload* upload = GST_GL_UPLOAD (trans); - upload = GST_GL_UPLOAD (trans); + //blocking call, request a texture and attach it to the upload FBO + GstGLBuffer* gl_outbuf = gst_gl_buffer_new (upload->display, + upload->gl_width, upload->gl_height); - //blocking call - gl_outbuf = gst_gl_buffer_new_from_video_format (upload->display, - upload->video_format, - upload->outWidth, upload->outHeight, - upload->inWidth, upload->inHeight, - upload->inWidth, upload->inHeight); *buf = GST_BUFFER (gl_outbuf); gst_buffer_set_caps (*buf, caps); @@ -460,18 +454,19 @@ static GstFlowReturn gst_gl_upload_transform (GstBaseTransform* trans, GstBuffer* inbuf, GstBuffer* outbuf) { - GstGLUpload* upload; + GstGLUpload* upload = GST_GL_UPLOAD (trans); GstGLBuffer* gl_outbuf = GST_GL_BUFFER (outbuf); - upload = GST_GL_UPLOAD (trans); - - GST_DEBUG ("making graphic %p size %d", + GST_DEBUG ("Upload %p size %d", GST_BUFFER_DATA (inbuf), GST_BUFFER_SIZE (inbuf)); - //blocking call - gst_gl_display_textureChanged(upload->display, upload->video_format, - gl_outbuf->texture, gl_outbuf->texture_u, gl_outbuf->texture_v, - gl_outbuf->width, gl_outbuf->height, GST_BUFFER_DATA (inbuf), &gl_outbuf->textureGL); + //blocking call. + //Depending on the colorspace, video is upload into several textures. + //However, there is only one output texture. The one attached + //to the upload FBO. + gst_gl_display_do_upload (upload->display, upload->video_format, + upload->video_width, upload->video_height, GST_BUFFER_DATA (inbuf), + gl_outbuf->width, gl_outbuf->height, gl_outbuf->texture); return GST_FLOW_OK; } diff --git a/gst/gl/gstglupload.h b/gst/gl/gstglupload.h index 47db1c7866..a6ad46d3b1 100644 --- a/gst/gl/gstglupload.h +++ b/gst/gl/gstglupload.h @@ -48,11 +48,12 @@ struct _GstGLUpload GstPad *sinkpad; GstGLDisplay *display; + GstVideoFormat video_format; - gint inWidth; - gint inHeight; - gint outWidth; - gint outHeight; + gint video_width; + gint video_height; + gint gl_width; + gint gl_height; }; struct _GstGLUploadClass