mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-28 04:31:06 +00:00
[046/906] * sys/glsink/BUGS: * sys/glsink/Makefile.am: * sys/glsink/gstglbuffer.c: * sys/glsink/gstglbuffer.h: * sys/glsink/gstglconvert.c: * sys/glsink/gstgldisplay.c: * sys/glsink/gstglfilter.c: * sys/glsink/gstglfilter.h: * sys/glsink/gstglfilterexample.c: * sys/glsink/gstgltestsrc.c: * sys/glsink/gstglupload.c: * sys/glsink/gstopengl.c: Remove code that handles non-texture buffers. Add a GstGLBufferFormat type that corresponds to how to use the texture, not the original video format. Convert gstflfilter.c into a base class, add glfilterexample and glconvert elements. * sys/glsink/color_matrix.c: Minor ramblings about color conversion matrices.
This commit is contained in:
parent
27c5fb1f81
commit
8abaf6f1dd
13 changed files with 1059 additions and 310 deletions
|
@ -18,22 +18,14 @@ gst_gl_buffer_finalize (GstGLBuffer * buffer)
|
||||||
{
|
{
|
||||||
gst_gl_display_lock (buffer->display);
|
gst_gl_display_lock (buffer->display);
|
||||||
|
|
||||||
switch (buffer->type) {
|
glDeleteTextures (1, &buffer->texture);
|
||||||
case GST_GL_BUFFER_XIMAGE:
|
if (buffer->texture_u) {
|
||||||
GST_DEBUG ("freeing pixmap %ld", buffer->pixmap);
|
glDeleteTextures (1, &buffer->texture_u);
|
||||||
XFreeGC (buffer->display->display, buffer->gc);
|
|
||||||
XFreePixmap (buffer->display->display, buffer->pixmap);
|
|
||||||
break;
|
|
||||||
case GST_GL_BUFFER_RBO:
|
|
||||||
glDeleteRenderbuffersEXT (1, &buffer->rbo);
|
|
||||||
break;
|
|
||||||
case GST_GL_BUFFER_TEXTURE:
|
|
||||||
glDeleteTextures (1, &buffer->texture);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
g_assert_not_reached ();
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
if (buffer->texture_v) {
|
||||||
|
glDeleteTextures (1, &buffer->texture_v);
|
||||||
|
}
|
||||||
|
|
||||||
gst_gl_display_unlock (buffer->display);
|
gst_gl_display_unlock (buffer->display);
|
||||||
g_object_unref (buffer->display);
|
g_object_unref (buffer->display);
|
||||||
|
|
||||||
|
@ -85,215 +77,194 @@ gst_gl_buffer_get_type (void)
|
||||||
|
|
||||||
|
|
||||||
GstGLBuffer *
|
GstGLBuffer *
|
||||||
gst_gl_buffer_new (GstGLDisplay * display, GstVideoFormat format,
|
gst_gl_buffer_new (GstGLDisplay * display, GstGLBufferFormat format,
|
||||||
int width, int height)
|
int width, int height)
|
||||||
{
|
{
|
||||||
GstGLBuffer *buffer;
|
GstGLBuffer *buffer;
|
||||||
XGCValues values = { 0 };
|
|
||||||
|
|
||||||
g_return_val_if_fail (format == GST_VIDEO_FORMAT_RGBx, NULL);
|
|
||||||
g_return_val_if_fail (width > 0, NULL);
|
g_return_val_if_fail (width > 0, NULL);
|
||||||
g_return_val_if_fail (height > 0, NULL);
|
g_return_val_if_fail (height > 0, NULL);
|
||||||
|
|
||||||
buffer = (GstGLBuffer *) gst_mini_object_new (GST_TYPE_GL_BUFFER);
|
buffer = (GstGLBuffer *) gst_mini_object_new (GST_TYPE_GL_BUFFER);
|
||||||
|
|
||||||
buffer->display = g_object_ref (display);
|
buffer->display = g_object_ref (display);
|
||||||
buffer->type = GST_GL_BUFFER_TEXTURE;
|
|
||||||
|
|
||||||
buffer->width = width;
|
buffer->width = width;
|
||||||
buffer->height = height;
|
buffer->height = height;
|
||||||
|
|
||||||
switch (buffer->type) {
|
gst_gl_display_lock (buffer->display);
|
||||||
case GST_GL_BUFFER_XIMAGE:
|
glGenTextures (1, &buffer->texture);
|
||||||
{
|
glBindTexture (GL_TEXTURE_RECTANGLE_ARB, buffer->texture);
|
||||||
buffer->pixmap = XCreatePixmap (display->display,
|
switch (format) {
|
||||||
DefaultRootWindow (display->display), width, height, 32);
|
case GST_GL_BUFFER_FORMAT_RGBA:
|
||||||
XSync (display->display, False);
|
glTexImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA,
|
||||||
|
buffer->width, buffer->height, 0, GL_RGBA, GL_FLOAT, NULL);
|
||||||
buffer->gc = XCreateGC (display->display, buffer->pixmap, 0, &values);
|
|
||||||
|
|
||||||
GST_DEBUG ("new pixmap %dx%d xid %ld", width, height, buffer->pixmap);
|
|
||||||
break;
|
break;
|
||||||
}
|
case GST_GL_BUFFER_FORMAT_RGB:
|
||||||
case GST_GL_BUFFER_RBO:
|
glTexImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGB,
|
||||||
{
|
buffer->width, buffer->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
|
||||||
GLuint fbo;
|
|
||||||
|
|
||||||
gst_gl_display_lock (buffer->display);
|
|
||||||
|
|
||||||
glGenFramebuffersEXT (1, &fbo);
|
|
||||||
glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, fbo);
|
|
||||||
|
|
||||||
glGenRenderbuffersEXT (1, &buffer->rbo);
|
|
||||||
glBindRenderbufferEXT (GL_RENDERBUFFER_EXT, buffer->rbo);
|
|
||||||
|
|
||||||
glFramebufferRenderbufferEXT (GL_FRAMEBUFFER_EXT,
|
|
||||||
GL_COLOR_ATTACHMENT1_EXT, GL_RENDERBUFFER_EXT, buffer->rbo);
|
|
||||||
glRenderbufferStorageEXT (GL_RENDERBUFFER_EXT, GL_RGB,
|
|
||||||
buffer->width, buffer->height);
|
|
||||||
|
|
||||||
glDrawBuffer (GL_COLOR_ATTACHMENT1_EXT);
|
|
||||||
glReadBuffer (GL_COLOR_ATTACHMENT1_EXT);
|
|
||||||
g_assert (glCheckFramebufferStatusEXT (GL_FRAMEBUFFER_EXT) ==
|
|
||||||
GL_FRAMEBUFFER_COMPLETE_EXT);
|
|
||||||
|
|
||||||
glDeleteFramebuffersEXT (1, &fbo);
|
|
||||||
|
|
||||||
gst_gl_display_unlock (buffer->display);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case GST_GL_BUFFER_TEXTURE:
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
g_assert_not_reached ();
|
g_warning ("GL buffer format not handled");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gst_gl_display_unlock (buffer->display);
|
||||||
|
|
||||||
return buffer;
|
return buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
GstGLBuffer *
|
||||||
gst_gl_buffer_upload (GstGLBuffer * buffer, void *data)
|
gst_gl_buffer_new_from_data (GstGLDisplay * display, GstVideoFormat format,
|
||||||
|
int width, int height, void *data)
|
||||||
{
|
{
|
||||||
Display *display = buffer->display->display;
|
GstGLBuffer *buffer;
|
||||||
|
int comp;
|
||||||
|
|
||||||
GST_DEBUG ("uploading %p %dx%d", data, buffer->width, buffer->height);
|
g_return_val_if_fail (width > 0, NULL);
|
||||||
|
g_return_val_if_fail (height > 0, NULL);
|
||||||
|
g_return_val_if_fail (data != NULL, NULL);
|
||||||
|
|
||||||
|
GST_DEBUG ("uploading %p %dx%d", data, width, height);
|
||||||
|
|
||||||
|
buffer = (GstGLBuffer *) gst_mini_object_new (GST_TYPE_GL_BUFFER);
|
||||||
|
buffer->display = g_object_ref (display);
|
||||||
|
buffer->width = width;
|
||||||
|
buffer->height = height;
|
||||||
|
|
||||||
gst_gl_display_lock (buffer->display);
|
gst_gl_display_lock (buffer->display);
|
||||||
|
glGenTextures (1, &buffer->texture);
|
||||||
|
glBindTexture (GL_TEXTURE_RECTANGLE_ARB, buffer->texture);
|
||||||
|
|
||||||
switch (buffer->type) {
|
switch (format) {
|
||||||
case GST_GL_BUFFER_XIMAGE:
|
case GST_VIDEO_FORMAT_RGBx:
|
||||||
{
|
buffer->format = GST_GL_BUFFER_FORMAT_RGB;
|
||||||
XImage *image;
|
glTexImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA,
|
||||||
Visual *visual;
|
buffer->width, buffer->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
|
||||||
int depth;
|
glTexSubImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, 0, 0, width, height,
|
||||||
int bpp;
|
GL_RGBA, GL_UNSIGNED_BYTE, data);
|
||||||
|
|
||||||
visual = DefaultVisual (display, 0);
|
|
||||||
depth = 32;
|
|
||||||
bpp = 32;
|
|
||||||
|
|
||||||
image = XCreateImage (display, visual, depth, ZPixmap, 0, NULL,
|
|
||||||
buffer->width, buffer->height, bpp, 0);
|
|
||||||
GST_DEBUG ("image %p", image);
|
|
||||||
image->data = data;
|
|
||||||
|
|
||||||
XPutImage (display, buffer->pixmap, buffer->gc,
|
|
||||||
image, 0, 0, 0, 0, buffer->width, buffer->height);
|
|
||||||
|
|
||||||
XDestroyImage (image);
|
|
||||||
break;
|
break;
|
||||||
}
|
case GST_VIDEO_FORMAT_BGRx:
|
||||||
case GST_GL_BUFFER_RBO:
|
buffer->format = GST_GL_BUFFER_FORMAT_RGB;
|
||||||
{
|
glTexImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA,
|
||||||
unsigned int fbo;
|
buffer->width, buffer->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
|
||||||
|
glTexSubImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, 0, 0, width, height,
|
||||||
g_assert (glIsRenderbufferEXT (buffer->rbo));
|
GL_BGRA, GL_UNSIGNED_BYTE, data);
|
||||||
|
|
||||||
glGenFramebuffersEXT (1, &fbo);
|
|
||||||
glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, fbo);
|
|
||||||
|
|
||||||
glFramebufferRenderbufferEXT (GL_FRAMEBUFFER_EXT,
|
|
||||||
GL_COLOR_ATTACHMENT1_EXT, GL_RENDERBUFFER_EXT, buffer->rbo);
|
|
||||||
|
|
||||||
glDrawBuffer (GL_COLOR_ATTACHMENT1_EXT);
|
|
||||||
glReadBuffer (GL_COLOR_ATTACHMENT1_EXT);
|
|
||||||
|
|
||||||
g_assert (glCheckFramebufferStatusEXT (GL_FRAMEBUFFER_EXT) ==
|
|
||||||
GL_FRAMEBUFFER_COMPLETE_EXT);
|
|
||||||
|
|
||||||
gst_gl_display_check_error (buffer->display, __LINE__);
|
|
||||||
glWindowPos2iARB (0, 0);
|
|
||||||
glDrawPixels (buffer->width, buffer->height, GL_RGB,
|
|
||||||
GL_UNSIGNED_BYTE, data);
|
|
||||||
|
|
||||||
glDeleteFramebuffersEXT (1, &fbo);
|
|
||||||
|
|
||||||
g_assert (glIsRenderbufferEXT (buffer->rbo));
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
case GST_VIDEO_FORMAT_xRGB:
|
||||||
case GST_GL_BUFFER_TEXTURE:
|
buffer->format = GST_GL_BUFFER_FORMAT_RGB;
|
||||||
buffer->texture =
|
glTexImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA,
|
||||||
gst_gl_display_upload_texture_rectangle (buffer->display,
|
buffer->width, buffer->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
|
||||||
GST_VIDEO_FORMAT_RGBx, data, buffer->width, buffer->height);
|
glTexSubImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, 0, 0, width, height,
|
||||||
|
GL_BGRA, GL_UNSIGNED_INT_8_8_8_8, data);
|
||||||
|
break;
|
||||||
|
case GST_VIDEO_FORMAT_xBGR:
|
||||||
|
buffer->format = GST_GL_BUFFER_FORMAT_RGB;
|
||||||
|
glTexImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA,
|
||||||
|
buffer->width, buffer->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
|
||||||
|
glTexSubImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, 0, 0, width, height,
|
||||||
|
GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, data);
|
||||||
|
break;
|
||||||
|
case GST_VIDEO_FORMAT_YUY2:
|
||||||
|
buffer->format = GST_GL_BUFFER_FORMAT_YUYV;
|
||||||
|
glTexImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, GL_YCBCR_MESA, width, height,
|
||||||
|
0, GL_YCBCR_MESA, GL_UNSIGNED_SHORT_8_8_REV_MESA, NULL);
|
||||||
|
glTexSubImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, 0, 0, width, height,
|
||||||
|
GL_YCBCR_MESA, GL_UNSIGNED_SHORT_8_8_REV_MESA, data);
|
||||||
|
break;
|
||||||
|
case GST_VIDEO_FORMAT_UYVY:
|
||||||
|
buffer->format = GST_GL_BUFFER_FORMAT_YUYV;
|
||||||
|
glTexImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, GL_YCBCR_MESA, width, height,
|
||||||
|
0, GL_YCBCR_MESA, GL_UNSIGNED_SHORT_8_8_REV_MESA, NULL);
|
||||||
|
glTexSubImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, 0, 0, width, height,
|
||||||
|
GL_YCBCR_MESA, GL_UNSIGNED_SHORT_8_8_MESA, data);
|
||||||
|
break;
|
||||||
|
case GST_VIDEO_FORMAT_AYUV:
|
||||||
|
buffer->format = GST_GL_BUFFER_FORMAT_RGB;
|
||||||
|
buffer->is_yuv = TRUE;
|
||||||
|
glTexImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA,
|
||||||
|
buffer->width, buffer->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
|
||||||
|
glTexSubImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, 0, 0, width, height,
|
||||||
|
GL_BGRA, GL_UNSIGNED_INT_8_8_8_8, data);
|
||||||
|
break;
|
||||||
|
case GST_VIDEO_FORMAT_I420:
|
||||||
|
case GST_VIDEO_FORMAT_YV12:
|
||||||
|
buffer->format = GST_GL_BUFFER_FORMAT_PLANAR420;
|
||||||
|
buffer->is_yuv = TRUE;
|
||||||
|
glTexImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, GL_LUMINANCE,
|
||||||
|
buffer->width, buffer->height,
|
||||||
|
0, GL_LUMINANCE, GL_UNSIGNED_BYTE, NULL);
|
||||||
|
glTexSubImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, 0, 0, width, height,
|
||||||
|
GL_LUMINANCE, GL_UNSIGNED_BYTE, data);
|
||||||
|
|
||||||
|
glGenTextures (1, &buffer->texture_u);
|
||||||
|
glBindTexture (GL_TEXTURE_RECTANGLE_ARB, buffer->texture_u);
|
||||||
|
glTexImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, GL_LUMINANCE,
|
||||||
|
GST_ROUND_UP_2 (buffer->width) / 2,
|
||||||
|
GST_ROUND_UP_2 (buffer->height) / 2,
|
||||||
|
0, GL_LUMINANCE, GL_UNSIGNED_BYTE, NULL);
|
||||||
|
comp = (format == GST_VIDEO_FORMAT_I420) ? 1 : 2;
|
||||||
|
glTexSubImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, 0, 0,
|
||||||
|
GST_ROUND_UP_2 (buffer->width) / 2,
|
||||||
|
GST_ROUND_UP_2 (buffer->height) / 2,
|
||||||
|
GL_LUMINANCE, GL_UNSIGNED_BYTE,
|
||||||
|
(guint8 *) data +
|
||||||
|
gst_video_format_get_component_offset (format, comp, width, height));
|
||||||
|
|
||||||
|
glGenTextures (1, &buffer->texture_v);
|
||||||
|
glBindTexture (GL_TEXTURE_RECTANGLE_ARB, buffer->texture_v);
|
||||||
|
glTexImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, GL_LUMINANCE,
|
||||||
|
GST_ROUND_UP_2 (buffer->width) / 2,
|
||||||
|
GST_ROUND_UP_2 (buffer->height) / 2,
|
||||||
|
0, GL_LUMINANCE, GL_UNSIGNED_BYTE, NULL);
|
||||||
|
comp = (format == GST_VIDEO_FORMAT_I420) ? 2 : 1;
|
||||||
|
glTexSubImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, 0, 0,
|
||||||
|
GST_ROUND_UP_2 (buffer->width) / 2,
|
||||||
|
GST_ROUND_UP_2 (buffer->height) / 2,
|
||||||
|
GL_LUMINANCE, GL_UNSIGNED_BYTE,
|
||||||
|
(guint8 *) data +
|
||||||
|
gst_video_format_get_component_offset (format, comp, width, height));
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
g_assert_not_reached ();
|
g_assert_not_reached ();
|
||||||
}
|
}
|
||||||
|
|
||||||
gst_gl_display_unlock (buffer->display);
|
gst_gl_display_unlock (buffer->display);
|
||||||
|
|
||||||
|
return buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
gst_gl_buffer_download (GstGLBuffer * buffer, void *data)
|
gst_gl_buffer_download (GstGLBuffer * buffer, void *data)
|
||||||
{
|
{
|
||||||
gst_gl_display_lock (buffer->display);
|
GLuint fbo;
|
||||||
|
|
||||||
GST_DEBUG ("downloading");
|
GST_DEBUG ("downloading");
|
||||||
|
|
||||||
switch (buffer->type) {
|
gst_gl_display_lock (buffer->display);
|
||||||
case GST_GL_BUFFER_XIMAGE:
|
|
||||||
{
|
|
||||||
XImage *image;
|
|
||||||
|
|
||||||
image = XGetImage (buffer->display->display, buffer->pixmap,
|
glGenFramebuffersEXT (1, &fbo);
|
||||||
0, 0, buffer->width, buffer->height, 0xffffffff, ZPixmap);
|
glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, fbo);
|
||||||
|
|
||||||
memcpy (data, image->data, buffer->width * buffer->height * 4);
|
glFramebufferTexture2DEXT (GL_FRAMEBUFFER_EXT,
|
||||||
|
GL_COLOR_ATTACHMENT1_EXT, GL_TEXTURE_RECTANGLE_ARB, buffer->texture, 0);
|
||||||
|
|
||||||
XDestroyImage (image);
|
glDrawBuffer (GL_COLOR_ATTACHMENT1_EXT);
|
||||||
break;
|
glReadBuffer (GL_COLOR_ATTACHMENT1_EXT);
|
||||||
}
|
|
||||||
case GST_GL_BUFFER_RBO:
|
|
||||||
{
|
|
||||||
unsigned int fbo;
|
|
||||||
|
|
||||||
glGenFramebuffersEXT (1, &fbo);
|
g_assert (glCheckFramebufferStatusEXT (GL_FRAMEBUFFER_EXT) ==
|
||||||
glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, fbo);
|
GL_FRAMEBUFFER_COMPLETE_EXT);
|
||||||
|
|
||||||
glFramebufferRenderbufferEXT (GL_FRAMEBUFFER_EXT,
|
/* needs a reset function */
|
||||||
GL_COLOR_ATTACHMENT1_EXT, GL_RENDERBUFFER_EXT, buffer->rbo);
|
glMatrixMode (GL_COLOR);
|
||||||
|
glLoadIdentity ();
|
||||||
|
glPixelTransferf (GL_POST_COLOR_MATRIX_RED_BIAS, 0);
|
||||||
|
glPixelTransferf (GL_POST_COLOR_MATRIX_GREEN_BIAS, 0);
|
||||||
|
glPixelTransferf (GL_POST_COLOR_MATRIX_BLUE_BIAS, 0);
|
||||||
|
|
||||||
glDrawBuffer (GL_COLOR_ATTACHMENT1_EXT);
|
glReadPixels (0, 0, buffer->width, buffer->height, GL_RGBA,
|
||||||
glReadBuffer (GL_COLOR_ATTACHMENT1_EXT);
|
GL_UNSIGNED_BYTE, data);
|
||||||
|
|
||||||
g_assert (glCheckFramebufferStatusEXT (GL_FRAMEBUFFER_EXT) ==
|
glDeleteFramebuffersEXT (1, &fbo);
|
||||||
GL_FRAMEBUFFER_COMPLETE_EXT);
|
|
||||||
|
|
||||||
glReadPixels (0, 0, buffer->width, buffer->height / 2, GL_RGBA,
|
|
||||||
GL_UNSIGNED_BYTE, data);
|
|
||||||
|
|
||||||
glDeleteFramebuffersEXT (1, &fbo);
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case GST_GL_BUFFER_TEXTURE:
|
|
||||||
{
|
|
||||||
unsigned int fbo;
|
|
||||||
|
|
||||||
glGenFramebuffersEXT (1, &fbo);
|
|
||||||
glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, fbo);
|
|
||||||
|
|
||||||
glFramebufferTexture2DEXT (GL_FRAMEBUFFER_EXT,
|
|
||||||
GL_COLOR_ATTACHMENT1_EXT, GL_TEXTURE_RECTANGLE_ARB,
|
|
||||||
buffer->texture, 0);
|
|
||||||
|
|
||||||
glDrawBuffer (GL_COLOR_ATTACHMENT1_EXT);
|
|
||||||
glReadBuffer (GL_COLOR_ATTACHMENT1_EXT);
|
|
||||||
|
|
||||||
g_assert (glCheckFramebufferStatusEXT (GL_FRAMEBUFFER_EXT) ==
|
|
||||||
GL_FRAMEBUFFER_COMPLETE_EXT);
|
|
||||||
|
|
||||||
glReadPixels (0, 0, buffer->width, buffer->height, GL_RGBA,
|
|
||||||
GL_UNSIGNED_BYTE, data);
|
|
||||||
|
|
||||||
glDeleteFramebuffersEXT (1, &fbo);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
g_assert_not_reached ();
|
|
||||||
}
|
|
||||||
|
|
||||||
gst_gl_display_unlock (buffer->display);
|
gst_gl_display_unlock (buffer->display);
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,24 +14,25 @@ typedef struct _GstGLBuffer GstGLBuffer;
|
||||||
#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))
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
GST_GL_BUFFER_UNKNOWN,
|
GST_GL_BUFFER_FORMAT_RGBA,
|
||||||
GST_GL_BUFFER_XIMAGE,
|
GST_GL_BUFFER_FORMAT_RGB,
|
||||||
GST_GL_BUFFER_RBO,
|
GST_GL_BUFFER_FORMAT_YUYV,
|
||||||
GST_GL_BUFFER_TEXTURE
|
GST_GL_BUFFER_FORMAT_PLANAR444,
|
||||||
} GstGLBufferType;
|
GST_GL_BUFFER_FORMAT_PLANAR422,
|
||||||
|
GST_GL_BUFFER_FORMAT_PLANAR420
|
||||||
|
} GstGLBufferFormat;
|
||||||
|
|
||||||
struct _GstGLBuffer {
|
struct _GstGLBuffer {
|
||||||
GstBuffer buffer;
|
GstBuffer buffer;
|
||||||
|
|
||||||
GstGLDisplay *display;
|
GstGLDisplay *display;
|
||||||
|
|
||||||
GstGLBufferType type;
|
GstGLBufferFormat format;
|
||||||
|
gboolean is_yuv;
|
||||||
|
|
||||||
XID pixmap;
|
|
||||||
GC gc;
|
|
||||||
|
|
||||||
GLuint rbo;
|
|
||||||
GLuint texture;
|
GLuint texture;
|
||||||
|
GLuint texture_u;
|
||||||
|
GLuint texture_v;
|
||||||
|
|
||||||
int width;
|
int width;
|
||||||
int height;
|
int height;
|
||||||
|
@ -39,9 +40,10 @@ struct _GstGLBuffer {
|
||||||
|
|
||||||
GType gst_gl_buffer_get_type (void);
|
GType gst_gl_buffer_get_type (void);
|
||||||
|
|
||||||
GstGLBuffer * gst_gl_buffer_new (GstGLDisplay *display, GstVideoFormat format,
|
GstGLBuffer * gst_gl_buffer_new (GstGLDisplay *display,
|
||||||
int width, int height);
|
GstGLBufferFormat format, int width, int height);
|
||||||
void gst_gl_buffer_upload (GstGLBuffer *buffer, void *data);
|
GstGLBuffer * gst_gl_buffer_new_from_data (GstGLDisplay *display,
|
||||||
|
GstVideoFormat format, int width, int height, void *data);
|
||||||
void gst_gl_buffer_download (GstGLBuffer *buffer, void *data);
|
void gst_gl_buffer_download (GstGLBuffer *buffer, void *data);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -430,8 +430,6 @@ draw_rect_texture (GstGLDisplay * display, GstVideoFormat type,
|
||||||
|
|
||||||
#ifdef GL_TEXTURE_RECTANGLE_ARB
|
#ifdef GL_TEXTURE_RECTANGLE_ARB
|
||||||
glEnable (GL_TEXTURE_RECTANGLE_ARB);
|
glEnable (GL_TEXTURE_RECTANGLE_ARB);
|
||||||
//glGenTextures (1, &texture);
|
|
||||||
//glBindTexture (GL_TEXTURE_RECTANGLE_ARB, texture);
|
|
||||||
|
|
||||||
texture = gst_gl_display_upload_texture_rectangle (display, type,
|
texture = gst_gl_display_upload_texture_rectangle (display, type,
|
||||||
data, width, height);
|
data, width, height);
|
||||||
|
|
19
gst/gl/BUGS
Normal file
19
gst/gl/BUGS
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
|
||||||
|
known issues:
|
||||||
|
|
||||||
|
- negotiation is shite. I don't want to know about any failed
|
||||||
|
negotiations or failed prerolls.
|
||||||
|
|
||||||
|
- teardown sometimes fails.
|
||||||
|
|
||||||
|
- sharing a GL context among a bunch of elements that stomp all
|
||||||
|
over it is potential fail.
|
||||||
|
|
||||||
|
|
||||||
|
intel driver:
|
||||||
|
|
||||||
|
- rendering to texture ignores the color matrix. This causes any
|
||||||
|
YUV->RGB conversion to fail.
|
||||||
|
|
||||||
|
- YUY2 and UYVY conversions in the driver use the wrong matrix.
|
||||||
|
|
|
@ -1,6 +1,11 @@
|
||||||
|
|
||||||
plugin_LTLIBRARIES = libgstglimagesink.la
|
plugin_LTLIBRARIES = libgstglimagesink.la
|
||||||
|
|
||||||
|
noinst_PROGRAMS = color_matrix
|
||||||
|
|
||||||
|
AM_CFLAGS = $(GST_CFLAGS) $(GST_BASE_CFLAGS)
|
||||||
|
AM_LIBS = $(GST_BASE_LIBS)
|
||||||
|
|
||||||
libgstglimagesink_la_SOURCES = \
|
libgstglimagesink_la_SOURCES = \
|
||||||
glimagesink.c \
|
glimagesink.c \
|
||||||
gstgldisplay.c \
|
gstgldisplay.c \
|
||||||
|
@ -11,7 +16,9 @@ libgstglimagesink_la_SOURCES = \
|
||||||
gstgldownload.c \
|
gstgldownload.c \
|
||||||
gstgltestsrc.c \
|
gstgltestsrc.c \
|
||||||
gltestsrc.c \
|
gltestsrc.c \
|
||||||
gstglfilter.c
|
gstglfilter.c \
|
||||||
|
gstglfilterexample.c \
|
||||||
|
gstglconvert.c
|
||||||
libgstglimagesink_la_CFLAGS = $(GST_CFLAGS) $(X_CFLAGS) $(GST_BASE_CFLAGS) \
|
libgstglimagesink_la_CFLAGS = $(GST_CFLAGS) $(X_CFLAGS) $(GST_BASE_CFLAGS) \
|
||||||
$(GST_PLUGINS_BASE_CFLAGS)
|
$(GST_PLUGINS_BASE_CFLAGS)
|
||||||
libgstglimagesink_la_LIBADD = $(X_LIBS) $(XSHM_LIBS) -lGL \
|
libgstglimagesink_la_LIBADD = $(X_LIBS) $(XSHM_LIBS) -lGL \
|
||||||
|
@ -25,4 +32,5 @@ noinst_HEADERS = \
|
||||||
glextensions.h \
|
glextensions.h \
|
||||||
gstgltestsrc.h \
|
gstgltestsrc.h \
|
||||||
gltestsrc.h \
|
gltestsrc.h \
|
||||||
gstglbuffer.h
|
gstglbuffer.h \
|
||||||
|
gstglfilter.h
|
||||||
|
|
243
gst/gl/color_matrix.c
Normal file
243
gst/gl/color_matrix.c
Normal file
|
@ -0,0 +1,243 @@
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
#include "config.h"
|
||||||
|
#endif
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
double comp[3];
|
||||||
|
} Color;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
Color pre_offset;
|
||||||
|
double matrix[3][3];
|
||||||
|
Color post_offset;
|
||||||
|
} ColorMatrix;
|
||||||
|
|
||||||
|
|
||||||
|
/* convert uint8 RGB values to float */
|
||||||
|
ColorMatrix rgb255_to_rgb = {
|
||||||
|
{{0, 0, 0}},
|
||||||
|
{{(1 / 255.0), 0, 0},
|
||||||
|
{0, (1 / 255.0), 0},
|
||||||
|
{0, 0, (1 / 255.0)}},
|
||||||
|
{{0, 0, 0}}
|
||||||
|
};
|
||||||
|
ColorMatrix rgb_to_rgb255;
|
||||||
|
|
||||||
|
/* convert uint8 YUV values to float as per ITU-R.601
|
||||||
|
* technically, Y, Cr, Cb to E_Y, E_C_B, E_C_R */
|
||||||
|
ColorMatrix ycbcr601_to_yuv = {
|
||||||
|
{{-16, -128, -128}},
|
||||||
|
{{(1 / 219.0), 0, 0},
|
||||||
|
{0, (1 / 224.0), 0},
|
||||||
|
{0, 0, (1 / 224.0)}},
|
||||||
|
{{0, 0, 0}}
|
||||||
|
};
|
||||||
|
ColorMatrix yuv_to_ycbcr601;
|
||||||
|
|
||||||
|
/* convert RGB to YUV as per ITU-R.601
|
||||||
|
* technically, E_R, E_G, E_B to E_Y, E_C_B, E_C_R */
|
||||||
|
ColorMatrix rgb_to_yuv = {
|
||||||
|
{{0, 0, 0}},
|
||||||
|
{{0.299, 0.587, 0.114},
|
||||||
|
{0.500, -0.419, -0.081},
|
||||||
|
{-0.169, -0.331, 0.500}},
|
||||||
|
{{0, 0, 0}}
|
||||||
|
};
|
||||||
|
ColorMatrix yuv_to_rgb;
|
||||||
|
|
||||||
|
ColorMatrix compress = {
|
||||||
|
{{0, 0, 0}},
|
||||||
|
{{0.50, 0, 0},
|
||||||
|
{0, 0.5, 0},
|
||||||
|
{0, 0, 0.500}},
|
||||||
|
{{0.25, 0.25, 0.25}}
|
||||||
|
};
|
||||||
|
|
||||||
|
/* red mask */
|
||||||
|
ColorMatrix red_mask = {
|
||||||
|
{{0, 0, 0}},
|
||||||
|
{{1, 1, 1},
|
||||||
|
{0, 0, 0},
|
||||||
|
{0, 0, 0}},
|
||||||
|
{{0, 0, 0}}
|
||||||
|
};
|
||||||
|
|
||||||
|
double colors[][3] = {
|
||||||
|
{0, 0, 0},
|
||||||
|
{255, 0, 0},
|
||||||
|
{0, 255, 0},
|
||||||
|
{0, 0, 255}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
color_dump (const double *a)
|
||||||
|
{
|
||||||
|
printf (" %g, %g, %g\n", a[0], a[1], a[2]);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
color_matrix_dump (ColorMatrix * m)
|
||||||
|
{
|
||||||
|
printf ("pre: %g, %g, %g\n",
|
||||||
|
m->pre_offset.comp[0], m->pre_offset.comp[1], m->pre_offset.comp[2]);
|
||||||
|
printf (" %g, %g, %g\n", m->matrix[0][0], m->matrix[0][1], m->matrix[0][2]);
|
||||||
|
printf (" %g, %g, %g\n", m->matrix[1][0], m->matrix[1][1], m->matrix[1][2]);
|
||||||
|
printf (" %g, %g, %g\n", m->matrix[2][0], m->matrix[2][1], m->matrix[2][2]);
|
||||||
|
printf ("post: %g, %g, %g\n",
|
||||||
|
m->post_offset.comp[0], m->post_offset.comp[1], m->post_offset.comp[2]);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
color_matrix_apply_color (Color * a, const ColorMatrix * b)
|
||||||
|
{
|
||||||
|
Color d;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
a->comp[0] += b->pre_offset.comp[0];
|
||||||
|
a->comp[1] += b->pre_offset.comp[1];
|
||||||
|
a->comp[2] += b->pre_offset.comp[2];
|
||||||
|
|
||||||
|
for (i = 0; i < 3; i++) {
|
||||||
|
d.comp[i] = a->comp[0] * b->matrix[i][0];
|
||||||
|
d.comp[i] += a->comp[1] * b->matrix[i][1];
|
||||||
|
d.comp[i] += a->comp[2] * b->matrix[i][2];
|
||||||
|
}
|
||||||
|
|
||||||
|
d.comp[0] += b->post_offset.comp[0];
|
||||||
|
d.comp[1] += b->post_offset.comp[1];
|
||||||
|
d.comp[2] += b->post_offset.comp[2];
|
||||||
|
|
||||||
|
*a = d;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
color_matrix_init (ColorMatrix * a)
|
||||||
|
{
|
||||||
|
memset (a, 0, sizeof (*a));
|
||||||
|
a->matrix[0][0] = 1.0;
|
||||||
|
a->matrix[1][1] = 1.0;
|
||||||
|
a->matrix[2][2] = 1.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
color_matrix_apply (ColorMatrix * a, ColorMatrix * b)
|
||||||
|
{
|
||||||
|
ColorMatrix d;
|
||||||
|
int i, j;
|
||||||
|
|
||||||
|
d.pre_offset = a->pre_offset;
|
||||||
|
|
||||||
|
d.post_offset = a->post_offset;
|
||||||
|
color_matrix_apply_color (&d.post_offset, b);
|
||||||
|
|
||||||
|
for (j = 0; j < 3; j++) {
|
||||||
|
for (i = 0; i < 3; i++) {
|
||||||
|
d.matrix[i][j] =
|
||||||
|
a->matrix[i][0] * b->matrix[0][j] +
|
||||||
|
a->matrix[i][1] * b->matrix[1][j] + a->matrix[i][2] * b->matrix[2][j];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
*a = d;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
color_matrix_invert (ColorMatrix * a, ColorMatrix * b)
|
||||||
|
{
|
||||||
|
int i, j;
|
||||||
|
double det;
|
||||||
|
|
||||||
|
a->post_offset.comp[0] = -b->pre_offset.comp[0];
|
||||||
|
a->post_offset.comp[1] = -b->pre_offset.comp[1];
|
||||||
|
a->post_offset.comp[2] = -b->pre_offset.comp[2];
|
||||||
|
|
||||||
|
for (j = 0; j < 3; j++) {
|
||||||
|
for (i = 0; i < 3; i++) {
|
||||||
|
a->matrix[j][i] =
|
||||||
|
b->matrix[(i + 1) % 3][(j + 1) % 3] * b->matrix[(i + 2) % 3][(j +
|
||||||
|
2) % 3] - b->matrix[(i + 1) % 3][(j + 2) % 3] * b->matrix[(i +
|
||||||
|
2) % 3][(j + 1) % 3];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
det = a->matrix[0][0] * b->matrix[0][0];
|
||||||
|
det += a->matrix[0][1] * b->matrix[1][0];
|
||||||
|
det += a->matrix[0][2] * b->matrix[2][0];
|
||||||
|
|
||||||
|
for (j = 0; j < 3; j++) {
|
||||||
|
for (i = 0; i < 3; i++) {
|
||||||
|
a->matrix[j][i] /= det;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
a->pre_offset.comp[0] = -b->post_offset.comp[0];
|
||||||
|
a->pre_offset.comp[1] = -b->post_offset.comp[1];
|
||||||
|
a->pre_offset.comp[2] = -b->post_offset.comp[2];
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
init (void)
|
||||||
|
{
|
||||||
|
color_matrix_invert (&yuv_to_rgb, &rgb_to_yuv);
|
||||||
|
color_matrix_invert (&yuv_to_ycbcr601, &ycbcr601_to_yuv);
|
||||||
|
color_matrix_invert (&rgb_to_rgb255, &rgb255_to_rgb);
|
||||||
|
#if 0
|
||||||
|
color_matrix_dump (&yuv_to_rgb);
|
||||||
|
color_matrix_dump (&yuv_to_ycbcr601);
|
||||||
|
color_matrix_dump (&rgb_to_rgb255);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
main (int argc, char *argv[])
|
||||||
|
{
|
||||||
|
ColorMatrix want;
|
||||||
|
ColorMatrix actual;
|
||||||
|
ColorMatrix actual_inv;
|
||||||
|
ColorMatrix a;
|
||||||
|
|
||||||
|
init ();
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < 4; i++) {
|
||||||
|
double color[3];
|
||||||
|
|
||||||
|
printf ("%d:\n", i);
|
||||||
|
|
||||||
|
color_copy (color, colors[i]);
|
||||||
|
color_matrix_apply_color (color, &rgb255_to_rgb);
|
||||||
|
color_matrix_apply_color (color, &rgb_to_yuv);
|
||||||
|
color_dump (color);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
color_matrix_init (&want);
|
||||||
|
color_matrix_apply (&want, &ycbcr601_to_yuv);
|
||||||
|
color_matrix_apply (&want, &yuv_to_rgb);
|
||||||
|
color_matrix_apply (&want, &compress);
|
||||||
|
color_matrix_apply (&want, &compress);
|
||||||
|
//color_matrix_apply (&want, &compress);
|
||||||
|
|
||||||
|
color_matrix_init (&actual);
|
||||||
|
color_matrix_apply (&actual, &rgb255_to_rgb);
|
||||||
|
|
||||||
|
/* calc X such that actual * X = want */
|
||||||
|
|
||||||
|
color_matrix_invert (&actual_inv, &actual);
|
||||||
|
|
||||||
|
a = actual_inv;
|
||||||
|
color_matrix_apply (&a, &want);
|
||||||
|
|
||||||
|
color_matrix_dump (&a);
|
||||||
|
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
253
gst/gl/gstglconvert.c
Normal file
253
gst/gl/gstglconvert.c
Normal file
|
@ -0,0 +1,253 @@
|
||||||
|
/*
|
||||||
|
* GStreamer
|
||||||
|
* Copyright (C) 2007 David Schleef <ds@schleef.org>
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Library General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Library General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Library General Public
|
||||||
|
* License along with this library; if not, write to the
|
||||||
|
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||||
|
* Boston, MA 02111-1307, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
#include "config.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <gst/gst.h>
|
||||||
|
#include <gst/video/video.h>
|
||||||
|
#include <gstglbuffer.h>
|
||||||
|
#include <gstglfilter.h>
|
||||||
|
#include "glextensions.h"
|
||||||
|
|
||||||
|
#define GST_CAT_DEFAULT gst_gl_convert_debug
|
||||||
|
GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
|
||||||
|
|
||||||
|
#define GST_TYPE_GL_CONVERT (gst_gl_convert_get_type())
|
||||||
|
#define GST_GL_CONVERT(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_GL_CONVERT,GstGLConvert))
|
||||||
|
#define GST_IS_GL_CONVERT(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_GL_CONVERT))
|
||||||
|
#define GST_GL_CONVERT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass) ,GST_TYPE_GL_CONVERT,GstGLConvertClass))
|
||||||
|
#define GST_IS_GL_CONVERT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass) ,GST_TYPE_GL_CONVERT))
|
||||||
|
#define GST_GL_CONVERT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj) ,GST_TYPE_GL_CONVERT,GstGLConvertClass))
|
||||||
|
typedef struct _GstGLConvert GstGLConvert;
|
||||||
|
typedef struct _GstGLConvertClass GstGLConvertClass;
|
||||||
|
|
||||||
|
struct _GstGLConvert
|
||||||
|
{
|
||||||
|
GstGLFilter filter;
|
||||||
|
|
||||||
|
/* < private > */
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _GstGLConvertClass
|
||||||
|
{
|
||||||
|
GstGLFilterClass filter_class;
|
||||||
|
};
|
||||||
|
|
||||||
|
static const GstElementDetails element_details = GST_ELEMENT_DETAILS ("FIXME",
|
||||||
|
"Filter/Effect",
|
||||||
|
"FIXME GL conversion filter",
|
||||||
|
"FIXME <fixme@fixme.com>");
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
#define GST_GL_VIDEO_CAPS "video/x-raw-gl"
|
||||||
|
|
||||||
|
static GstStaticPadTemplate gst_gl_convert_src_pad_template =
|
||||||
|
GST_STATIC_PAD_TEMPLATE ("src",
|
||||||
|
GST_PAD_SRC,
|
||||||
|
GST_PAD_ALWAYS,
|
||||||
|
GST_STATIC_CAPS (GST_GL_VIDEO_CAPS)
|
||||||
|
);
|
||||||
|
|
||||||
|
static GstStaticPadTemplate gst_gl_convert_sink_pad_template =
|
||||||
|
GST_STATIC_PAD_TEMPLATE ("sink",
|
||||||
|
GST_PAD_SINK,
|
||||||
|
GST_PAD_ALWAYS,
|
||||||
|
GST_STATIC_CAPS (GST_GL_VIDEO_CAPS)
|
||||||
|
);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
PROP_0
|
||||||
|
};
|
||||||
|
|
||||||
|
#define DEBUG_INIT(bla) \
|
||||||
|
GST_DEBUG_CATEGORY_INIT (gst_gl_convert_debug, "glconvert", 0, "glconvert element");
|
||||||
|
|
||||||
|
GST_BOILERPLATE_FULL (GstGLConvert, gst_gl_convert, GstGLFilter,
|
||||||
|
GST_TYPE_GL_FILTER, DEBUG_INIT);
|
||||||
|
|
||||||
|
static void gst_gl_convert_set_property (GObject * object, guint prop_id,
|
||||||
|
const GValue * value, GParamSpec * pspec);
|
||||||
|
static void gst_gl_convert_get_property (GObject * object, guint prop_id,
|
||||||
|
GValue * value, GParamSpec * pspec);
|
||||||
|
|
||||||
|
static void gst_gl_convert_reset (GstGLConvert * filter);
|
||||||
|
static gboolean gst_gl_convert_transform (GstGLFilter * filter,
|
||||||
|
GstGLBuffer * outbuf, GstGLBuffer * inbuf);
|
||||||
|
static gboolean gst_gl_convert_start (GstGLFilter * _filter);
|
||||||
|
static gboolean gst_gl_convert_stop (GstGLFilter * _filter);
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_gl_convert_base_init (gpointer klass)
|
||||||
|
{
|
||||||
|
GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
|
||||||
|
|
||||||
|
gst_element_class_set_details (element_class, &element_details);
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
gst_element_class_add_pad_template (element_class,
|
||||||
|
gst_static_pad_template_get (&gst_gl_convert_src_pad_template));
|
||||||
|
gst_element_class_add_pad_template (element_class,
|
||||||
|
gst_static_pad_template_get (&gst_gl_convert_sink_pad_template));
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_gl_convert_class_init (GstGLConvertClass * klass)
|
||||||
|
{
|
||||||
|
GObjectClass *gobject_class;
|
||||||
|
|
||||||
|
gobject_class = (GObjectClass *) klass;
|
||||||
|
gobject_class->set_property = gst_gl_convert_set_property;
|
||||||
|
gobject_class->get_property = gst_gl_convert_get_property;
|
||||||
|
|
||||||
|
GST_GL_FILTER_CLASS (klass)->transform = gst_gl_convert_transform;
|
||||||
|
GST_GL_FILTER_CLASS (klass)->start = gst_gl_convert_start;
|
||||||
|
GST_GL_FILTER_CLASS (klass)->stop = gst_gl_convert_stop;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_gl_convert_init (GstGLConvert * filter, GstGLConvertClass * klass)
|
||||||
|
{
|
||||||
|
gst_gl_convert_reset (filter);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_gl_convert_set_property (GObject * object, guint prop_id,
|
||||||
|
const GValue * value, GParamSpec * pspec)
|
||||||
|
{
|
||||||
|
//GstGLConvert *filter = GST_GL_CONVERT (object);
|
||||||
|
|
||||||
|
switch (prop_id) {
|
||||||
|
default:
|
||||||
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_gl_convert_get_property (GObject * object, guint prop_id,
|
||||||
|
GValue * value, GParamSpec * pspec)
|
||||||
|
{
|
||||||
|
//GstGLConvert *filter = GST_GL_CONVERT (object);
|
||||||
|
|
||||||
|
switch (prop_id) {
|
||||||
|
default:
|
||||||
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_gl_convert_reset (GstGLConvert * filter)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
gst_gl_convert_start (GstGLFilter * _filter)
|
||||||
|
{
|
||||||
|
//GstGLConvert *convert = GST_GL_CONVERT(_filter);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
gst_gl_convert_stop (GstGLFilter * _filter)
|
||||||
|
{
|
||||||
|
GstGLConvert *convert = GST_GL_CONVERT (_filter);
|
||||||
|
|
||||||
|
gst_gl_convert_reset (convert);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
gst_gl_convert_transform (GstGLFilter * filter, GstGLBuffer * outbuf,
|
||||||
|
GstGLBuffer * inbuf)
|
||||||
|
{
|
||||||
|
//GstGLConvert *convert = GST_GL_CONVERT(filter);
|
||||||
|
|
||||||
|
glDisable (GL_CULL_FACE);
|
||||||
|
glEnableClientState (GL_TEXTURE_COORD_ARRAY);
|
||||||
|
|
||||||
|
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);
|
||||||
|
glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP);
|
||||||
|
glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
|
||||||
|
|
||||||
|
if (inbuf->is_yuv) {
|
||||||
|
#ifdef GL_POST_COLOR_MATRIX_RED_BIAS
|
||||||
|
const double matrix[16] = {
|
||||||
|
1.16438, 1.6321, -0.00107909, 0,
|
||||||
|
1.13839, -0.813005, -0.39126, 0,
|
||||||
|
1.13839, 0.00112726, 2.01741, 0,
|
||||||
|
0, 0, 0, 1
|
||||||
|
};
|
||||||
|
|
||||||
|
GST_DEBUG ("applying YUV->RGB conversion");
|
||||||
|
|
||||||
|
glMatrixMode (GL_COLOR);
|
||||||
|
glLoadMatrixd (matrix);
|
||||||
|
|
||||||
|
/* same */
|
||||||
|
glPixelTransferf (GL_POST_COLOR_MATRIX_RED_BIAS, -0.873494);
|
||||||
|
glPixelTransferf (GL_POST_COLOR_MATRIX_GREEN_BIAS, 0.531435);
|
||||||
|
glPixelTransferf (GL_POST_COLOR_MATRIX_BLUE_BIAS, -1.08629);
|
||||||
|
#else
|
||||||
|
g_assert_not_reached ();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
glColor4f (1, 0, 1, 1);
|
||||||
|
|
||||||
|
glBegin (GL_QUADS);
|
||||||
|
glNormal3f (0, 0, -1);
|
||||||
|
glTexCoord2f (inbuf->width, 0);
|
||||||
|
glVertex3f (1.0, -1.0, 0);
|
||||||
|
glTexCoord2f (0, 0);
|
||||||
|
glVertex3f (-1.0, -1.0, 0);
|
||||||
|
glTexCoord2f (0, inbuf->height);
|
||||||
|
glVertex3f (-1.0, 1.0, 0);
|
||||||
|
glTexCoord2f (inbuf->width, inbuf->height);
|
||||||
|
glVertex3f (1.0, 1.0, 0);
|
||||||
|
glEnd ();
|
||||||
|
|
||||||
|
if (inbuf->is_yuv) {
|
||||||
|
#ifdef GL_POST_COLOR_MATRIX_RED_BIAS
|
||||||
|
glMatrixMode (GL_COLOR);
|
||||||
|
glLoadIdentity ();
|
||||||
|
|
||||||
|
glPixelTransferf (GL_POST_COLOR_MATRIX_RED_BIAS, 0);
|
||||||
|
glPixelTransferf (GL_POST_COLOR_MATRIX_GREEN_BIAS, 0);
|
||||||
|
glPixelTransferf (GL_POST_COLOR_MATRIX_BLUE_BIAS, 0);
|
||||||
|
#else
|
||||||
|
g_assert_not_reached ();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
|
@ -25,46 +25,12 @@
|
||||||
#include <gst/gst.h>
|
#include <gst/gst.h>
|
||||||
#include <gst/video/video.h>
|
#include <gst/video/video.h>
|
||||||
#include <gstglbuffer.h>
|
#include <gstglbuffer.h>
|
||||||
|
#include <gstglfilter.h>
|
||||||
#include "glextensions.h"
|
#include "glextensions.h"
|
||||||
|
|
||||||
#define GST_CAT_DEFAULT gst_gl_filter_debug
|
#define GST_CAT_DEFAULT gst_gl_filter_debug
|
||||||
GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
|
GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
|
||||||
|
|
||||||
#define GST_TYPE_GL_FILTER (gst_gl_filter_get_type())
|
|
||||||
#define GST_GL_FILTER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_GL_FILTER,GstGLFilter))
|
|
||||||
#define GST_IS_GL_FILTER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_GL_FILTER))
|
|
||||||
#define GST_GL_FILTER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass) ,GST_TYPE_GL_FILTER,GstGLFilterClass))
|
|
||||||
#define GST_IS_GL_FILTER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass) ,GST_TYPE_GL_FILTER))
|
|
||||||
#define GST_GL_FILTER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj) ,GST_TYPE_GL_FILTER,GstGLFilterClass))
|
|
||||||
typedef struct _GstGLFilter GstGLFilter;
|
|
||||||
typedef struct _GstGLFilterClass GstGLFilterClass;
|
|
||||||
|
|
||||||
typedef void (*GstGLFilterProcessFunc) (GstGLFilter *, guint8 *, guint);
|
|
||||||
|
|
||||||
struct _GstGLFilter
|
|
||||||
{
|
|
||||||
GstElement element;
|
|
||||||
|
|
||||||
GstPad *srcpad;
|
|
||||||
GstPad *sinkpad;
|
|
||||||
|
|
||||||
/* < private > */
|
|
||||||
|
|
||||||
GstGLDisplay *display;
|
|
||||||
GstVideoFormat format;
|
|
||||||
int width;
|
|
||||||
int height;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct _GstGLFilterClass
|
|
||||||
{
|
|
||||||
GstElementClass element_class;
|
|
||||||
};
|
|
||||||
|
|
||||||
static const GstElementDetails element_details = GST_ELEMENT_DETAILS ("FIXME",
|
|
||||||
"Filter/Effect",
|
|
||||||
"FIXME example filter",
|
|
||||||
"FIXME <fixme@fixme.com>");
|
|
||||||
|
|
||||||
#define GST_GL_VIDEO_CAPS "video/x-raw-gl"
|
#define GST_GL_VIDEO_CAPS "video/x-raw-gl"
|
||||||
|
|
||||||
|
@ -82,11 +48,6 @@ GST_STATIC_PAD_TEMPLATE ("sink",
|
||||||
GST_STATIC_CAPS (GST_GL_VIDEO_CAPS)
|
GST_STATIC_CAPS (GST_GL_VIDEO_CAPS)
|
||||||
);
|
);
|
||||||
|
|
||||||
enum
|
|
||||||
{
|
|
||||||
PROP_0
|
|
||||||
};
|
|
||||||
|
|
||||||
#define DEBUG_INIT(bla) \
|
#define DEBUG_INIT(bla) \
|
||||||
GST_DEBUG_CATEGORY_INIT (gst_gl_filter_debug, "glfilter", 0, "glfilter element");
|
GST_DEBUG_CATEGORY_INIT (gst_gl_filter_debug, "glfilter", 0, "glfilter element");
|
||||||
|
|
||||||
|
@ -103,8 +64,8 @@ static void gst_gl_filter_reset (GstGLFilter * filter);
|
||||||
static GstStateChangeReturn
|
static GstStateChangeReturn
|
||||||
gst_gl_filter_change_state (GstElement * element, GstStateChange transition);
|
gst_gl_filter_change_state (GstElement * element, GstStateChange transition);
|
||||||
static gboolean gst_gl_filter_sink_setcaps (GstPad * pad, GstCaps * caps);
|
static gboolean gst_gl_filter_sink_setcaps (GstPad * pad, GstCaps * caps);
|
||||||
static gboolean gst_gl_filter_transform (GstGLBuffer * outbuf,
|
static gboolean gst_gl_filter_do_transform (GstGLFilter * filter,
|
||||||
GstGLBuffer * inbuf);
|
GstGLBuffer * outbuf, GstGLBuffer * inbuf);
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -112,8 +73,6 @@ gst_gl_filter_base_init (gpointer klass)
|
||||||
{
|
{
|
||||||
GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
|
GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
|
||||||
|
|
||||||
gst_element_class_set_details (element_class, &element_details);
|
|
||||||
|
|
||||||
gst_element_class_add_pad_template (element_class,
|
gst_element_class_add_pad_template (element_class,
|
||||||
gst_static_pad_template_get (&gst_gl_filter_src_pad_template));
|
gst_static_pad_template_get (&gst_gl_filter_src_pad_template));
|
||||||
gst_element_class_add_pad_template (element_class,
|
gst_element_class_add_pad_template (element_class,
|
||||||
|
@ -179,17 +138,26 @@ gst_gl_filter_reset (GstGLFilter * filter)
|
||||||
g_object_unref (filter->display);
|
g_object_unref (filter->display);
|
||||||
filter->display = NULL;
|
filter->display = NULL;
|
||||||
}
|
}
|
||||||
filter->format = GST_VIDEO_FORMAT_RGBx;
|
filter->format = GST_GL_BUFFER_FORMAT_RGB;
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
gst_gl_filter_start (GstGLFilter * filter)
|
gst_gl_filter_start (GstGLFilter * filter)
|
||||||
{
|
{
|
||||||
|
GstGLFilterClass *filter_class;
|
||||||
gboolean ret;
|
gboolean ret;
|
||||||
|
|
||||||
filter->format = GST_VIDEO_FORMAT_RGBx;
|
filter_class = GST_GL_FILTER_GET_CLASS (filter);
|
||||||
|
|
||||||
|
filter->format = GST_GL_BUFFER_FORMAT_RGB;
|
||||||
filter->display = gst_gl_display_new ();
|
filter->display = gst_gl_display_new ();
|
||||||
ret = gst_gl_display_connect (filter->display, NULL);
|
ret = gst_gl_display_connect (filter->display, NULL);
|
||||||
|
if (!ret)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
if (filter_class->start) {
|
||||||
|
ret = filter_class->start (filter);
|
||||||
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -197,8 +165,20 @@ gst_gl_filter_start (GstGLFilter * filter)
|
||||||
static gboolean
|
static gboolean
|
||||||
gst_gl_filter_stop (GstGLFilter * filter)
|
gst_gl_filter_stop (GstGLFilter * filter)
|
||||||
{
|
{
|
||||||
|
GstGLFilterClass *filter_class;
|
||||||
|
gboolean ret;
|
||||||
|
|
||||||
|
filter_class = GST_GL_FILTER_GET_CLASS (filter);
|
||||||
|
|
||||||
gst_gl_filter_reset (filter);
|
gst_gl_filter_reset (filter);
|
||||||
|
|
||||||
|
if (filter_class->stop) {
|
||||||
|
ret = filter_class->stop (filter);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_object_unref (filter->display);
|
||||||
|
filter->display = NULL;
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -218,7 +198,7 @@ gst_gl_filter_sink_setcaps (GstPad * pad, GstCaps * caps)
|
||||||
if (!ret)
|
if (!ret)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
GST_ERROR ("setcaps %d %d", filter->width, filter->height);
|
GST_DEBUG ("setcaps %d %d", filter->width, filter->height);
|
||||||
|
|
||||||
ret = gst_pad_set_caps (filter->srcpad, caps);
|
ret = gst_pad_set_caps (filter->srcpad, caps);
|
||||||
|
|
||||||
|
@ -242,7 +222,7 @@ gst_gl_filter_chain (GstPad * pad, GstBuffer * buf)
|
||||||
GST_BUFFER_COPY_TIMESTAMPS | GST_BUFFER_COPY_FLAGS);
|
GST_BUFFER_COPY_TIMESTAMPS | GST_BUFFER_COPY_FLAGS);
|
||||||
gst_buffer_set_caps (GST_BUFFER (outbuf), GST_PAD_CAPS (filter->srcpad));
|
gst_buffer_set_caps (GST_BUFFER (outbuf), GST_PAD_CAPS (filter->srcpad));
|
||||||
|
|
||||||
gst_gl_filter_transform (outbuf, inbuf);
|
gst_gl_filter_do_transform (filter, outbuf, inbuf);
|
||||||
|
|
||||||
gst_pad_push (filter->srcpad, GST_BUFFER (outbuf));
|
gst_pad_push (filter->srcpad, GST_BUFFER (outbuf));
|
||||||
|
|
||||||
|
@ -292,65 +272,21 @@ gst_gl_filter_change_state (GstElement * element, GstStateChange transition)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
dump_fbconfigs (Display * display)
|
|
||||||
{
|
|
||||||
GLXFBConfig *fbconfigs;
|
|
||||||
int n;
|
|
||||||
int i;
|
|
||||||
int j;
|
|
||||||
int ret;
|
|
||||||
int value;
|
|
||||||
struct
|
|
||||||
{
|
|
||||||
int attr;
|
|
||||||
char *name;
|
|
||||||
} list[] = {
|
|
||||||
{
|
|
||||||
GLX_DRAWABLE_TYPE, "drawable type"}, {
|
|
||||||
GLX_BIND_TO_TEXTURE_TARGETS_EXT, "bind to texture targets"}, {
|
|
||||||
GLX_BIND_TO_TEXTURE_RGBA_EXT, "bind to texture rgba"}, {
|
|
||||||
GLX_MAX_PBUFFER_WIDTH, "max pbuffer width"}, {
|
|
||||||
GLX_MAX_PBUFFER_HEIGHT, "max pbuffer height"}, {
|
|
||||||
GLX_MAX_PBUFFER_PIXELS, "max pbuffer pixels"}, {
|
|
||||||
GLX_RENDER_TYPE, "render type"}, {
|
|
||||||
0, 0}
|
|
||||||
};
|
|
||||||
|
|
||||||
g_print ("screen count: %d\n", ScreenCount (display));
|
|
||||||
|
|
||||||
fbconfigs = glXGetFBConfigs (display, 0, &n);
|
|
||||||
for (i = 0; i < n; i++) {
|
|
||||||
g_print ("%d:\n", i);
|
|
||||||
for (j = 0; list[j].attr; j++) {
|
|
||||||
ret = glXGetFBConfigAttrib (display, fbconfigs[i], list[j].attr, &value);
|
|
||||||
if (ret != Success) {
|
|
||||||
g_print ("%s: failed\n", list[j].name);
|
|
||||||
} else {
|
|
||||||
g_print ("%s: %d\n", list[j].name, value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
gst_gl_filter_transform (GstGLBuffer * outbuf, GstGLBuffer * inbuf)
|
gst_gl_filter_do_transform (GstGLFilter * filter,
|
||||||
|
GstGLBuffer * outbuf, GstGLBuffer * inbuf)
|
||||||
{
|
{
|
||||||
GstGLDisplay *display = inbuf->display;
|
GstGLDisplay *display = inbuf->display;
|
||||||
|
GstGLFilterClass *filter_class;
|
||||||
unsigned int fbo;
|
unsigned int fbo;
|
||||||
|
|
||||||
|
filter_class = GST_GL_FILTER_GET_CLASS (filter);
|
||||||
|
|
||||||
gst_gl_display_lock (display);
|
gst_gl_display_lock (display);
|
||||||
|
|
||||||
glGenFramebuffersEXT (1, &fbo);
|
glGenFramebuffersEXT (1, &fbo);
|
||||||
glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, fbo);
|
glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, fbo);
|
||||||
|
|
||||||
/* FIXME: This should be part of buffer creation */
|
|
||||||
glGenTextures (1, &outbuf->texture);
|
|
||||||
glBindTexture (GL_TEXTURE_RECTANGLE_ARB, outbuf->texture);
|
|
||||||
glTexImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA,
|
|
||||||
outbuf->width, outbuf->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
|
|
||||||
|
|
||||||
glFramebufferTexture2DEXT (GL_FRAMEBUFFER_EXT,
|
glFramebufferTexture2DEXT (GL_FRAMEBUFFER_EXT,
|
||||||
GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_RECTANGLE_ARB, outbuf->texture, 0);
|
GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_RECTANGLE_ARB, outbuf->texture, 0);
|
||||||
|
|
||||||
|
@ -379,6 +315,9 @@ gst_gl_filter_transform (GstGLBuffer * outbuf, GstGLBuffer * inbuf)
|
||||||
glEnable (GL_TEXTURE_RECTANGLE_ARB);
|
glEnable (GL_TEXTURE_RECTANGLE_ARB);
|
||||||
glBindTexture (GL_TEXTURE_RECTANGLE_ARB, inbuf->texture);
|
glBindTexture (GL_TEXTURE_RECTANGLE_ARB, inbuf->texture);
|
||||||
|
|
||||||
|
filter_class->transform (filter, outbuf, inbuf);
|
||||||
|
|
||||||
|
#if 0
|
||||||
glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
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_MIN_FILTER, GL_LINEAR);
|
||||||
glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP);
|
glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP);
|
||||||
|
@ -399,6 +338,7 @@ gst_gl_filter_transform (GstGLBuffer * outbuf, GstGLBuffer * inbuf)
|
||||||
glTexCoord2f (inbuf->width, inbuf->height);
|
glTexCoord2f (inbuf->width, inbuf->height);
|
||||||
glVertex3f (1.0, 1.0, 0);
|
glVertex3f (1.0, 1.0, 0);
|
||||||
glEnd ();
|
glEnd ();
|
||||||
|
#endif
|
||||||
|
|
||||||
glFlush ();
|
glFlush ();
|
||||||
|
|
||||||
|
|
68
gst/gl/gstglfilter.h
Normal file
68
gst/gl/gstglfilter.h
Normal file
|
@ -0,0 +1,68 @@
|
||||||
|
/*
|
||||||
|
* GStreamer
|
||||||
|
* Copyright (C) 2007 David Schleef <ds@schleef.org>
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Library General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Library General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Library General Public
|
||||||
|
* License along with this library; if not, write to the
|
||||||
|
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||||
|
* Boston, MA 02111-1307, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _GST_GL_FILTER_H_
|
||||||
|
#define _GST_GL_FILTER_H_
|
||||||
|
|
||||||
|
#include <gst/gst.h>
|
||||||
|
#include <gst/video/video.h>
|
||||||
|
#include <gstglbuffer.h>
|
||||||
|
|
||||||
|
#define GST_TYPE_GL_FILTER (gst_gl_filter_get_type())
|
||||||
|
#define GST_GL_FILTER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_GL_FILTER,GstGLFilter))
|
||||||
|
#define GST_IS_GL_FILTER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_GL_FILTER))
|
||||||
|
#define GST_GL_FILTER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass) ,GST_TYPE_GL_FILTER,GstGLFilterClass))
|
||||||
|
#define GST_IS_GL_FILTER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass) ,GST_TYPE_GL_FILTER))
|
||||||
|
#define GST_GL_FILTER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj) ,GST_TYPE_GL_FILTER,GstGLFilterClass))
|
||||||
|
typedef struct _GstGLFilter GstGLFilter;
|
||||||
|
typedef struct _GstGLFilterClass GstGLFilterClass;
|
||||||
|
|
||||||
|
typedef gboolean (*GstGLFilterProcessFunc) (GstGLFilter *filter,
|
||||||
|
GstGLBuffer *outbuf, GstGLBuffer *inbuf);
|
||||||
|
typedef gboolean (*GstGLFilterStartFunc) (GstGLFilter *filter);
|
||||||
|
typedef gboolean (*GstGLFilterStopFunc) (GstGLFilter *filter);
|
||||||
|
|
||||||
|
struct _GstGLFilter
|
||||||
|
{
|
||||||
|
GstElement element;
|
||||||
|
|
||||||
|
GstPad *srcpad;
|
||||||
|
GstPad *sinkpad;
|
||||||
|
|
||||||
|
/* < private > */
|
||||||
|
|
||||||
|
GstGLDisplay *display;
|
||||||
|
GstGLBufferFormat format;
|
||||||
|
int width;
|
||||||
|
int height;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _GstGLFilterClass
|
||||||
|
{
|
||||||
|
GstElementClass element_class;
|
||||||
|
GstGLFilterProcessFunc transform;
|
||||||
|
GstGLFilterStartFunc start;
|
||||||
|
GstGLFilterStopFunc stop;
|
||||||
|
};
|
||||||
|
|
||||||
|
GType gst_gl_filter_get_type(void);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
243
gst/gl/gstglfilterexample.c
Normal file
243
gst/gl/gstglfilterexample.c
Normal file
|
@ -0,0 +1,243 @@
|
||||||
|
/*
|
||||||
|
* GStreamer
|
||||||
|
* Copyright (C) 2007 David Schleef <ds@schleef.org>
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Library General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Library General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Library General Public
|
||||||
|
* License along with this library; if not, write to the
|
||||||
|
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||||
|
* Boston, MA 02111-1307, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
#include "config.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <gst/gst.h>
|
||||||
|
#include <gst/video/video.h>
|
||||||
|
#include <gstglbuffer.h>
|
||||||
|
#include <gstglfilter.h>
|
||||||
|
#include "glextensions.h"
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#define GST_CAT_DEFAULT gst_gl_filter_example_debug
|
||||||
|
GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
|
||||||
|
|
||||||
|
#define GST_TYPE_GL_FILTER_EXAMPLE (gst_gl_filter_example_get_type())
|
||||||
|
#define GST_GL_FILTER_EXAMPLE(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_GL_FILTER_EXAMPLE,GstGLFilterExample))
|
||||||
|
#define GST_IS_GL_FILTER_EXAMPLE(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_GL_FILTER_EXAMPLE))
|
||||||
|
#define GST_GL_FILTER_EXAMPLE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass) ,GST_TYPE_GL_FILTER_EXAMPLE,GstGLFilterExampleClass))
|
||||||
|
#define GST_IS_GL_FILTER_EXAMPLE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass) ,GST_TYPE_GL_FILTER_EXAMPLE))
|
||||||
|
#define GST_GL_FILTER_EXAMPLE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj) ,GST_TYPE_GL_FILTER_EXAMPLE,GstGLFilterExampleClass))
|
||||||
|
typedef struct _GstGLFilterExample GstGLFilterExample;
|
||||||
|
typedef struct _GstGLFilterExampleClass GstGLFilterExampleClass;
|
||||||
|
|
||||||
|
struct _GstGLFilterExample
|
||||||
|
{
|
||||||
|
GstGLFilter filter;
|
||||||
|
|
||||||
|
/* < private > */
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _GstGLFilterExampleClass
|
||||||
|
{
|
||||||
|
GstGLFilterClass filter_class;
|
||||||
|
};
|
||||||
|
|
||||||
|
static const GstElementDetails element_details = GST_ELEMENT_DETAILS ("FIXME",
|
||||||
|
"Filter/Effect",
|
||||||
|
"FIXME example filter",
|
||||||
|
"FIXME <fixme@fixme.com>");
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
#define GST_GL_VIDEO_CAPS "video/x-raw-gl"
|
||||||
|
|
||||||
|
static GstStaticPadTemplate gst_gl_filter_example_src_pad_template =
|
||||||
|
GST_STATIC_PAD_TEMPLATE ("src",
|
||||||
|
GST_PAD_SRC,
|
||||||
|
GST_PAD_ALWAYS,
|
||||||
|
GST_STATIC_CAPS (GST_GL_VIDEO_CAPS)
|
||||||
|
);
|
||||||
|
|
||||||
|
static GstStaticPadTemplate gst_gl_filter_example_sink_pad_template =
|
||||||
|
GST_STATIC_PAD_TEMPLATE ("sink",
|
||||||
|
GST_PAD_SINK,
|
||||||
|
GST_PAD_ALWAYS,
|
||||||
|
GST_STATIC_CAPS (GST_GL_VIDEO_CAPS)
|
||||||
|
);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
PROP_0
|
||||||
|
};
|
||||||
|
|
||||||
|
#define DEBUG_INIT(bla) \
|
||||||
|
GST_DEBUG_CATEGORY_INIT (gst_gl_filter_example_debug, "glfilterexample", 0, "glfilterexample element");
|
||||||
|
|
||||||
|
GST_BOILERPLATE_FULL (GstGLFilterExample, gst_gl_filter_example, GstGLFilter,
|
||||||
|
GST_TYPE_GL_FILTER, DEBUG_INIT);
|
||||||
|
|
||||||
|
static void gst_gl_filter_example_set_property (GObject * object, guint prop_id,
|
||||||
|
const GValue * value, GParamSpec * pspec);
|
||||||
|
static void gst_gl_filter_example_get_property (GObject * object, guint prop_id,
|
||||||
|
GValue * value, GParamSpec * pspec);
|
||||||
|
|
||||||
|
static void gst_gl_filter_example_reset (GstGLFilterExample * filter);
|
||||||
|
static gboolean gst_gl_filter_example_transform (GstGLFilter * filter,
|
||||||
|
GstGLBuffer * outbuf, GstGLBuffer * inbuf);
|
||||||
|
static gboolean gst_gl_filter_example_start (GstGLFilter * filter);
|
||||||
|
static gboolean gst_gl_filter_example_stop (GstGLFilter * filter);
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_gl_filter_example_base_init (gpointer klass)
|
||||||
|
{
|
||||||
|
GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
|
||||||
|
|
||||||
|
gst_element_class_set_details (element_class, &element_details);
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
gst_element_class_add_pad_template (element_class,
|
||||||
|
gst_static_pad_template_get (&gst_gl_filter_example_src_pad_template));
|
||||||
|
gst_element_class_add_pad_template (element_class,
|
||||||
|
gst_static_pad_template_get (&gst_gl_filter_example_sink_pad_template));
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_gl_filter_example_class_init (GstGLFilterExampleClass * klass)
|
||||||
|
{
|
||||||
|
GObjectClass *gobject_class;
|
||||||
|
|
||||||
|
gobject_class = (GObjectClass *) klass;
|
||||||
|
gobject_class->set_property = gst_gl_filter_example_set_property;
|
||||||
|
gobject_class->get_property = gst_gl_filter_example_get_property;
|
||||||
|
|
||||||
|
GST_GL_FILTER_CLASS (klass)->transform = gst_gl_filter_example_transform;
|
||||||
|
GST_GL_FILTER_CLASS (klass)->start = gst_gl_filter_example_start;
|
||||||
|
GST_GL_FILTER_CLASS (klass)->stop = gst_gl_filter_example_stop;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_gl_filter_example_init (GstGLFilterExample * filter,
|
||||||
|
GstGLFilterExampleClass * klass)
|
||||||
|
{
|
||||||
|
gst_gl_filter_example_reset (filter);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_gl_filter_example_set_property (GObject * object, guint prop_id,
|
||||||
|
const GValue * value, GParamSpec * pspec)
|
||||||
|
{
|
||||||
|
//GstGLFilterExample *filter = GST_GL_FILTER_EXAMPLE (object);
|
||||||
|
|
||||||
|
switch (prop_id) {
|
||||||
|
default:
|
||||||
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_gl_filter_example_get_property (GObject * object, guint prop_id,
|
||||||
|
GValue * value, GParamSpec * pspec)
|
||||||
|
{
|
||||||
|
//GstGLFilterExample *filter = GST_GL_FILTER_EXAMPLE (object);
|
||||||
|
|
||||||
|
switch (prop_id) {
|
||||||
|
default:
|
||||||
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_gl_filter_example_reset (GstGLFilterExample * filter)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
gst_gl_filter_example_start (GstGLFilter * _filter)
|
||||||
|
{
|
||||||
|
//GstGLFilterExample *filter = GST_GL_FILTER_EXAMPLE(_filter);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
gst_gl_filter_example_stop (GstGLFilter * _filter)
|
||||||
|
{
|
||||||
|
GstGLFilterExample *filter = GST_GL_FILTER_EXAMPLE (_filter);
|
||||||
|
|
||||||
|
gst_gl_filter_example_reset (filter);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
gst_gl_filter_example_transform (GstGLFilter * filter, GstGLBuffer * outbuf,
|
||||||
|
GstGLBuffer * inbuf)
|
||||||
|
{
|
||||||
|
//GstGLFilterExample *example = GST_GL_FILTER_EXAMPLE(filter);
|
||||||
|
|
||||||
|
glDisable (GL_CULL_FACE);
|
||||||
|
glEnableClientState (GL_TEXTURE_COORD_ARRAY);
|
||||||
|
|
||||||
|
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);
|
||||||
|
glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP);
|
||||||
|
glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
|
||||||
|
|
||||||
|
glColor4f (1, 0, 1, 1);
|
||||||
|
|
||||||
|
#define GAIN 0.5
|
||||||
|
{
|
||||||
|
const double matrix[16] = {
|
||||||
|
0, 0, 1.0, 0,
|
||||||
|
0, 1.0, 0, 0,
|
||||||
|
1.0, 0, 0, 0,
|
||||||
|
0, 0, 0, 1
|
||||||
|
};
|
||||||
|
|
||||||
|
glMatrixMode (GL_COLOR);
|
||||||
|
glLoadMatrixd (matrix);
|
||||||
|
glPixelTransferf (GL_POST_COLOR_MATRIX_RED_BIAS, (1 - GAIN) / 2);
|
||||||
|
glPixelTransferf (GL_POST_COLOR_MATRIX_GREEN_BIAS, (1 - GAIN) / 2);
|
||||||
|
glPixelTransferf (GL_POST_COLOR_MATRIX_BLUE_BIAS, (1 - GAIN) / 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
glBegin (GL_QUADS);
|
||||||
|
glNormal3f (0, 0, -1);
|
||||||
|
glTexCoord2f (inbuf->width, 0);
|
||||||
|
glVertex3f (0.9, -0.9, 0);
|
||||||
|
glTexCoord2f (0, 0);
|
||||||
|
glVertex3f (-1.0, -1.0, 0);
|
||||||
|
glTexCoord2f (0, inbuf->height);
|
||||||
|
glVertex3f (-1.0, 1.0, 0);
|
||||||
|
glTexCoord2f (inbuf->width, inbuf->height);
|
||||||
|
glVertex3f (1.0, 1.0, 0);
|
||||||
|
glEnd ();
|
||||||
|
|
||||||
|
glFlush ();
|
||||||
|
|
||||||
|
glMatrixMode (GL_COLOR);
|
||||||
|
glLoadIdentity ();
|
||||||
|
glPixelTransferf (GL_POST_COLOR_MATRIX_RED_SCALE, 1.0);
|
||||||
|
glPixelTransferf (GL_POST_COLOR_MATRIX_RED_BIAS, 0);
|
||||||
|
glPixelTransferf (GL_POST_COLOR_MATRIX_GREEN_BIAS, 0);
|
||||||
|
glPixelTransferf (GL_POST_COLOR_MATRIX_BLUE_BIAS, 0);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
|
@ -522,19 +522,13 @@ 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 (src->display, GST_VIDEO_FORMAT_RGBx,
|
outbuf = gst_gl_buffer_new (src->display, GST_GL_BUFFER_FORMAT_RGB,
|
||||||
src->width, src->height);
|
src->width, src->height);
|
||||||
gst_buffer_set_caps (GST_BUFFER (outbuf),
|
gst_buffer_set_caps (GST_BUFFER (outbuf),
|
||||||
GST_PAD_CAPS (GST_BASE_SRC_PAD (psrc)));
|
GST_PAD_CAPS (GST_BASE_SRC_PAD (psrc)));
|
||||||
|
|
||||||
gst_gl_display_lock (outbuf->display);
|
gst_gl_display_lock (outbuf->display);
|
||||||
|
|
||||||
/* FIXME: This should be part of buffer creation */
|
|
||||||
glGenTextures (1, &outbuf->texture);
|
|
||||||
glBindTexture (GL_TEXTURE_RECTANGLE_ARB, outbuf->texture);
|
|
||||||
glTexImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA,
|
|
||||||
outbuf->width, outbuf->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
|
|
||||||
|
|
||||||
glGenFramebuffersEXT (1, &fbo);
|
glGenFramebuffersEXT (1, &fbo);
|
||||||
glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, fbo);
|
glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, fbo);
|
||||||
|
|
||||||
|
|
|
@ -50,7 +50,8 @@ struct _GstGLUpload
|
||||||
/* < private > */
|
/* < private > */
|
||||||
|
|
||||||
GstGLDisplay *display;
|
GstGLDisplay *display;
|
||||||
GstVideoFormat format;
|
GstVideoFormat video_format;
|
||||||
|
GstGLBufferFormat format;
|
||||||
int width;
|
int width;
|
||||||
int height;
|
int height;
|
||||||
|
|
||||||
|
@ -77,10 +78,14 @@ GST_STATIC_PAD_TEMPLATE ("src",
|
||||||
);
|
);
|
||||||
|
|
||||||
static GstStaticPadTemplate gst_gl_upload_sink_pad_template =
|
static GstStaticPadTemplate gst_gl_upload_sink_pad_template =
|
||||||
GST_STATIC_PAD_TEMPLATE ("sink",
|
GST_STATIC_PAD_TEMPLATE ("sink",
|
||||||
GST_PAD_SINK,
|
GST_PAD_SINK,
|
||||||
GST_PAD_ALWAYS,
|
GST_PAD_ALWAYS,
|
||||||
GST_STATIC_CAPS (GST_VIDEO_CAPS_RGBx)
|
GST_STATIC_CAPS (GST_VIDEO_CAPS_RGBx ";"
|
||||||
|
GST_VIDEO_CAPS_BGRx ";"
|
||||||
|
GST_VIDEO_CAPS_xRGB ";"
|
||||||
|
GST_VIDEO_CAPS_xBGR ";"
|
||||||
|
GST_VIDEO_CAPS_YUV ("{ YUY2, UYVY, AYUV, YV12, I420 }"))
|
||||||
);
|
);
|
||||||
|
|
||||||
enum
|
enum
|
||||||
|
@ -178,7 +183,7 @@ gst_gl_upload_reset (GstGLUpload * upload)
|
||||||
g_object_unref (upload->display);
|
g_object_unref (upload->display);
|
||||||
upload->display = NULL;
|
upload->display = NULL;
|
||||||
}
|
}
|
||||||
upload->format = GST_VIDEO_FORMAT_RGBx;
|
upload->format = GST_GL_BUFFER_FORMAT_RGB;
|
||||||
upload->peek = FALSE;
|
upload->peek = FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -187,7 +192,7 @@ gst_gl_upload_start (GstGLUpload * upload)
|
||||||
{
|
{
|
||||||
gboolean ret;
|
gboolean ret;
|
||||||
|
|
||||||
upload->format = GST_VIDEO_FORMAT_RGBx;
|
upload->format = GST_GL_BUFFER_FORMAT_RGB;
|
||||||
upload->display = gst_gl_display_new ();
|
upload->display = gst_gl_display_new ();
|
||||||
ret = gst_gl_display_connect (upload->display, NULL);
|
ret = gst_gl_display_connect (upload->display, NULL);
|
||||||
|
|
||||||
|
@ -206,7 +211,7 @@ static gboolean
|
||||||
gst_gl_upload_sink_setcaps (GstPad * pad, GstCaps * caps)
|
gst_gl_upload_sink_setcaps (GstPad * pad, GstCaps * caps)
|
||||||
{
|
{
|
||||||
GstGLUpload *upload;
|
GstGLUpload *upload;
|
||||||
GstVideoFormat format;
|
GstVideoFormat video_format;
|
||||||
int height;
|
int height;
|
||||||
int width;
|
int width;
|
||||||
gboolean ret;
|
gboolean ret;
|
||||||
|
@ -214,15 +219,15 @@ gst_gl_upload_sink_setcaps (GstPad * pad, GstCaps * caps)
|
||||||
|
|
||||||
upload = GST_GL_UPLOAD (gst_pad_get_parent (pad));
|
upload = GST_GL_UPLOAD (gst_pad_get_parent (pad));
|
||||||
|
|
||||||
ret = gst_video_format_parse_caps (caps, &format, &width, &height);
|
ret = gst_video_format_parse_caps (caps, &video_format, &width, &height);
|
||||||
if (!ret)
|
if (!ret)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
upload->format = format;
|
upload->video_format = video_format;
|
||||||
upload->width = width;
|
upload->width = width;
|
||||||
upload->height = height;
|
upload->height = height;
|
||||||
|
|
||||||
GST_ERROR ("setcaps %d %d %d", format, width, height);
|
GST_DEBUG ("setcaps %d %d %d", video_format, width, height);
|
||||||
|
|
||||||
srccaps = gst_caps_new_simple ("video/x-raw-gl",
|
srccaps = gst_caps_new_simple ("video/x-raw-gl",
|
||||||
"width", G_TYPE_INT, width, "height", G_TYPE_INT, height, NULL);
|
"width", G_TYPE_INT, width, "height", G_TYPE_INT, height, NULL);
|
||||||
|
@ -240,8 +245,9 @@ gst_gl_upload_chain (GstPad * pad, GstBuffer * buf)
|
||||||
|
|
||||||
upload = GST_GL_UPLOAD (gst_pad_get_parent (pad));
|
upload = GST_GL_UPLOAD (gst_pad_get_parent (pad));
|
||||||
|
|
||||||
outbuf = gst_gl_buffer_new (upload->display, upload->format,
|
outbuf = gst_gl_buffer_new_from_data (upload->display,
|
||||||
upload->width, upload->height);
|
upload->video_format, upload->width, upload->height,
|
||||||
|
GST_BUFFER_DATA (buf));
|
||||||
|
|
||||||
gst_buffer_copy_metadata (GST_BUFFER (outbuf), buf,
|
gst_buffer_copy_metadata (GST_BUFFER (outbuf), buf,
|
||||||
GST_BUFFER_COPY_TIMESTAMPS | GST_BUFFER_COPY_FLAGS);
|
GST_BUFFER_COPY_TIMESTAMPS | GST_BUFFER_COPY_FLAGS);
|
||||||
|
@ -249,7 +255,6 @@ gst_gl_upload_chain (GstPad * pad, GstBuffer * buf)
|
||||||
|
|
||||||
GST_DEBUG ("uploading %p size %d", GST_BUFFER_DATA (buf),
|
GST_DEBUG ("uploading %p size %d", GST_BUFFER_DATA (buf),
|
||||||
GST_BUFFER_SIZE (buf));
|
GST_BUFFER_SIZE (buf));
|
||||||
gst_gl_buffer_upload (outbuf, GST_BUFFER_DATA (buf));
|
|
||||||
gst_buffer_unref (buf);
|
gst_buffer_unref (buf);
|
||||||
|
|
||||||
if (upload->peek) {
|
if (upload->peek) {
|
||||||
|
|
|
@ -34,7 +34,8 @@
|
||||||
|
|
||||||
GType gst_gl_upload_get_type (void);
|
GType gst_gl_upload_get_type (void);
|
||||||
GType gst_gl_download_get_type (void);
|
GType gst_gl_download_get_type (void);
|
||||||
GType gst_gl_filter_get_type (void);
|
GType gst_gl_filter_example_get_type (void);
|
||||||
|
GType gst_gl_convert_get_type (void);
|
||||||
GType gst_gl_test_src_get_type (void);
|
GType gst_gl_test_src_get_type (void);
|
||||||
|
|
||||||
|
|
||||||
|
@ -56,8 +57,12 @@ plugin_init (GstPlugin * plugin)
|
||||||
GST_RANK_NONE, gst_gl_download_get_type ())) {
|
GST_RANK_NONE, gst_gl_download_get_type ())) {
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
if (!gst_element_register (plugin, "glfilter",
|
if (!gst_element_register (plugin, "glfilterexample",
|
||||||
GST_RANK_NONE, gst_gl_filter_get_type ())) {
|
GST_RANK_NONE, gst_gl_filter_example_get_type ())) {
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
if (!gst_element_register (plugin, "glconvert",
|
||||||
|
GST_RANK_NONE, gst_gl_convert_get_type ())) {
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
if (!gst_element_register (plugin, "gltestsrc",
|
if (!gst_element_register (plugin, "gltestsrc",
|
||||||
|
|
Loading…
Reference in a new issue