[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 Matthew Waters
parent 04946b3f1d
commit e7f5afee87
17 changed files with 337 additions and 393 deletions

View file

@ -30,8 +30,7 @@ static void
gst_gl_buffer_finalize (GstGLBuffer* buffer) gst_gl_buffer_finalize (GstGLBuffer* buffer)
{ {
//wait clear textures end, blocking call //wait clear textures end, blocking call
gst_gl_display_clearTexture (buffer->display, buffer->texture, gst_gl_display_clearTexture (buffer->display, buffer->texture);
buffer->texture_u, buffer->texture_v);
g_object_unref (buffer->display); g_object_unref (buffer->display);
@ -43,15 +42,10 @@ static void
gst_gl_buffer_init (GstGLBuffer* buffer, gpointer g_class) gst_gl_buffer_init (GstGLBuffer* buffer, gpointer g_class)
{ {
buffer->display = NULL; buffer->display = NULL;
buffer->video_format = 0;
buffer->width = 0; buffer->width = 0;
buffer->height = 0; buffer->height = 0;
buffer->texture = 0; buffer->texture = 0;
buffer->texture_u = 0;
buffer->texture_v = 0;
buffer->widthGL = 0;
buffer->heightGL = 0;
buffer->textureGL = 0;
} }
static void static void
@ -92,57 +86,43 @@ gst_gl_buffer_get_type (void)
GstGLBuffer* GstGLBuffer*
gst_gl_buffer_new_from_video_format (GstGLDisplay* display, gst_gl_buffer_new (GstGLDisplay* display,
GstVideoFormat video_format, gint context_width, gint context_height, gint gl_width, gint gl_height)
gint widthGL, gint heightGL,
gint width, gint 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); gl_buffer->display = g_object_ref (display);
g_return_val_if_fail (display != NULL, NULL); gl_buffer->width = gl_width;
g_return_val_if_fail (width > 0, NULL); gl_buffer->height = gl_height;
g_return_val_if_fail (height > 0, NULL);
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); //blocking call, request a texture and attach it to the upload FBO
buffer->width = width; gst_gl_display_prepare_texture (gl_buffer->display, &gl_buffer->texture) ;
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, init texture return gl_buffer;
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;
} }
int gint
gst_gl_buffer_format_get_size (GstVideoFormat format, int width, int height) gst_gl_buffer_get_size (gint width, gint height)
{ {
/* this is not strictly true, but it's used for compatibility with //this is not strictly true, but it's used for compatibility with
* queue and BaseTransform */ //queue and BaseTransform
return width * height * 4; return width * height * 4;
} }
gboolean gboolean
gst_gl_buffer_format_parse_caps (GstCaps * caps, GstVideoFormat * format, gst_gl_buffer_parse_caps (GstCaps* caps, gint* width, gint* height)
gint* width, gint* height)
{ {
GstStructure *structure; GstStructure* structure = gst_caps_get_structure (caps, 0);
gboolean ret; gboolean ret = gst_structure_has_name (structure, "video/x-raw-gl");
structure = gst_caps_get_structure (caps, 0); if (!ret)
return ret;
if (!gst_structure_has_name (structure, "video/x-raw-gl"))
return FALSE;
ret = gst_structure_get_int (structure, "width", width); ret = gst_structure_get_int (structure, "width", width);
ret &= gst_structure_get_int (structure, "height", height); 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_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)) #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 { struct _GstGLBuffer {
GstBuffer buffer; GstBuffer buffer;
GstGLDisplay *display; GstGLDisplay *display;
GstVideoFormat video_format;
gint width; gint width;
gint height; gint height;
GLuint texture; GLuint texture;
GLuint texture_u;
GLuint texture_v;
gint widthGL;
gint heightGL;
GLuint textureGL;
}; };
GType gst_gl_buffer_get_type (void); 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_ref(x) ((GstGLBuffer *)(gst_buffer_ref((GstBuffer *)(x))))
#define gst_gl_buffer_unref(x) (gst_buffer_unref((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, GstGLBuffer* gst_gl_buffer_new (GstGLDisplay* display, gint gl_width, gint gl_height);
gint context_width, gint context_height, gint gst_gl_buffer_get_size (gint width, gint height);
gint widthGL, gint heightGL, gboolean gst_gl_buffer_parse_caps (GstCaps* caps, gint* width, gint* height);
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);
#define GST_GL_VIDEO_CAPS \ #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_texture (GstGLDisplay* display);
void gst_gl_display_draw_graphic (GstGLDisplay* display); void gst_gl_display_draw_graphic (GstGLDisplay* display);
void gst_gl_display_fill_video (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); GLhandleARB gst_gl_display_loadGLSLprogram (gchar* textFProgram);
void checkFramebufferStatus(void); void checkFramebufferStatus(void);
GST_BOILERPLATE (GstGLDisplay, gst_gl_display, GObject, G_TYPE_OBJECT); 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->requestedFBO = 0;
display->requestedDepthBuffer = 0; display->requestedDepthBuffer = 0;
display->requestedTextureFBO = 0;
display->requestedTextureFBOWidth = 0; display->requestedTextureFBOWidth = 0;
display->requestedTextureFBOHeight = 0; display->requestedTextureFBOHeight = 0;
display->usedFBO = 0; display->usedFBO = 0;
@ -140,37 +141,22 @@ gst_gl_display_init (GstGLDisplay *display, GstGLDisplayClass *klass)
display->inputTexture = 0; display->inputTexture = 0;
display->rejectedFBO = 0; display->rejectedFBO = 0;
display->rejectedDepthBuffer = 0; display->rejectedDepthBuffer = 0;
display->rejectedTextureFBO = 0;
display->displayedTexture = 0; display->displayedTexture = 0;
display->displayedTextureWidth = 0; display->displayedTextureWidth = 0;
display->displayedTextureHeight = 0; display->displayedTextureHeight = 0;
display->requestedTexture = 0; display->preparedTexture = 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->currentTexture = 0; display->currentTexture = 0;
display->currentTexture_u = 0; display->currentTexture_u = 0;
display->currentTexture_v = 0; display->currentTexture_v = 0;
display->currentVideo_format = 0;
display->currentTextureWidth = 0; display->currentTextureWidth = 0;
display->currentTextureHeight = 0; display->currentTextureHeight = 0;
display->currentVideo_format = 0;
display->currentData = NULL;
display->textureTrash = 0; display->textureTrash = 0;
display->textureTrash_u = 0;
display->textureTrash_v = 0;
display->videoFBO = 0; display->videoFBO = 0;
display->videoDepthBuffer = 0; display->videoDepthBuffer = 0;
@ -497,10 +483,10 @@ gst_gl_display_glutCreateWindow (GstGLDisplay *display)
{ {
//OpenGL > 2.1.0 and Glew > 1.5.0 //OpenGL > 2.1.0 and Glew > 1.5.0
GString* opengl_version = g_string_truncate (g_string_new ((gchar*) glGetString (GL_VERSION)), 3); 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; gint opengl_version_minor = 0;
GString* glew_version = g_string_truncate (g_string_new ((gchar*) glewGetString (GLEW_VERSION)), 3); 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; gint glew_version_minor = 0;
sscanf(opengl_version->str, "%d.%d", &opengl_version_major, &opengl_version_minor); 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) 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); GST_DEBUG ("Context %d, EXT_framebuffer_object supported: yes", glutWinId);
//-- init intput frame buffer object (video -> GL) //-- init intput frame buffer object (video -> GL)
@ -540,29 +529,29 @@ gst_gl_display_glutCreateWindow (GstGLDisplay *display)
display->textureFBOWidth, display->textureFBOHeight); display->textureFBOWidth, display->textureFBOHeight);
//setup a texture to render to //setup a texture to render to
glGenTextures (1, &display->textureFBO); glGenTextures (1, &fake_texture);
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, display->textureFBO); glBindTexture(GL_TEXTURE_RECTANGLE_ARB, fake_texture);
glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA8, glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA8,
display->textureFBOWidth, display->textureFBOHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); 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 //attach the texture to the FBO to renderer to
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, 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 //attach the depth render buffer to the FBO
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT,
GL_RENDERBUFFER_EXT, display->depthBuffer); GL_RENDERBUFFER_EXT, display->depthBuffer);
checkFramebufferStatus();
g_assert (glCheckFramebufferStatusEXT (GL_FRAMEBUFFER_EXT) == g_assert (glCheckFramebufferStatusEXT (GL_FRAMEBUFFER_EXT) ==
GL_FRAMEBUFFER_COMPLETE_EXT); GL_FRAMEBUFFER_COMPLETE_EXT);
//unbind the FBO //unbind the FBO
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
glDeleteTextures (1, &fake_texture);
} }
else else
{ {
@ -621,7 +610,6 @@ gst_gl_display_glutGenerateOutputVideoFBO (GstGLDisplay *display)
{ {
glutSetWindow (display->glutWinId); glutSetWindow (display->glutWinId);
if (GLEW_EXT_framebuffer_object) if (GLEW_EXT_framebuffer_object)
{ {
GST_DEBUG ("Context %d, EXT_framebuffer_object supported: yes", display->glutWinId); 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, glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT,
GL_RENDERBUFFER_EXT, display->graphicDepthBuffer); GL_RENDERBUFFER_EXT, display->graphicDepthBuffer);
checkFramebufferStatus();
g_assert (glCheckFramebufferStatusEXT (GL_FRAMEBUFFER_EXT) == g_assert (glCheckFramebufferStatusEXT (GL_FRAMEBUFFER_EXT) ==
GL_FRAMEBUFFER_COMPLETE_EXT); GL_FRAMEBUFFER_COMPLETE_EXT);
@ -772,7 +762,9 @@ gst_gl_display_glutGenerateOutputVideoFBO (GstGLDisplay *display)
static void static void
gst_gl_display_glutGenerateFBO (GstGLDisplay *display) gst_gl_display_glutGenerateFBO (GstGLDisplay *display)
{ {
//a texture must be attached to the FBO
guint fake_texture = 0;
glutSetWindow (display->glutWinId); glutSetWindow (display->glutWinId);
//-- generate frame buffer object //-- generate frame buffer object
@ -788,18 +780,14 @@ gst_gl_display_glutGenerateFBO (GstGLDisplay *display)
display->requestedTextureFBOWidth, display->requestedTextureFBOHeight); display->requestedTextureFBOWidth, display->requestedTextureFBOHeight);
//setup a texture to render to //setup a texture to render to
glGenTextures (1, &display->requestedTextureFBO); glGenTextures (1, &fake_texture);
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, display->requestedTextureFBO); glBindTexture(GL_TEXTURE_RECTANGLE_ARB, fake_texture);
glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA8, glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA8,
display->requestedTextureFBOWidth, display->requestedTextureFBOHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); 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 //attach the texture to the FBO to renderer to
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, 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 //attach the depth render buffer to the FBO
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT,
@ -811,6 +799,8 @@ gst_gl_display_glutGenerateFBO (GstGLDisplay *display)
//unbind the FBO //unbind the FBO
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
glDeleteTextures (1, &fake_texture);
g_cond_signal (display->cond_generateFBO); g_cond_signal (display->cond_generateFBO);
} }
@ -824,6 +814,19 @@ gst_gl_display_glutUseFBO (GstGLDisplay *display)
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, display->usedFBO); 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); glPushAttrib(GL_VIEWPORT_BIT);
glMatrixMode(GL_PROJECTION); glMatrixMode(GL_PROJECTION);
@ -872,12 +875,24 @@ gst_gl_display_glutUseFBO2 (GstGLDisplay *display)
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, display->usedFBO); 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); glPushAttrib(GL_VIEWPORT_BIT);
glMatrixMode(GL_PROJECTION); glMatrixMode(GL_PROJECTION);
glPushMatrix(); glPushMatrix();
glLoadIdentity(); glLoadIdentity();
//gluPerspective(45, (gfloat)display->usedTextureFBOWidth/(gfloat)display->usedTextureFBOHeight, 0.1, 100);
gluOrtho2D(0.0, display->usedTextureFBOWidth, 0.0, display->usedTextureFBOHeight); gluOrtho2D(0.0, display->usedTextureFBOWidth, 0.0, display->usedTextureFBOHeight);
glMatrixMode(GL_MODELVIEW); glMatrixMode(GL_MODELVIEW);
@ -919,10 +934,8 @@ gst_gl_display_glutDestroyFBO (GstGLDisplay* display)
glDeleteFramebuffersEXT (1, &display->rejectedFBO); glDeleteFramebuffersEXT (1, &display->rejectedFBO);
glDeleteRenderbuffersEXT(1, &display->rejectedDepthBuffer); glDeleteRenderbuffersEXT(1, &display->rejectedDepthBuffer);
glDeleteTextures (1, &display->rejectedTextureFBO);
display->rejectedFBO = 0; display->rejectedFBO = 0;
display->rejectedDepthBuffer = 0; display->rejectedDepthBuffer = 0;
display->rejectedTextureFBO = 0;
g_cond_signal (display->cond_destroyFBO); g_cond_signal (display->cond_destroyFBO);
} }
@ -970,7 +983,6 @@ gst_gl_display_glutDestroyWindow (GstGLDisplay *display)
glDeleteFramebuffersEXT (1, &display->fbo); glDeleteFramebuffersEXT (1, &display->fbo);
glDeleteRenderbuffersEXT(1, &display->depthBuffer); glDeleteRenderbuffersEXT(1, &display->depthBuffer);
glDeleteTextures (1, &display->textureFBO);
glDeleteFramebuffersEXT (1, &display->graphicFBO); glDeleteFramebuffersEXT (1, &display->graphicFBO);
glDeleteRenderbuffersEXT(1, &display->graphicDepthBuffer); glDeleteRenderbuffersEXT(1, &display->graphicDepthBuffer);
@ -986,15 +998,8 @@ gst_gl_display_glutDestroyWindow (GstGLDisplay *display)
while (g_queue_get_length (display->texturePool)) while (g_queue_get_length (display->texturePool))
{ {
GstGLDisplayTex* tex = g_queue_pop_head (display->texturePool); GstGLDisplayTex* tex = g_queue_pop_head (display->texturePool);
//delete textures
glDeleteTextures (1, &tex->texture); glDeleteTextures (1, &tex->texture);
if (tex->texture_u) { g_free (tex);
glDeleteTextures (1, &tex->texture_u);
}
if (tex->texture_v) {
glDeleteTextures (1, &tex->texture_v);
}
} }
g_hash_table_remove (gst_gl_display_map, GINT_TO_POINTER (display->glutWinId)); 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) gst_gl_display_glutPrepareTexture (GstGLDisplay * display)
{ {
glutSetWindow (display->glutWinId); 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); g_cond_signal (display->cond_make);
} }
@ -1046,6 +1052,7 @@ static void
gst_gl_display_glutUpdateTexture (GstGLDisplay * display) gst_gl_display_glutUpdateTexture (GstGLDisplay * display)
{ {
glutSetWindow (display->glutWinId); glutSetWindow (display->glutWinId);
gst_gl_display_make_texture (display);
gst_gl_display_fill_texture (display); gst_gl_display_fill_texture (display);
gst_gl_display_draw_texture (display); gst_gl_display_draw_texture (display);
g_cond_signal (display->cond_fill); g_cond_signal (display->cond_fill);
@ -1054,25 +1061,10 @@ gst_gl_display_glutUpdateTexture (GstGLDisplay * display)
/* Called by the idle function */ /* Called by the idle function */
static void static void
gst_gl_display_glutCleanTexture (GstGLDisplay * display) gst_gl_display_glutCleanTexture (GstGLDisplay* display)
{ {
GstGLDisplayTex* tex = NULL;
glutSetWindow (display->glutWinId); glutSetWindow (display->glutWinId);
gst_gl_display_del_texture (display, &display->textureTrash);
//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);
g_cond_signal (display->cond_clear); g_cond_signal (display->cond_clear);
} }
@ -1348,55 +1340,40 @@ gst_gl_display_resizeWindow (GstGLDisplay* display, gint width, gint height)
/* Called by gstglbuffer */ /* Called by gstglbuffer */
void void
gst_gl_display_textureRequested (GstGLDisplay* display, GstVideoFormat video_format, gst_gl_display_prepare_texture (GstGLDisplay* display, guint* pTexture)
gint width, gint height, guint* texture,
guint* texture_u, guint* texture_v)
{ {
gst_gl_display_lock (display); 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); gst_gl_display_postMessage (GST_GL_DISPLAY_ACTION_PREPARE, display);
g_cond_wait (display->cond_make, display->mutex); g_cond_wait (display->cond_make, display->mutex);
*texture = display->requestedTexture; *pTexture = display->preparedTexture;
*texture_u = display->requestedTexture_u;
*texture_v = display->requestedTexture_v;
gst_gl_display_unlock (display); gst_gl_display_unlock (display);
} }
/* Called by gst_gl elements */ /* Called by gst_gl elements */
void void
gst_gl_display_textureChanged (GstGLDisplay* display, GstVideoFormat video_format, gst_gl_display_do_upload (GstGLDisplay* display, GstVideoFormat video_format,
GLuint texture, GLuint texture_u, GLuint texture_v, gint video_width, gint video_height, gpointer data,
gint width, gint height, gpointer data, GLuint* outputTexture) guint gl_width, guint gl_height, guint pTexture)
{ {
gst_gl_display_lock (display); gst_gl_display_lock (display);
display->candidateTexture = texture; display->currentTextureWidth = video_width;
display->candidateTexture_u = texture_u; display->currentTextureHeight = video_height;
display->candidateTexture_v = texture_v; display->currentVideo_format = video_format;
display->candidateVideo_format = video_format; display->currentData = data;
display->candidateTextureWidth = width; display->textureFBO = pTexture;
display->candidateTextureHeight = height;
display->candidateData = data;
gst_gl_display_postMessage (GST_GL_DISPLAY_ACTION_CHANGE, display); gst_gl_display_postMessage (GST_GL_DISPLAY_ACTION_CHANGE, display);
g_cond_wait (display->cond_fill, display->mutex); 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); gst_gl_display_unlock (display);
} }
/* Called by gstglbuffer */ /* Called by gstglbuffer */
void void
gst_gl_display_clearTexture (GstGLDisplay* display, guint texture, gst_gl_display_clearTexture (GstGLDisplay* display, guint texture)
guint texture_u, guint texture_v)
{ {
gst_gl_display_lock (display); gst_gl_display_lock (display);
display->textureTrash = texture; display->textureTrash = texture;
display->textureTrash_u = texture_u;
display->textureTrash_v = texture_v;
gst_gl_display_postMessage (GST_GL_DISPLAY_ACTION_CLEAR, display); gst_gl_display_postMessage (GST_GL_DISPLAY_ACTION_CLEAR, display);
g_cond_wait (display->cond_clear, display->mutex); g_cond_wait (display->cond_clear, display->mutex);
gst_gl_display_unlock (display); gst_gl_display_unlock (display);
@ -1446,7 +1423,7 @@ gst_gl_display_postRedisplay (GstGLDisplay* display, GLuint texture, gint width
/* Called by gst_gl elements */ /* Called by gst_gl elements */
void void
gst_gl_display_requestFBO (GstGLDisplay* display, gint width, gint height, 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); gst_gl_display_lock (display);
display->requestedTextureFBOWidth = width; 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); g_cond_wait (display->cond_generateFBO, display->mutex);
*fbo = display->requestedFBO; *fbo = display->requestedFBO;
*depthbuffer = display->requestedDepthBuffer; *depthbuffer = display->requestedDepthBuffer;
*texture = display->requestedTextureFBO;
gst_gl_display_unlock (display); gst_gl_display_unlock (display);
} }
@ -1497,6 +1473,8 @@ gst_gl_display_useFBO2 (GstGLDisplay* display, gint textureFBOWidth, gint textur
display->usedTextureFBOWidth = textureFBOWidth; display->usedTextureFBOWidth = textureFBOWidth;
display->usedTextureFBOHeight = textureFBOheight; display->usedTextureFBOHeight = textureFBOheight;
display->glsceneFBO_cb2 = cb2; display->glsceneFBO_cb2 = cb2;
display->p1 = p1;
display->p2 = p2;
gst_gl_display_postMessage (GST_GL_DISPLAY_ACTION_USEFBO2, display); gst_gl_display_postMessage (GST_GL_DISPLAY_ACTION_USEFBO2, display);
g_cond_wait (display->cond_useFBO2, display->mutex); g_cond_wait (display->cond_useFBO2, display->mutex);
gst_gl_display_unlock (display); gst_gl_display_unlock (display);
@ -1506,12 +1484,11 @@ gst_gl_display_useFBO2 (GstGLDisplay* display, gint textureFBOWidth, gint textur
/* Called by gst_gl elements */ /* Called by gst_gl elements */
void void
gst_gl_display_rejectFBO (GstGLDisplay* display, guint fbo, gst_gl_display_rejectFBO (GstGLDisplay* display, guint fbo,
guint depthbuffer, guint texture) guint depthbuffer)
{ {
gst_gl_display_lock (display); gst_gl_display_lock (display);
display->rejectedFBO = fbo; display->rejectedFBO = fbo;
display->rejectedDepthBuffer = depthbuffer; display->rejectedDepthBuffer = depthbuffer;
display->rejectedTextureFBO = texture;
gst_gl_display_postMessage (GST_GL_DISPLAY_ACTION_DELFBO, display); gst_gl_display_postMessage (GST_GL_DISPLAY_ACTION_DELFBO, display);
g_cond_wait (display->cond_destroyFBO, display->mutex); g_cond_wait (display->cond_destroyFBO, display->mutex);
gst_gl_display_unlock (display); 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) */ /* called by gst_gl_display_glutUpdateTexture (in the glut thread) */
void gst_gl_display_make_texture (GstGLDisplay * display) 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 glBindTexture (GL_TEXTURE_RECTANGLE_ARB, display->currentTexture);
if (g_queue_get_length (display->texturePool)) switch (display->currentVideo_format)
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) {
case GST_VIDEO_FORMAT_RGBx: case GST_VIDEO_FORMAT_RGBx:
case GST_VIDEO_FORMAT_BGRx: case GST_VIDEO_FORMAT_BGRx:
case GST_VIDEO_FORMAT_xRGB: 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_ABGR:
case GST_VIDEO_FORMAT_AYUV: case GST_VIDEO_FORMAT_AYUV:
glTexImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA, 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; break;
case GST_VIDEO_FORMAT_RGB: case GST_VIDEO_FORMAT_RGB:
case GST_VIDEO_FORMAT_BGR: case GST_VIDEO_FORMAT_BGR:
glTexImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGB, 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; break;
case GST_VIDEO_FORMAT_YUY2: case GST_VIDEO_FORMAT_YUY2:
case GST_VIDEO_FORMAT_UYVY: case GST_VIDEO_FORMAT_UYVY:
glTexImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, GL_LUMINANCE_ALPHA, glTexImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, GL_LUMINANCE_ALPHA,
display->requestedTextureWidth, display->requestedTextureHeight, width, height,
0, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, NULL); 0, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, NULL);
//one tex is available gst_gl_display_gen_texture (display, &display->currentTexture_u);
if (tex)
display->requestedTexture_u = tex->texture_u;
else
glGenTextures (1, &display->requestedTexture_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, 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); 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL);
break; break;
case GST_VIDEO_FORMAT_I420: case GST_VIDEO_FORMAT_I420:
case GST_VIDEO_FORMAT_YV12: case GST_VIDEO_FORMAT_YV12:
glTexImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, GL_LUMINANCE, glTexImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, GL_LUMINANCE,
display->requestedTextureWidth, display->requestedTextureHeight, width, height,
0, GL_LUMINANCE, GL_UNSIGNED_BYTE, NULL); 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, NULL);
//one tex is available gst_gl_display_gen_texture (display, &display->currentTexture_u);
if (tex)
display->requestedTexture_u = tex->texture_u;
else
glGenTextures (1, &display->requestedTexture_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, glTexImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, GL_LUMINANCE,
GST_ROUND_UP_2 (display->requestedTextureWidth) / 2, GST_ROUND_UP_2 (width) / 2,
GST_ROUND_UP_2 (display->requestedTextureHeight) / 2, GST_ROUND_UP_2 (height) / 2,
0, GL_LUMINANCE, GL_UNSIGNED_BYTE, NULL); 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, NULL);
//one tex is available gst_gl_display_gen_texture (display, &display->currentTexture_v);
if (tex)
display->requestedTexture_v = tex->texture_v;
else
glGenTextures (1, &display->requestedTexture_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, glTexImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, GL_LUMINANCE,
GST_ROUND_UP_2 (display->requestedTextureWidth) / 2, GST_ROUND_UP_2 (width) / 2,
GST_ROUND_UP_2 (display->requestedTextureHeight) / 2, GST_ROUND_UP_2 (height) / 2,
0, GL_LUMINANCE, GL_UNSIGNED_BYTE, NULL); 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, NULL);
break; break;
default: default:
g_assert_not_reached (); g_assert_not_reached ();
} }
if (tex)
g_free (tex);
} }
/* called by gst_gl_display_glutUpdateTexture (in the glut thread) */ /* called by gst_gl_display_glutUpdateTexture (in the glut thread) */
void void
gst_gl_display_fill_texture (GstGLDisplay * display) gst_gl_display_fill_texture (GstGLDisplay * display)
{ {
GstVideoFormat video_format = display->candidateVideo_format; gint width = display->currentTextureWidth;
gint width = display->candidateTextureWidth; gint height = display->currentTextureHeight;
gint height = display->candidateTextureHeight; GstVideoFormat video_format = display->currentVideo_format;
gpointer data = display->candidateData; gpointer data = display->currentData;
glBindTexture (GL_TEXTURE_RECTANGLE_ARB, display->candidateTexture); glBindTexture (GL_TEXTURE_RECTANGLE_ARB, display->currentTexture);
switch (video_format) { switch (video_format) {
case GST_VIDEO_FORMAT_RGBx: 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, glTexSubImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, 0, 0, width, height,
GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, data); 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, glTexSubImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, 0, 0,
GST_ROUND_UP_2 (width) / 2, height, GST_ROUND_UP_2 (width) / 2, height,
GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, data); 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, glTexSubImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, 0, 0, width, height,
GL_LUMINANCE, GL_UNSIGNED_BYTE, data); 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, glTexSubImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, 0, 0,
GST_ROUND_UP_2 (width) / 2, GST_ROUND_UP_2 (height) / 2, GST_ROUND_UP_2 (width) / 2, GST_ROUND_UP_2 (height) / 2,
GL_LUMINANCE, GL_UNSIGNED_BYTE, GL_LUMINANCE, GL_UNSIGNED_BYTE,
(guint8 *) data + (guint8 *) data +
gst_video_format_get_component_offset (video_format, offsetU, width, height)); 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, glTexSubImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, 0, 0,
GST_ROUND_UP_2 (width) / 2, GST_ROUND_UP_2 (height) / 2, GST_ROUND_UP_2 (width) / 2, GST_ROUND_UP_2 (height) / 2,
GL_LUMINANCE, GL_UNSIGNED_BYTE, GL_LUMINANCE, GL_UNSIGNED_BYTE,
@ -1891,15 +1848,6 @@ gst_gl_display_fill_texture (GstGLDisplay * display)
default: default:
g_assert_not_reached (); 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); 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); glPushAttrib(GL_VIEWPORT_BIT);
glMatrixMode(GL_PROJECTION); glMatrixMode(GL_PROJECTION);
@ -2079,6 +2039,12 @@ gst_gl_display_draw_texture (GstGLDisplay* display)
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
checkFramebufferStatus(); 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) */ /* called by gst_gl_display_glutCreateWindow (in the glut thread) */
GLhandleARB GLhandleARB
gst_gl_display_loadGLSLprogram (gchar* textFProgram) gst_gl_display_loadGLSLprogram (gchar* textFProgram)
@ -2427,10 +2429,10 @@ checkFramebufferStatus(void)
break; break;
case GL_FRAMEBUFFER_UNSUPPORTED_EXT: case GL_FRAMEBUFFER_UNSUPPORTED_EXT:
GST_DEBUG("GL_FRAMEBUFFER_UNSUPPORTED_EXT"); g_print ("GL_FRAMEBUFFER_UNSUPPORTED_EXT\n");
break; break;
default: default:
GST_DEBUG("General FBO error"); g_print ("General FBO error\n");
} }
} }

View file

@ -74,8 +74,6 @@ typedef struct _GstGLDisplayMsg {
//Texture pool elements //Texture pool elements
typedef struct _GstGLDisplayTex { typedef struct _GstGLDisplayTex {
GLuint texture; GLuint texture;
GLuint texture_u;
GLuint texture_v;
} GstGLDisplayTex; } GstGLDisplayTex;
@ -133,9 +131,9 @@ struct _GstGLDisplay {
//filter frame buffer object (GL -> GL) //filter frame buffer object (GL -> GL)
GLuint requestedFBO; GLuint requestedFBO;
GLuint requestedDepthBuffer; GLuint requestedDepthBuffer;
GLuint requestedTextureFBO;
GLuint requestedTextureFBOWidth; GLuint requestedTextureFBOWidth;
GLuint requestedTextureFBOHeight; GLuint requestedTextureFBOHeight;
GLuint usedFBO; GLuint usedFBO;
GLuint usedDepthBuffer; GLuint usedDepthBuffer;
GLuint usedTextureFBO; GLuint usedTextureFBO;
@ -150,38 +148,23 @@ struct _GstGLDisplay {
GLuint inputTexture; GLuint inputTexture;
GLuint rejectedFBO; GLuint rejectedFBO;
GLuint rejectedDepthBuffer; GLuint rejectedDepthBuffer;
GLuint rejectedTextureFBO;
//displayed texture //displayed texture
GLuint displayedTexture; GLuint displayedTexture;
GLuint displayedTextureWidth; GLuint displayedTextureWidth;
GLuint displayedTextureHeight; GLuint displayedTextureHeight;
GLuint requestedTexture; GLuint preparedTexture;
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 currentTexture; GLuint currentTexture;
GLuint currentTexture_u; GLuint currentTexture_u;
GLuint currentTexture_v; GLuint currentTexture_v;
GstVideoFormat currentVideo_format;
GLuint currentTextureWidth; GLuint currentTextureWidth;
GLuint currentTextureHeight; GLuint currentTextureHeight;
GstVideoFormat currentVideo_format;
gpointer currentData;
GLuint textureTrash; GLuint textureTrash;
GLuint textureTrash_u;
GLuint textureTrash_v;
//output frame buffer object (GL -> video) //output frame buffer object (GL -> video)
GLuint videoFBO; 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_setClientDrawCallback (GstGLDisplay* display, CDCB cb);
void gst_gl_display_setVisibleWindow (GstGLDisplay* display, gboolean visible); void gst_gl_display_setVisibleWindow (GstGLDisplay* display, gboolean visible);
void gst_gl_display_resizeWindow (GstGLDisplay* display, gint width, gint height); void gst_gl_display_resizeWindow (GstGLDisplay* display, gint width, gint height);
void gst_gl_display_textureRequested (GstGLDisplay* display, GstVideoFormat format, void gst_gl_display_prepare_texture (GstGLDisplay* display, guint* pTexture);
gint width, gint height, guint* texture, void gst_gl_display_do_upload (GstGLDisplay* display, GstVideoFormat video_format,
guint* texture_u, guint* texture_v); gint video_width, gint video_height, gpointer data,
void gst_gl_display_textureChanged (GstGLDisplay* display, GstVideoFormat video_format, guint gl_width, guint gl_height, guint pTexture);
GLuint texture, GLuint texture_u, GLuint texture_v, void gst_gl_display_clearTexture (GstGLDisplay* display, guint texture);
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_videoChanged (GstGLDisplay* display, GstVideoFormat video_format, void gst_gl_display_videoChanged (GstGLDisplay* display, GstVideoFormat video_format,
gint width, gint height, GLuint recordedTexture, gpointer data); gint width, gint height, GLuint recordedTexture, gpointer data);
gboolean gst_gl_display_postRedisplay (GstGLDisplay* display, GLuint texture, gint width, gint height); gboolean gst_gl_display_postRedisplay (GstGLDisplay* display, GLuint texture, gint width, gint height);
void gst_gl_display_requestFBO (GstGLDisplay* display, 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, void gst_gl_display_useFBO (GstGLDisplay* display, gint textureFBOWidth, gint textureFBOheight,
guint fbo, guint depthbuffer, guint textureFBO, GLCB cb, guint fbo, guint depthbuffer, guint textureFBO, GLCB cb,
guint inputTextureWidth, guint inputTextureHeight, guint inputTexture, 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, guint fbo, guint depthbuffer, guint textureFBO, GLCB2 cb,
gpointer* p1, gpointer* p2); gpointer* p1, gpointer* p2);
void gst_gl_display_rejectFBO (GstGLDisplay* display, guint fbo, 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_initDonwloadFBO (GstGLDisplay* display, gint width, gint height);
void gst_gl_display_initShader (GstGLDisplay* display, gchar* textShader, GLhandleARB* handleShader); void gst_gl_display_initShader (GstGLDisplay* display, gchar* textShader, GLhandleARB* handleShader);
void gst_gl_display_destroyShader (GstGLDisplay* display, GLhandleARB shader); 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 //blocking call, delete the FBO
gst_gl_display_rejectFBO (filter->display, filter->fbo, gst_gl_display_rejectFBO (filter->display, filter->fbo,
filter->depthbuffer, filter->texture); filter->depthbuffer);
g_object_unref (filter->display); g_object_unref (filter->display);
filter->display = NULL; filter->display = NULL;
} }
filter->video_format = GST_VIDEO_FORMAT_UNKNOWN;
filter->width = 0; filter->width = 0;
filter->height = 0; filter->height = 0;
filter->fbo = 0; filter->fbo = 0;
filter->depthbuffer = 0; filter->depthbuffer = 0;
filter->texture = 0;
} }
static gboolean static gboolean
@ -221,14 +219,13 @@ static gboolean
gst_gl_filter_get_unit_size (GstBaseTransform* trans, GstCaps* caps, gst_gl_filter_get_unit_size (GstBaseTransform* trans, GstCaps* caps,
guint* size) guint* size)
{ {
gboolean ret; gboolean ret = FALSE;
GstVideoFormat video_format; gint width = 0;
gint width; gint height = 0;
gint height;
ret = gst_gl_buffer_format_parse_caps (caps, &video_format, &width, &height); ret = gst_gl_buffer_parse_caps (caps, &width, &height);
if (ret) if (ret)
*size = gst_gl_buffer_format_get_size (video_format, width, height); *size = gst_gl_buffer_get_size (width, height);
return TRUE; return TRUE;
} }
@ -251,17 +248,14 @@ gst_gl_filter_prepare_output_buffer (GstBaseTransform* trans,
//blocking call, generate a FBO //blocking call, generate a FBO
gst_gl_display_requestFBO (filter->display, filter->width, filter->height, gst_gl_display_requestFBO (filter->display, filter->width, filter->height,
&filter->fbo, &filter->depthbuffer, &filter->texture); &filter->fbo, &filter->depthbuffer);
if (filter_class->onInitFBO) if (filter_class->onInitFBO)
filter_class->onInitFBO (filter); filter_class->onInitFBO (filter);
} }
gl_outbuf = gst_gl_buffer_new_from_video_format (filter->display, gl_outbuf = gst_gl_buffer_new (filter->display,
filter->video_format, filter->width, filter->height);
filter->width, filter->height,
filter->width, filter->height,
gl_inbuf->width, gl_inbuf->height);
*buf = GST_BUFFER (gl_outbuf); *buf = GST_BUFFER (gl_outbuf);
gst_buffer_set_caps (*buf, caps); gst_buffer_set_caps (*buf, caps);
@ -277,8 +271,7 @@ gst_gl_filter_set_caps (GstBaseTransform* bt, GstCaps* incaps,
gboolean ret = FALSE; gboolean ret = FALSE;
GstGLFilterClass* filter_class = GST_GL_FILTER_GET_CLASS (filter); GstGLFilterClass* filter_class = GST_GL_FILTER_GET_CLASS (filter);
ret = gst_gl_buffer_format_parse_caps (outcaps, &filter->video_format, ret = gst_gl_buffer_parse_caps (outcaps, &filter->width, &filter->height);
&filter->width, &filter->height);
if (filter_class->set_caps) if (filter_class->set_caps)
filter_class->set_caps (filter, incaps, outcaps); filter_class->set_caps (filter, incaps, outcaps);

View file

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

View file

@ -104,9 +104,9 @@ gst_gl_colorscale_base_init (gpointer klass)
} }
static void 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 = (GObjectClass *) klass;
gobject_class->set_property = gst_gl_colorscale_set_property; gobject_class->set_property = gst_gl_colorscale_set_property;
@ -123,7 +123,7 @@ gst_gl_colorscale_class_init (GstGLColorscaleClass * klass)
} }
static void static void
gst_gl_colorscale_init (GstGLColorscale* colorscale, GstGLColorscaleClass * klass) gst_gl_colorscale_init (GstGLColorscale* colorscale, GstGLColorscaleClass* klass)
{ {
gst_gl_colorscale_reset (colorscale); gst_gl_colorscale_reset (colorscale);
} }
@ -370,15 +370,15 @@ gst_gl_colorscale_set_caps (GstBaseTransform* bt, GstCaps* incaps,
{ {
GstGLColorscale* colorscale = GST_GL_COLORSCALE (bt); GstGLColorscale* colorscale = GST_GL_COLORSCALE (bt);
gboolean ret = FALSE; gboolean ret = FALSE;
static gint glcontext_y = 0; static gint y_pos = 0;
GST_DEBUG ("called with %" GST_PTR_FORMAT, incaps); GST_DEBUG ("called with %" GST_PTR_FORMAT, incaps);
ret = gst_video_format_parse_caps (outcaps, &colorscale->outVideo_format, ret = gst_video_format_parse_caps (outcaps, &colorscale->output_video_format,
&colorscale->outWidth, &colorscale->outHeight); &colorscale->output_video_width, &colorscale->output_video_height);
ret |= gst_video_format_parse_caps (incaps, &colorscale->inVideo_format, ret |= gst_video_format_parse_caps (incaps, &colorscale->input_video_format,
&colorscale->inWidth, &colorscale->inHeight); &colorscale->input_video_width, &colorscale->input_video_height);
if (!ret) if (!ret)
{ {
@ -390,12 +390,13 @@ gst_gl_colorscale_set_caps (GstBaseTransform* bt, GstCaps* incaps,
//init unvisible opengl context //init unvisible opengl context
gst_gl_display_initGLContext (colorscale->display, gst_gl_display_initGLContext (colorscale->display,
50, glcontext_y++ * (colorscale->inHeight+50) + 50, 50, y_pos++ * (colorscale->output_video_height+50) + 50,
colorscale->inWidth, colorscale->inHeight, colorscale->output_video_width, colorscale->output_video_height,
colorscale->inWidth, colorscale->inHeight, 0, FALSE); colorscale->output_video_width, colorscale->output_video_height, 0, FALSE);
//blocking call //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; return ret;
} }
@ -412,11 +413,9 @@ gst_gl_colorscale_get_unit_size (GstBaseTransform* trans, GstCaps* caps,
structure = gst_caps_get_structure (caps, 0); structure = gst_caps_get_structure (caps, 0);
if (gst_structure_has_name (structure, "video/x-raw-gl")) if (gst_structure_has_name (structure, "video/x-raw-gl"))
{ {
GstVideoFormat video_format; ret = gst_gl_buffer_parse_caps (caps, &width, &height);
ret = gst_gl_buffer_format_parse_caps (caps, &video_format, &width, &height);
if (ret) if (ret)
*size = gst_gl_buffer_format_get_size (video_format, width, height); *size = gst_gl_buffer_get_size (width, height);
} }
else else
{ {
@ -437,26 +436,26 @@ gst_gl_colorscale_transform (GstBaseTransform* trans, GstBuffer* inbuf,
GstGLColorscale* colorscale = GST_GL_COLORSCALE (trans); GstGLColorscale* colorscale = GST_GL_COLORSCALE (trans);
//blocking call //blocking call
GstGLBuffer* gl_tembuf = gst_gl_buffer_new_from_video_format (colorscale->display, GstGLBuffer* gl_temp_buffer = gst_gl_buffer_new (colorscale->display,
colorscale->inVideo_format, colorscale->output_video_width, colorscale->output_video_height);
colorscale->outWidth, colorscale->outHeight,
colorscale->inWidth, colorscale->inHeight,
colorscale->inWidth, colorscale->inHeight);
GST_DEBUG ("input size %p size %d", GST_DEBUG ("input size %p size %d",
GST_BUFFER_DATA (inbuf), GST_BUFFER_SIZE (inbuf)); GST_BUFFER_DATA (inbuf), GST_BUFFER_SIZE (inbuf));
//blocking call //blocking call
gst_gl_display_textureChanged(colorscale->display, colorscale->inVideo_format, gst_gl_display_do_upload (colorscale->display, colorscale->input_video_format,
gl_tembuf->texture, gl_tembuf->texture_u, gl_tembuf->texture_v, colorscale->input_video_width, colorscale->input_video_height, GST_BUFFER_DATA (inbuf),
gl_tembuf->width, gl_tembuf->height, GST_BUFFER_DATA (inbuf), &gl_tembuf->textureGL); gl_temp_buffer->width, gl_temp_buffer->height, gl_temp_buffer->texture);
GST_DEBUG ("output size %p size %d", GST_DEBUG ("output size %p size %d",
GST_BUFFER_DATA (outbuf), GST_BUFFER_SIZE (outbuf)); GST_BUFFER_DATA (outbuf), GST_BUFFER_SIZE (outbuf));
//blocking call //blocking call
gst_gl_display_videoChanged(colorscale->display, colorscale->outVideo_format, gst_gl_display_videoChanged(colorscale->display, colorscale->output_video_format,
gl_tembuf->width, gl_tembuf->height, gl_tembuf->textureGL, GST_BUFFER_DATA (outbuf)); 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; return GST_FLOW_OK;
} }

View file

@ -48,12 +48,14 @@ struct _GstGLColorscale
GstPad *sinkpad; GstPad *sinkpad;
GstGLDisplay *display; GstGLDisplay *display;
GstVideoFormat inVideo_format;
gint inWidth; GstVideoFormat input_video_format;
gint inHeight; gint input_video_width;
GstVideoFormat outVideo_format; gint input_video_height;
gint outWidth;
gint outHeight; GstVideoFormat output_video_format;
gint output_video_width;
gint output_video_height;
}; };
struct _GstGLColorscaleClass struct _GstGLColorscaleClass

View file

@ -270,11 +270,9 @@ gst_gl_download_get_unit_size (GstBaseTransform* trans, GstCaps* caps,
structure = gst_caps_get_structure (caps, 0); structure = gst_caps_get_structure (caps, 0);
if (gst_structure_has_name (structure, "video/x-raw-gl")) if (gst_structure_has_name (structure, "video/x-raw-gl"))
{ {
GstVideoFormat video_format; ret = gst_gl_buffer_parse_caps (caps, &width, &height);
ret = gst_gl_buffer_format_parse_caps (caps, &video_format, &width, &height);
if (ret) if (ret)
*size = gst_gl_buffer_format_get_size (video_format, width, height); *size = gst_gl_buffer_get_size (width, height);
} }
else else
{ {
@ -309,7 +307,7 @@ gst_gl_download_transform (GstBaseTransform* trans, GstBuffer* inbuf,
//blocking call //blocking call
gst_gl_display_videoChanged(download->display, download->video_format, 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; return GST_FLOW_OK;
} }

View file

@ -56,6 +56,7 @@ static gboolean gst_gl_filter_app_set_caps (GstGLFilter* filter,
static void gst_gl_filter_app_setClientCallbacks (GstGLFilter* filter); static void gst_gl_filter_app_setClientCallbacks (GstGLFilter* filter);
static gboolean gst_gl_filter_app_filter (GstGLFilter* filter, static gboolean gst_gl_filter_app_filter (GstGLFilter* filter,
GstGLBuffer* inbuf, GstGLBuffer* outbuf); GstGLBuffer* inbuf, GstGLBuffer* outbuf);
static void gst_gl_filter_app_callback (guint width, guint height, guint texture, GLhandleARB shader);
static void static void
@ -164,14 +165,39 @@ gst_gl_filter_app_filter (GstGLFilter* filter, GstGLBuffer* inbuf,
{ {
//GstGLFilterApp* app_filter = GST_GL_FILTER_APP(filter); //GstGLFilterApp* app_filter = GST_GL_FILTER_APP(filter);
outbuf->width = inbuf->width; //blocking call, use a FBO
outbuf->height = inbuf->height; gst_gl_display_useFBO (filter->display, filter->width, filter->height,
outbuf->texture = inbuf->texture; filter->fbo, filter->depthbuffer, outbuf->texture, gst_gl_filter_app_callback,
outbuf->texture_u = inbuf->texture_u; inbuf->width, inbuf->height, inbuf->texture, 0);
outbuf->texture_v = inbuf->texture_v;
outbuf->widthGL = inbuf->widthGL;
outbuf->heightGL = inbuf->heightGL;
outbuf->textureGL = inbuf->textureGL;
return TRUE; 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 ();
}

View file

@ -114,17 +114,10 @@ gst_gl_filter_cube_filter (GstGLFilter* filter, GstGLBuffer* inbuf,
{ {
//GstGLFilterCube* cube_filter = GST_GL_FILTER_CUBE(filter); //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, gst_gl_display_useFBO (filter->display, filter->width, filter->height,
filter->fbo, filter->depthbuffer, filter->texture, gst_gl_filter_cube_callback, filter->fbo, filter->depthbuffer, outbuf->texture, gst_gl_filter_cube_callback,
inbuf->width, inbuf->height, inbuf->textureGL, 0); inbuf->width, inbuf->height, inbuf->texture, 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;
return TRUE; return TRUE;
} }

View file

@ -170,15 +170,8 @@ gst_gl_filter_edge_filter (GstGLFilter* filter, GstGLBuffer* inbuf,
//blocking call, generate a FBO //blocking call, generate a FBO
gst_gl_display_useFBO (filter->display, filter->width, filter->height, gst_gl_display_useFBO (filter->display, filter->width, filter->height,
filter->fbo, filter->depthbuffer, filter->texture, gst_gl_filter_edge_callback, filter->fbo, filter->depthbuffer, outbuf->texture, gst_gl_filter_edge_callback,
inbuf->width, inbuf->height, inbuf->textureGL, edge_filter->handleShader); inbuf->width, inbuf->height, inbuf->texture, 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;
return TRUE; return TRUE;
} }
@ -214,7 +207,6 @@ gst_gl_filter_edge_callback (guint width, guint height, guint texture, GLhandleA
glTexCoord2i (width, height); glTexCoord2i (width, height);
glVertex2f (1.0f, 1.0f); glVertex2f (1.0f, 1.0f);
glTexCoord2i (0, height); glTexCoord2i (0, height);
glVertex2f (-1.0f, 1.0f); glVertex2f (-1.0f, 1.0f);
glEnd (); glEnd ();
} }

View file

@ -444,15 +444,13 @@ gst_glimage_sink_render (GstBaseSink* bsink, GstBuffer* buf)
} }
//blocking call //blocking call
gl_buffer = gst_gl_buffer_new_from_video_format (glimage_sink->display, gl_buffer = gst_gl_buffer_new (glimage_sink->display,
glimage_sink->format, glimage_sink->width, glimage_sink->height,
glimage_sink->width, glimage_sink->height,
glimage_sink->width, glimage_sink->height); glimage_sink->width, glimage_sink->height);
//blocking call //blocking call
gst_gl_display_textureChanged(glimage_sink->display, glimage_sink->format, gst_gl_display_do_upload(glimage_sink->display, glimage_sink->format,
gl_buffer->texture, gl_buffer->texture_u, gl_buffer->texture_v, glimage_sink->width, glimage_sink->height, GST_BUFFER_DATA (buf),
gl_buffer->width, gl_buffer->height, GST_BUFFER_DATA (buf), &gl_buffer->textureGL); gl_buffer->width, gl_buffer->height, gl_buffer->texture);
//gl_buffer is created in this block, so the gl buffer is already referenced //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 //redisplay opengl scene
isAlive = gst_gl_display_postRedisplay (glimage_sink->display, 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) if (isAlive)
return GST_FLOW_OK; return GST_FLOW_OK;

View file

@ -369,7 +369,7 @@ gst_gl_test_src_setcaps (GstBaseSrc* bsrc, GstCaps* caps)
gltestsrc->width, gltestsrc->height, 0, FALSE); gltestsrc->width, gltestsrc->height, 0, FALSE);
gst_gl_display_requestFBO (gltestsrc->display, gltestsrc->width, gltestsrc->height, gst_gl_display_requestFBO (gltestsrc->display, gltestsrc->width, gltestsrc->height,
&gltestsrc->fbo, &gltestsrc->depthbuffer, &gltestsrc->texture); &gltestsrc->fbo, &gltestsrc->depthbuffer);
} }
return res; 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", GST_LOG_OBJECT (src, "creating buffer %dx%d image for frame %d",
src->width, src->height, (gint) src->n_frames); src->width, src->height, (gint) src->n_frames);
outbuf = gst_gl_buffer_new_from_video_format (src->display, outbuf = gst_gl_buffer_new (src->display,
GST_VIDEO_FORMAT_UNKNOWN,
src->width, src->height,
src->width, src->height,
src->width, src->height); src->width, src->height);
gst_buffer_set_caps (GST_BUFFER (outbuf), 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 //blocking call, generate a FBO
gst_gl_display_useFBO2 (src->display, src->width, src->height, 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); (gpointer*)src, (gpointer*)outbuf);
outbuf->textureGL = src->texture;
GST_BUFFER_TIMESTAMP (GST_BUFFER (outbuf)) = GST_BUFFER_TIMESTAMP (GST_BUFFER (outbuf)) =
src->timestamp_offset + src->running_time; src->timestamp_offset + src->running_time;
@ -631,7 +627,7 @@ gst_gl_test_src_stop (GstBaseSrc* basesrc)
{ {
//blocking call, delete the FBO //blocking call, delete the FBO
gst_gl_display_rejectFBO (src->display, src->fbo, gst_gl_display_rejectFBO (src->display, src->fbo,
src->depthbuffer, src->texture); src->depthbuffer);
g_object_unref (src->display); g_object_unref (src->display);
src->display = NULL; src->display = NULL;
} }

View file

@ -98,7 +98,6 @@ struct _GstGLTestSrc {
guint fbo; guint fbo;
guint depthbuffer; guint depthbuffer;
guint texture;
/* private */ /* private */
GstGLDisplay *display; GstGLDisplay *display;

View file

@ -377,54 +377,53 @@ gst_gl_upload_set_caps (GstBaseTransform* bt, GstCaps* incaps,
GstGLUpload* upload = GST_GL_UPLOAD (bt); GstGLUpload* upload = GST_GL_UPLOAD (bt);
gboolean ret = FALSE; gboolean ret = FALSE;
GstVideoFormat video_format = GST_VIDEO_FORMAT_UNKNOWN; 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); GST_DEBUG ("called with %" GST_PTR_FORMAT, incaps);
ret = gst_video_format_parse_caps (outcaps, &video_format, 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, ret |= gst_video_format_parse_caps (incaps, &upload->video_format,
&upload->inWidth, &upload->inHeight); &upload->video_width, &upload->video_height);
if (!ret) if (!ret)
{ {
GST_DEBUG ("bad caps"); GST_DEBUG ("caps connot be parsed");
return FALSE; return FALSE;
} }
//we have video and gl size, we can now init OpenGL stuffs
upload->display = gst_gl_display_new (); upload->display = gst_gl_display_new ();
//init unvisible opengl context //init unvisible opengl context
gst_gl_display_initGLContext (upload->display, gst_gl_display_initGLContext (upload->display,
50, glcontext_y++ * (upload->inHeight+50) + 50, 50, y_pos++ * (upload->gl_height+50) + 50,
upload->inWidth, upload->inHeight, upload->gl_width, upload->gl_height,
upload->inWidth, upload->inHeight, 0, FALSE); upload->gl_width, upload->gl_height, 0, FALSE);
return ret; return ret;
} }
static gboolean static gboolean
gst_gl_upload_get_unit_size (GstBaseTransform* trans, GstCaps* caps, gst_gl_upload_get_unit_size (GstBaseTransform* trans, GstCaps* caps,
guint* size) guint* size)
{ {
gboolean ret; gboolean ret = FALSE;
GstStructure *structure; GstStructure* structure = NULL;
gint width; gint width = 0;
gint height; gint height = 0;
structure = gst_caps_get_structure (caps, 0); structure = gst_caps_get_structure (caps, 0);
if (gst_structure_has_name (structure, "video/x-raw-gl")) if (gst_structure_has_name (structure, "video/x-raw-gl"))
{ {
GstVideoFormat video_format; ret = gst_gl_buffer_parse_caps (caps, &width, &height);
ret = gst_gl_buffer_format_parse_caps (caps, &video_format, &width, &height);
if (ret) if (ret)
*size = gst_gl_buffer_format_get_size (video_format, width, height); *size = gst_gl_buffer_get_size (width, height);
} }
else else
{ {
GstVideoFormat video_format; GstVideoFormat video_format = GST_VIDEO_FORMAT_UNKNOWN;
ret = gst_video_format_parse_caps (caps, &video_format, &width, &height); ret = gst_video_format_parse_caps (caps, &video_format, &width, &height);
if (ret) if (ret)
@ -438,17 +437,12 @@ static GstFlowReturn
gst_gl_upload_prepare_output_buffer (GstBaseTransform* trans, gst_gl_upload_prepare_output_buffer (GstBaseTransform* trans,
GstBuffer* input, gint size, GstCaps* caps, GstBuffer** buf) GstBuffer* input, gint size, GstCaps* caps, GstBuffer** buf)
{ {
GstGLUpload* upload; GstGLUpload* upload = GST_GL_UPLOAD (trans);
GstGLBuffer* gl_outbuf;
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); *buf = GST_BUFFER (gl_outbuf);
gst_buffer_set_caps (*buf, caps); gst_buffer_set_caps (*buf, caps);
@ -460,18 +454,19 @@ static GstFlowReturn
gst_gl_upload_transform (GstBaseTransform* trans, GstBuffer* inbuf, gst_gl_upload_transform (GstBaseTransform* trans, GstBuffer* inbuf,
GstBuffer* outbuf) GstBuffer* outbuf)
{ {
GstGLUpload* upload; GstGLUpload* upload = GST_GL_UPLOAD (trans);
GstGLBuffer* gl_outbuf = GST_GL_BUFFER (outbuf); GstGLBuffer* gl_outbuf = GST_GL_BUFFER (outbuf);
upload = GST_GL_UPLOAD (trans); GST_DEBUG ("Upload %p size %d",
GST_DEBUG ("making graphic %p size %d",
GST_BUFFER_DATA (inbuf), GST_BUFFER_SIZE (inbuf)); GST_BUFFER_DATA (inbuf), GST_BUFFER_SIZE (inbuf));
//blocking call //blocking call.
gst_gl_display_textureChanged(upload->display, upload->video_format, //Depending on the colorspace, video is upload into several textures.
gl_outbuf->texture, gl_outbuf->texture_u, gl_outbuf->texture_v, //However, there is only one output texture. The one attached
gl_outbuf->width, gl_outbuf->height, GST_BUFFER_DATA (inbuf), &gl_outbuf->textureGL); //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; return GST_FLOW_OK;
} }

View file

@ -48,11 +48,12 @@ struct _GstGLUpload
GstPad *sinkpad; GstPad *sinkpad;
GstGLDisplay *display; GstGLDisplay *display;
GstVideoFormat video_format; GstVideoFormat video_format;
gint inWidth; gint video_width;
gint inHeight; gint video_height;
gint outWidth; gint gl_width;
gint outHeight; gint gl_height;
}; };
struct _GstGLUploadClass struct _GstGLUploadClass